diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e00d1ac --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,87 @@ +name: CI + +on: + push: + branches: [main, "maint/*"] + pull_request: + branches: [main, "maint/*"] + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + BUILDMODE: [CIBUILDWHEEL, ASTROPY] + + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-python@v2 + + - name: Set up QEMU + if: ${{ matrix.os == 'ubuntu-latest' && matrix.BUILDMODE == 'CIBUILDWHEEL' }} + id: qemu + uses: docker/setup-qemu-action@v1 + + - name: Setup Conda Environment + if: ${{ matrix.BUILDMODE == 'ASTROPY' }} + uses: conda-incubator/setup-miniconda@v2 + with: + miniforge-variant: Mambaforge + miniforge-version: latest + use-mamba: true + python-version: ${{ matrix.python-version }} + environment-file: ci/environment.yaml + activate-environment: test-environment + + - name: Run tests + if: ${{ matrix.BUILDMODE == 'ASTROPY' }} + shell: bash -l {0} + run: | + pip install -e . + python selftest.py + - name: Build wheel + if: ${{ matrix.BUILDMODE == 'CIBUILDWHEEL' }} + env: + CIBW_TEST_COMMAND: python {project}/selftest.py + CIBW_BEFORE_BUILD_LINUX: yum install -y freetype-devel + CIBW_SKIP: "*-musllinux*" + CIBW_TEST_REQUIRES: numpy pillow pytest + CIBW_ARCHS_LINUX: auto aarch64 + run: | + python -m pip install cibuildwheel + cibuildwheel --output-dir wheelhouse + - name: upload + if: ${{ matrix.BUILDMODE == 'CIBUILDWHEEL' }} + uses: actions/upload-artifact@v2 + with: + name: wheelhouse + path: "wheelhouse/*.whl" + + publish: + if: startsWith(github.ref, 'refs/tags') + runs-on: ubuntu-latest + needs: + - build + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-python@v2 + + - name: sdist + run: python setup.py sdist + + - name: download + uses: actions/download-artifact@v2 + + - name: Install dependencies + run: python -m pip install twine + + - name: Publish wheels to PyPI + env: + TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} + TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + run: | + python -m twine upload --skip-existing dist/*.tar.gz + python -m twine upload --skip-existing wheelhouse/*.whl diff --git a/.gitignore b/.gitignore index 25c47a0..804a39d 100644 --- a/.gitignore +++ b/.gitignore @@ -167,3 +167,4 @@ ENV/ .idea/ # distutils MANIFEST MANIFEST +.pytest_cache diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 5342919..0000000 --- a/.travis.yml +++ /dev/null @@ -1,46 +0,0 @@ -language: generic -env: - global: - - NUMPY_VERSION=stable - - MAIN_CMD='python setup.py' - - CONDA_DEPENDENCIES='sphinx pillow coveralls coverage pytest' - - SETUP_XVFB=False - - EVENT_TYPE='push pull_request' - - SETUP_CMD='test' - - CONDA_CHANNELS='conda-forge' - - CONDA_CHANNEL_PRIORITY='True' - - CIBW_TEST_REQUIRES='numpy pillow pytest' - - CIBW_TEST_COMMAND='python {project}/selftest.py' - - CIBW_BEFORE_BUILD_LINUX='yum install -y freetype-devel' - - TWINE_USERNAME='dhoese' - # TWINE_PASSWORD - - secure: Cmwxk41Nd+cu7l5Qhl7ZyCuwYg8WGCT53wqFBZMKIDZkNPVsnfaE8G9s1ZPTlpyoMEL5TioYTVjbjPXZD8M3z7OHHicXRP3mO53PrUDsETEl6/gR2h309ux/cWdOGgLd9s6CKT6wjtCT8Clft1cz61Y2ABOEtyTq3mrvPI0PyxE= -matrix: - include: - - os: linux - env: - - BUILDMODE=ASTROPY - - PYTHON_VERSION=2.7 - - os: linux - env: - - BUILDMODE=ASTROPY - - PYTHON_VERSION=3.7 - - os: osx - env: - - BUILDMODE=ASTROPY - - PYTHON_VERSION=2.7 - - os: osx - env: - - BUILDMODE=ASTROPY - - PYTHON_VERSION=3.7 - - sudo: required - language: python - services: - - docker - env: BUILDMODE=CIBUILDWHEEL - - os: osx - env: BUILDMODE=CIBUILDWHEEL -install: -- source ci/travis-install.sh -script: -- ci/travis-build.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 53cbe19..e5ce6e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # The aggdraw Library +## Version 1.3.13 + +- Rebuild for python 3.10 wheels and switch to GitHub Actions + +## Version 1.3.12 + +- Rebuild for python 3.8 wheels + ## Version 1.3.11 - Force rebuild to fix freetype linking in OSX wheels diff --git a/MANIFEST.in b/MANIFEST.in index 17b2c5c..4d231ec 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,4 @@ include aggdraw.cxx include LICENSE.txt -recursive-include agg2 *.cpp -recursive-include agg2 *.h +recursive-include agg *.cpp +recursive-include agg *.h diff --git a/README.rst b/README.rst index f570127..d24446c 100644 --- a/README.rst +++ b/README.rst @@ -2,11 +2,25 @@ The aggdraw module ================== -.. image:: https://travis-ci.org/pytroll/aggdraw.svg?branch=master - :target: https://travis-ci.org/pytroll/aggdraw +.. image:: https://github.com/pytroll/aggdraw/workflows/CI/badge.svg?branch=main + :target: https://github.com/pytroll/aggdraw/actions?query=workflow%3A%22CI%22 -.. image:: https://ci.appveyor.com/api/projects/status/9g7qt1kitwxya7u4/branch/master?svg=true - :target: https://ci.appveyor.com/project/pytroll/aggdraw/branch/master +---------------------------------------------------------------------- +agg 2.4 notes +---------------------------------------------------------------------- + +aggdraw was ported to agg 2.4 and extended by + +Dov Grobgeld +2016-05-30 Mon + +This port is planned for released as 1.4.0, but currently produces different +results from previous versions and the causes of these differences have not +been tracked down. + +---------------------------------------------------------------------- +Original README +---------------------------------------------------------------------- A high-quality graphics engine for PIL, based on Maxim Shemanarev's Anti-Grain Geometry library (from http://antigrain.com). diff --git a/agg2/font_freetype/agg_font_freetype.cpp b/agg/font_freetype/agg_font_freetype.cpp similarity index 68% rename from agg2/font_freetype/agg_font_freetype.cpp rename to agg/font_freetype/agg_font_freetype.cpp index 0af06f6..0afe9ab 100644 --- a/agg2/font_freetype/agg_font_freetype.cpp +++ b/agg/font_freetype/agg_font_freetype.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -14,7 +14,8 @@ //---------------------------------------------------------------------------- -#include +#include +#include #include "agg_font_freetype.h" #include "agg_bitset_iterator.h" #include "agg_renderer_scanline.h" @@ -122,31 +123,38 @@ namespace agg return ~crc; } - //------------------------------------------------------------------------ - inline double conv_coord_64(int v) + static inline int dbl_to_plain_fx(double d) { - return double(v) / 64.0; + return int(d * 65536.0); } + //------------------------------------------------------------------------ + static inline double int26p6_to_dbl(int p) + { + return double(p) / 64.0; + } //------------------------------------------------------------------------ - inline int conv_coord_none(int v) + static inline int dbl_to_int26p6(double p) { - return v; + return int(p * 64.0 + 0.5); } //------------------------------------------------------------------------ - template + template bool decompose_ft_outline(const FT_Outline& outline, bool flip_y, - PathStorage& path, - ConvCoord conv) + const trans_affine& mtx, + PathStorage& path) { + typedef typename PathStorage::value_type value_type; + FT_Vector v_last; FT_Vector v_control; FT_Vector v_start; + double x1, y1, x2, y2, x3, y3; FT_Vector* point; FT_Vector* limit; @@ -201,7 +209,12 @@ namespace agg tags--; } - path.move_to(conv(v_start.x), flip_y ? -conv(v_start.y) : conv(v_start.y)); + x1 = int26p6_to_dbl(v_start.x); + y1 = int26p6_to_dbl(v_start.y); + if(flip_y) y1 = -y1; + mtx.transform(&x1, &y1); + path.move_to(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1))); while(point < limit) { @@ -213,7 +226,13 @@ namespace agg { case FT_CURVE_TAG_ON: // emit a single line_to { - path.line_to(conv(point->x), flip_y ? -conv(point->y) : conv(point->y)); + x1 = int26p6_to_dbl(point->x); + y1 = int26p6_to_dbl(point->y); + if(flip_y) y1 = -y1; + mtx.transform(&x1, &y1); + path.line_to(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1))); + //path.line_to(conv(point->x), flip_y ? -conv(point->y) : conv(point->y)); continue; } @@ -237,10 +256,17 @@ namespace agg if(tag == FT_CURVE_TAG_ON) { - path.curve3(conv(v_control.x), - flip_y ? -conv(v_control.y) : conv(v_control.y), - conv(vec.x), - flip_y ? -conv(vec.y) : conv(vec.y)); + x1 = int26p6_to_dbl(v_control.x); + y1 = int26p6_to_dbl(v_control.y); + x2 = int26p6_to_dbl(vec.x); + y2 = int26p6_to_dbl(vec.y); + if(flip_y) { y1 = -y1; y2 = -y2; } + mtx.transform(&x1, &y1); + mtx.transform(&x2, &y2); + path.curve3(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1)), + value_type(dbl_to_int26p6(x2)), + value_type(dbl_to_int26p6(y2))); continue; } @@ -249,18 +275,43 @@ namespace agg v_middle.x = (v_control.x + vec.x) / 2; v_middle.y = (v_control.y + vec.y) / 2; - path.curve3(conv(v_control.x), - flip_y ? -conv(v_control.y) : conv(v_control.y), - conv(v_middle.x), - flip_y ? -conv(v_middle.y) : conv(v_middle.y)); + x1 = int26p6_to_dbl(v_control.x); + y1 = int26p6_to_dbl(v_control.y); + x2 = int26p6_to_dbl(v_middle.x); + y2 = int26p6_to_dbl(v_middle.y); + if(flip_y) { y1 = -y1; y2 = -y2; } + mtx.transform(&x1, &y1); + mtx.transform(&x2, &y2); + path.curve3(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1)), + value_type(dbl_to_int26p6(x2)), + value_type(dbl_to_int26p6(y2))); + + //path.curve3(conv(v_control.x), + // flip_y ? -conv(v_control.y) : conv(v_control.y), + // conv(v_middle.x), + // flip_y ? -conv(v_middle.y) : conv(v_middle.y)); v_control = vec; goto Do_Conic; } - path.curve3(conv(v_control.x), - flip_y ? -conv(v_control.y) : conv(v_control.y), - conv(v_start.x), - flip_y ? -conv(v_start.y) : conv(v_start.y)); + + x1 = int26p6_to_dbl(v_control.x); + y1 = int26p6_to_dbl(v_control.y); + x2 = int26p6_to_dbl(v_start.x); + y2 = int26p6_to_dbl(v_start.y); + if(flip_y) { y1 = -y1; y2 = -y2; } + mtx.transform(&x1, &y1); + mtx.transform(&x2, &y2); + path.curve3(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1)), + value_type(dbl_to_int26p6(x2)), + value_type(dbl_to_int26p6(y2))); + + //path.curve3(conv(v_control.x), + // flip_y ? -conv(v_control.y) : conv(v_control.y), + // conv(v_start.x), + // flip_y ? -conv(v_start.y) : conv(v_start.y)); goto Close; } @@ -288,21 +339,55 @@ namespace agg vec.x = point->x; vec.y = point->y; - path.curve4(conv(vec1.x), - flip_y ? -conv(vec1.y) : conv(vec1.y), - conv(vec2.x), - flip_y ? -conv(vec2.y) : conv(vec2.y), - conv(vec.x), - flip_y ? -conv(vec.y) : conv(vec.y)); + x1 = int26p6_to_dbl(vec1.x); + y1 = int26p6_to_dbl(vec1.y); + x2 = int26p6_to_dbl(vec2.x); + y2 = int26p6_to_dbl(vec2.y); + x3 = int26p6_to_dbl(vec.x); + y3 = int26p6_to_dbl(vec.y); + if(flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; } + mtx.transform(&x1, &y1); + mtx.transform(&x2, &y2); + mtx.transform(&x3, &y3); + path.curve4(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1)), + value_type(dbl_to_int26p6(x2)), + value_type(dbl_to_int26p6(y2)), + value_type(dbl_to_int26p6(x3)), + value_type(dbl_to_int26p6(y3))); + + //path.curve4(conv(vec1.x), + // flip_y ? -conv(vec1.y) : conv(vec1.y), + // conv(vec2.x), + // flip_y ? -conv(vec2.y) : conv(vec2.y), + // conv(vec.x), + // flip_y ? -conv(vec.y) : conv(vec.y)); continue; } - path.curve4(conv(vec1.x), - flip_y ? -conv(vec1.y) : conv(vec1.y), - conv(vec2.x), - flip_y ? -conv(vec2.y) : conv(vec2.y), - conv(v_start.x), - flip_y ? -conv(v_start.y) : conv(v_start.y)); + x1 = int26p6_to_dbl(vec1.x); + y1 = int26p6_to_dbl(vec1.y); + x2 = int26p6_to_dbl(vec2.x); + y2 = int26p6_to_dbl(vec2.y); + x3 = int26p6_to_dbl(v_start.x); + y3 = int26p6_to_dbl(v_start.y); + if(flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; } + mtx.transform(&x1, &y1); + mtx.transform(&x2, &y2); + mtx.transform(&x3, &y3); + path.curve4(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1)), + value_type(dbl_to_int26p6(x2)), + value_type(dbl_to_int26p6(y2)), + value_type(dbl_to_int26p6(x3)), + value_type(dbl_to_int26p6(y3))); + + //path.curve4(conv(vec1.x), + // flip_y ? -conv(vec1.y) : conv(vec1.y), + // conv(vec2.x), + // flip_y ? -conv(vec2.y) : conv(vec2.y), + // conv(v_start.x), + // flip_y ? -conv(v_start.y) : conv(v_start.y)); goto Close; } } @@ -331,7 +416,7 @@ namespace agg const int8u* buf = (const int8u*)bitmap.buffer; int pitch = bitmap.pitch; sl.reset(x, x + bitmap.width); - storage.prepare(bitmap.width + 2); + storage.prepare(); if(flip_y) { buf += bitmap.pitch * (bitmap.rows - 1); @@ -372,7 +457,7 @@ namespace agg const int8u* buf = (const int8u*)bitmap.buffer; int pitch = bitmap.pitch; sl.reset(x, x + bitmap.width); - storage.prepare(bitmap.width + 2); + storage.prepare(); if(flip_y) { buf += bitmap.pitch * (bitmap.rows - 1); @@ -466,10 +551,6 @@ namespace agg m_scanlines_bin(), m_rasterizer() { - m_matrix.xx = 0x10000L; - m_matrix.xy = 0; - m_matrix.yx = 0; - m_matrix.yy = 0x10000L; m_curves16.approximation_scale(4.0); m_curves32.approximation_scale(4.0); m_last_error = FT_Init_FreeType(&m_library); @@ -492,16 +573,39 @@ namespace agg unsigned i; for(i = 0; i < m_num_faces; ++i) { - if(strcmp(face_name, m_face_names[i]) == 0) return i; + if(std::strcmp(face_name, m_face_names[i]) == 0) return i; } return -1; } + //------------------------------------------------------------------------ + double font_engine_freetype_base::ascender() const + { + if(m_cur_face) + { + return m_cur_face->ascender * height() / m_cur_face->height; + } + return 0.0; + } + + //------------------------------------------------------------------------ + double font_engine_freetype_base::descender() const + { + if(m_cur_face) + { + return m_cur_face->descender * height() / m_cur_face->height; + } + return 0.0; + } + + //------------------------------------------------------------------------ bool font_engine_freetype_base::load_font(const char* font_name, unsigned face_index, - glyph_rendering ren_type) + glyph_rendering ren_type, + const char* font_mem, + const long font_mem_size) { bool ret = false; @@ -521,23 +625,35 @@ namespace agg { delete [] m_face_names[0]; FT_Done_Face(m_faces[0]); - memcpy(m_faces, + std::memcpy(m_faces, m_faces + 1, (m_max_faces - 1) * sizeof(FT_Face)); - memcpy(m_face_names, + std::memcpy(m_face_names, m_face_names + 1, (m_max_faces - 1) * sizeof(char*)); m_num_faces = m_max_faces - 1; } - m_last_error = FT_New_Face(m_library, - font_name, - face_index, - &m_faces[m_num_faces]); + if (font_mem && font_mem_size) + { + m_last_error = FT_New_Memory_Face(m_library, + (const FT_Byte*)font_mem, + font_mem_size, + face_index, + &m_faces[m_num_faces]); + } + else + { + m_last_error = FT_New_Face(m_library, + font_name, + face_index, + &m_faces[m_num_faces]); + } + if(m_last_error == 0) { - m_face_names[m_num_faces] = new char [strlen(font_name) + 1]; - strcpy(m_face_names[m_num_faces], font_name); + m_face_names[m_num_faces] = new char [std::strlen(font_name) + 1]; + std::strcpy(m_face_names[m_num_faces], font_name); m_cur_face = m_faces[m_num_faces]; m_name = m_face_names[m_num_faces]; ++m_num_faces; @@ -554,7 +670,7 @@ namespace agg if(m_last_error == 0) { ret = true; - + switch(ren_type) { case glyph_ren_native_mono: @@ -598,8 +714,7 @@ namespace agg } break; } - - update_transform(); + update_signature(); } } return ret; @@ -628,13 +743,14 @@ namespace agg } //------------------------------------------------------------------------ - bool font_engine_freetype_base::char_map(FT_Encoding char_map) + bool font_engine_freetype_base::char_map(FT_Encoding map) { if(m_cur_face) { - m_last_error = FT_Select_Charmap(m_cur_face, m_char_map); + m_last_error = FT_Select_Charmap(m_cur_face, map); if(m_last_error == 0) { + m_char_map = map; update_signature(); return true; } @@ -666,59 +782,20 @@ namespace agg return false; } - //------------------------------------------------------------------------ - void font_engine_freetype_base::update_transform() - { - FT_Matrix mtx = m_matrix; - - if(m_flip_y) - { - mtx.xy = -mtx.xy; - mtx.yy = -mtx.yy; - } - + void font_engine_freetype_base::hinting(bool h) + { + m_hinting = h; if(m_cur_face) { - FT_Vector pen; - pen.x = 0; - pen.y = 0; - FT_Set_Transform(m_cur_face, &mtx, &pen); update_signature(); } } - //------------------------------------------------------------------------ - void font_engine_freetype_base::transform(const trans_affine& mtx) - { - double m[6]; - mtx.store_to(m); - - m_matrix.xx = long( m[0] * 0x10000L); - m_matrix.xy = long(-m[1] * 0x10000L); - m_matrix.yx = long(-m[2] * 0x10000L); - m_matrix.yy = long( m[3] * 0x10000L); - update_transform(); - } - - - //------------------------------------------------------------------------ - void font_engine_freetype_base::transform(double xx, double xy, - double yx, double yy) - { - m_matrix.xx = long( xx * 0x10000L); - m_matrix.xy = long(-xy * 0x10000L); - m_matrix.yx = long(-yx * 0x10000L); - m_matrix.yy = long( yy * 0x10000L); - update_transform(); - } - - - //------------------------------------------------------------------------ - void font_engine_freetype_base::hinting(bool h) + void font_engine_freetype_base::flip_y(bool f) { - m_hinting = h; + m_flip_y = f; if(m_cur_face) { update_signature(); @@ -726,12 +803,12 @@ namespace agg } //------------------------------------------------------------------------ - void font_engine_freetype_base::flip_y(bool f) - { - m_flip_y = f; + void font_engine_freetype_base::transform(const trans_affine& affine) + { + m_affine = affine; if(m_cur_face) { - update_transform(); + update_signature(); } } @@ -740,7 +817,7 @@ namespace agg { if(m_cur_face && m_name) { - unsigned name_len = strlen(m_name); + unsigned name_len = std::strlen(m_name); if(name_len > m_name_len) { delete [] m_signature; @@ -753,17 +830,17 @@ namespace agg m_glyph_rendering == glyph_ren_agg_mono || m_glyph_rendering == glyph_ren_agg_gray8) { - unsigned char gamma_table[rasterizer_scanline_aa<>::aa_num]; + unsigned char gamma_table[rasterizer_scanline_aa<>::aa_scale]; unsigned i; - for(i = 0; i < rasterizer_scanline_aa<>::aa_num; ++i) + for(i = 0; i < rasterizer_scanline_aa<>::aa_scale; ++i) { gamma_table[i] = m_rasterizer.apply_gamma(i); } gamma_hash = calc_crc32(gamma_table, sizeof(gamma_table)); } - sprintf(m_signature, - "%s,%u,%d,%d,%d:%dx%d,%d,%d,%d,%d,%d,%d,%08X", + std::sprintf(m_signature, + "%s,%u,%d,%d,%d:%dx%d,%d,%d,%08X", m_name, m_char_map, m_face_index, @@ -771,13 +848,25 @@ namespace agg m_resolution, m_height, m_width, - m_matrix.xx, - m_matrix.xy, - m_matrix.yx, - m_matrix.yy, int(m_hinting), int(m_flip_y), gamma_hash); + if(m_glyph_rendering == glyph_ren_outline || + m_glyph_rendering == glyph_ren_agg_mono || + m_glyph_rendering == glyph_ren_agg_gray8) + { + double mtx[6]; + char buf[100]; + m_affine.store_to(mtx); + std::sprintf(buf, ",%08X%08X%08X%08X%08X%08X", + dbl_to_plain_fx(mtx[0]), + dbl_to_plain_fx(mtx[1]), + dbl_to_plain_fx(mtx[2]), + dbl_to_plain_fx(mtx[3]), + dbl_to_plain_fx(mtx[4]), + dbl_to_plain_fx(mtx[5])); + std::strcat(m_signature, buf); + } ++m_change_stamp; } } @@ -813,9 +902,6 @@ namespace agg //------------------------------------------------------------------------ bool font_engine_freetype_base::prepare_glyph(unsigned glyph_code) { - bool flip = false; - - m_glyph_index = FT_Get_Char_Index(m_cur_face, glyph_code); m_last_error = FT_Load_Glyph(m_cur_face, m_glyph_index, @@ -831,19 +917,19 @@ namespace agg { decompose_ft_bitmap_mono(m_cur_face->glyph->bitmap, m_cur_face->glyph->bitmap_left, - flip ? -m_cur_face->glyph->bitmap_top : - m_cur_face->glyph->bitmap_top, - flip, + m_flip_y ? -m_cur_face->glyph->bitmap_top : + m_cur_face->glyph->bitmap_top, + m_flip_y, m_scanline_bin, m_scanlines_bin); m_bounds.x1 = m_scanlines_bin.min_x(); m_bounds.y1 = m_scanlines_bin.min_y(); - m_bounds.x2 = m_scanlines_bin.max_x(); - m_bounds.y2 = m_scanlines_bin.max_y(); + m_bounds.x2 = m_scanlines_bin.max_x() + 1; + m_bounds.y2 = m_scanlines_bin.max_y() + 1; m_data_size = m_scanlines_bin.byte_size(); m_data_type = glyph_data_mono; - m_advance_x = double(m_cur_face->glyph->advance.x) / 64.0; - m_advance_y = double(m_cur_face->glyph->advance.y) / 64.0; + m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); + m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); return true; } break; @@ -855,20 +941,20 @@ namespace agg { decompose_ft_bitmap_gray8(m_cur_face->glyph->bitmap, m_cur_face->glyph->bitmap_left, - flip ? -m_cur_face->glyph->bitmap_top : - m_cur_face->glyph->bitmap_top, - flip, + m_flip_y ? -m_cur_face->glyph->bitmap_top : + m_cur_face->glyph->bitmap_top, + m_flip_y, m_rasterizer, m_scanline_aa, m_scanlines_aa); m_bounds.x1 = m_scanlines_aa.min_x(); m_bounds.y1 = m_scanlines_aa.min_y(); - m_bounds.x2 = m_scanlines_aa.max_x(); - m_bounds.y2 = m_scanlines_aa.max_y(); + m_bounds.x2 = m_scanlines_aa.max_x() + 1; + m_bounds.y2 = m_scanlines_aa.max_y() + 1; m_data_size = m_scanlines_aa.byte_size(); m_data_type = glyph_data_gray8; - m_advance_x = double(m_cur_face->glyph->advance.x) / 64.0; - m_advance_y = double(m_cur_face->glyph->advance.y) / 64.0; + m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); + m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); return true; } break; @@ -881,9 +967,9 @@ namespace agg { m_path32.remove_all(); if(decompose_ft_outline(m_cur_face->glyph->outline, - flip, - m_path32, - conv_coord_none)) + m_flip_y, + m_affine, + m_path32)) { rect_d bnd = m_path32.bounding_rect(); m_data_size = m_path32.byte_size(); @@ -892,8 +978,9 @@ namespace agg m_bounds.y1 = int(floor(bnd.y1)); m_bounds.x2 = int(ceil(bnd.x2)); m_bounds.y2 = int(ceil(bnd.y2)); - m_advance_x = double(m_cur_face->glyph->advance.x) / 64.0; - m_advance_y = double(m_cur_face->glyph->advance.y) / 64.0; + m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); + m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); + m_affine.transform(&m_advance_x, &m_advance_y); return true; } } @@ -901,9 +988,9 @@ namespace agg { m_path16.remove_all(); if(decompose_ft_outline(m_cur_face->glyph->outline, - flip, - m_path16, - conv_coord_none)) + m_flip_y, + m_affine, + m_path16)) { rect_d bnd = m_path16.bounding_rect(); m_data_size = m_path16.byte_size(); @@ -912,8 +999,9 @@ namespace agg m_bounds.y1 = int(floor(bnd.y1)); m_bounds.x2 = int(ceil(bnd.x2)); m_bounds.y2 = int(ceil(bnd.y2)); - m_advance_x = double(m_cur_face->glyph->advance.x) / 64.0; - m_advance_y = double(m_cur_face->glyph->advance.y) / 64.0; + m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); + m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); + m_affine.transform(&m_advance_x, &m_advance_y); return true; } } @@ -928,30 +1016,31 @@ namespace agg { m_path32.remove_all(); decompose_ft_outline(m_cur_face->glyph->outline, - flip, - m_path32, - conv_coord_none); + m_flip_y, + m_affine, + m_path32); m_rasterizer.add_path(m_curves32); } else { m_path16.remove_all(); decompose_ft_outline(m_cur_face->glyph->outline, - flip, - m_path16, - conv_coord_none); + m_flip_y, + m_affine, + m_path16); m_rasterizer.add_path(m_curves16); } - m_scanlines_bin.prepare(1); // Remove all + m_scanlines_bin.prepare(); // Remove all render_scanlines(m_rasterizer, m_scanline_bin, m_scanlines_bin); m_bounds.x1 = m_scanlines_bin.min_x(); m_bounds.y1 = m_scanlines_bin.min_y(); - m_bounds.x2 = m_scanlines_bin.max_x(); - m_bounds.y2 = m_scanlines_bin.max_y(); + m_bounds.x2 = m_scanlines_bin.max_x() + 1; + m_bounds.y2 = m_scanlines_bin.max_y() + 1; m_data_size = m_scanlines_bin.byte_size(); m_data_type = glyph_data_mono; - m_advance_x = double(m_cur_face->glyph->advance.x) / 64.0; - m_advance_y = double(m_cur_face->glyph->advance.y) / 64.0; + m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); + m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); + m_affine.transform(&m_advance_x, &m_advance_y); return true; } return false; @@ -965,30 +1054,31 @@ namespace agg { m_path32.remove_all(); decompose_ft_outline(m_cur_face->glyph->outline, - flip, - m_path32, - conv_coord_none); + m_flip_y, + m_affine, + m_path32); m_rasterizer.add_path(m_curves32); } else { m_path16.remove_all(); decompose_ft_outline(m_cur_face->glyph->outline, - flip, - m_path16, - conv_coord_none); + m_flip_y, + m_affine, + m_path16); m_rasterizer.add_path(m_curves16); } - m_scanlines_aa.prepare(1); // Remove all + m_scanlines_aa.prepare(); // Remove all render_scanlines(m_rasterizer, m_scanline_aa, m_scanlines_aa); m_bounds.x1 = m_scanlines_aa.min_x(); m_bounds.y1 = m_scanlines_aa.min_y(); - m_bounds.x2 = m_scanlines_aa.max_x(); - m_bounds.y2 = m_scanlines_aa.max_y(); + m_bounds.x2 = m_scanlines_aa.max_x() + 1; + m_bounds.y2 = m_scanlines_aa.max_y() + 1; m_data_size = m_scanlines_aa.byte_size(); m_data_type = glyph_data_gray8; - m_advance_x = double(m_cur_face->glyph->advance.x) / 64.0; - m_advance_y = double(m_cur_face->glyph->advance.y) / 64.0; + m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); + m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); + m_affine.transform(&m_advance_x, &m_advance_y); return true; } return false; @@ -1007,6 +1097,7 @@ namespace agg { switch(m_data_type) { + default: return; case glyph_data_mono: m_scanlines_bin.serialize(data); break; case glyph_data_gray8: m_scanlines_aa.serialize(data); break; case glyph_data_outline: @@ -1019,6 +1110,7 @@ namespace agg m_path16.serialize(data); } break; + case glyph_data_invalid: break; } } } @@ -1034,9 +1126,17 @@ namespace agg FT_Vector delta; FT_Get_Kerning(m_cur_face, first, second, FT_KERNING_DEFAULT, &delta); - FT_Vector_Transform(&delta, &m_matrix); - *x += double(delta.x) / 64.0; - *y += double(delta.y) / 64.0; + double dx = int26p6_to_dbl(delta.x); + double dy = int26p6_to_dbl(delta.y); + if(m_glyph_rendering == glyph_ren_outline || + m_glyph_rendering == glyph_ren_agg_mono || + m_glyph_rendering == glyph_ren_agg_gray8) + { + m_affine.transform_2x2(&dx, &dy); + } + *x += dx; + *y += dy; + return true; } return false; diff --git a/agg2/font_freetype/agg_font_freetype.h b/agg/font_freetype/agg_font_freetype.h similarity index 93% rename from agg2/font_freetype/agg_font_freetype.h rename to agg/font_freetype/agg_font_freetype.h index 91ee552..263e352 100644 --- a/agg2/font_freetype/agg_font_freetype.h +++ b/agg/font_freetype/agg_font_freetype.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -31,8 +31,8 @@ #include "agg_path_storage_integer.h" #include "agg_rasterizer_scanline_aa.h" #include "agg_conv_curve.h" -#include "agg_trans_affine.h" #include "agg_font_cache_manager.h" +#include "agg_trans_affine.h" namespace agg { @@ -55,15 +55,15 @@ namespace agg // Set font parameters //-------------------------------------------------------------------- void resolution(unsigned dpi); - bool load_font(const char* font_name, unsigned face_index, glyph_rendering ren_type); + bool load_font(const char* font_name, unsigned face_index, glyph_rendering ren_type, + const char* font_mem = 0, const long font_mem_size = 0); bool attach(const char* file_name); bool char_map(FT_Encoding map); bool height(double h); bool width(double w); - void transform(const trans_affine& mtx); - void transform(double xx, double xy, double yx, double yy); void hinting(bool h); void flip_y(bool f); + void transform(const trans_affine& affine); // Set Gamma //-------------------------------------------------------------------- @@ -79,8 +79,10 @@ namespace agg const char* name() const { return m_name; } unsigned num_faces() const; FT_Encoding char_map() const { return m_char_map; } - double height() const { return double(m_height) / 64.0; } - double width() const { return double(m_width) / 64.0; } + double height() const { return double(m_height) / 64.0; } + double width() const { return double(m_width) / 64.0; } + double ascender() const; + double descender() const; bool hinting() const { return m_hinting; } bool flip_y() const { return m_flip_y; } @@ -94,12 +96,13 @@ namespace agg unsigned glyph_index() const { return m_glyph_index; } unsigned data_size() const { return m_data_size; } glyph_data_type data_type() const { return m_data_type; } - const rect& bounds() const { return m_bounds; } + const rect_i& bounds() const { return m_bounds; } double advance_x() const { return m_advance_x; } double advance_y() const { return m_advance_y; } void write_glyph_to(int8u* data) const; bool add_kerning(unsigned first, unsigned second, double* x, double* y); + FT_Face m_cur_face; // handle to the current face object private: font_engine_freetype_base(const font_engine_freetype_base&); @@ -107,7 +110,6 @@ namespace agg void update_char_size(); void update_signature(); - void update_transform(); int find_face(const char* face_name) const; bool m_flag32; @@ -120,7 +122,6 @@ namespace agg char* m_signature; unsigned m_height; unsigned m_width; - FT_Matrix m_matrix; bool m_hinting; bool m_flip_y; bool m_library_initialized; @@ -129,17 +130,15 @@ namespace agg char** m_face_names; unsigned m_num_faces; unsigned m_max_faces; - public: - FT_Face m_cur_face; // handle to the current face object - private: int m_resolution; glyph_rendering m_glyph_rendering; unsigned m_glyph_index; unsigned m_data_size; glyph_data_type m_data_type; - rect m_bounds; + rect_i m_bounds; double m_advance_x; double m_advance_y; + trans_affine m_affine; path_storage_integer m_path16; path_storage_integer m_path32; diff --git a/agg/font_freetype/agg_font_freetype2.cpp b/agg/font_freetype/agg_font_freetype2.cpp new file mode 100644 index 0000000..9f76317 --- /dev/null +++ b/agg/font_freetype/agg_font_freetype2.cpp @@ -0,0 +1,877 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#include +#include +#include +#include "agg_font_freetype2.h" +#include "agg_bitset_iterator.h" +#include "agg_renderer_scanline.h" + + +namespace agg { +namespace fman { + + //------------------------------------------------------------------------------ + // + // This code implements the AUTODIN II polynomial + // The variable corresponding to the macro argument "crc" should + // be an unsigned long. + // Oroginal code by Spencer Garrett + // + + // generated using the AUTODIN II polynomial + // x^32 + x^26 + x^23 + x^22 + x^16 + + // x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1 + // + //------------------------------------------------------------------------------ + + static const unsigned crc32tab[256] = + { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, + }; + + + //------------------------------------------------------------------------------ + + static unsigned calc_crc32(const unsigned char* buf, unsigned size) + { + unsigned crc = (unsigned)~0; + const unsigned char* p; + unsigned len = 0; + unsigned nr = size; + + for (len += nr, p = buf; nr--; ++p) + { + crc = (crc >> 8) ^ crc32tab[(crc ^ *p) & 0xff]; + } + return ~crc; + } + + //------------------------------------------------------------------------ + static inline int dbl_to_plain_fx(double d) + { + return int(d * 65536.0); + } + + //------------------------------------------------------------------------ + static inline double int26p6_to_dbl(int p) + { + return double(p) / 64.0; + } + + //------------------------------------------------------------------------ + static inline int dbl_to_int26p6(double p) + { + return int(p * 64.0 + 0.5); + } + + + //------------------------------------------------------------------------ + template + bool decompose_ft_outline(const FT_Outline& outline, + bool flip_y, + const trans_affine& mtx, + PathStorage& path) + { + typedef typename PathStorage::value_type value_type; + + FT_Vector v_last; + FT_Vector v_control; + FT_Vector v_start; + double x1, y1, x2, y2, x3, y3; + + FT_Vector* point; + FT_Vector* limit; + char* tags; + + int n; // index of contour in outline + int first; // index of first point in contour + char tag; // current point's state + + first = 0; + + for(n = 0; n < outline.n_contours; n++) + { + int last; // index of last point in contour + + last = outline.contours[n]; + limit = outline.points + last; + + v_start = outline.points[first]; + v_last = outline.points[last]; + + v_control = v_start; + + point = outline.points + first; + tags = outline.tags + first; + tag = FT_CURVE_TAG(tags[0]); + + // A contour cannot start with a cubic control point! + if(tag == FT_CURVE_TAG_CUBIC) return false; + + // check first point to determine origin + if( tag == FT_CURVE_TAG_CONIC) + { + // first point is conic control. Yes, this happens. + if(FT_CURVE_TAG(outline.tags[last]) == FT_CURVE_TAG_ON) + { + // start at last point if it is on the curve + v_start = v_last; + limit--; + } + else + { + // if both first and last points are conic, + // start at their middle and record its position + // for closure + v_start.x = (v_start.x + v_last.x) / 2; + v_start.y = (v_start.y + v_last.y) / 2; + + v_last = v_start; + } + point--; + tags--; + } + + x1 = int26p6_to_dbl(v_start.x); + y1 = int26p6_to_dbl(v_start.y); + if(flip_y) y1 = -y1; + mtx.transform(&x1, &y1); + path.move_to(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1))); + + while(point < limit) + { + point++; + tags++; + + tag = FT_CURVE_TAG(tags[0]); + switch(tag) + { + case FT_CURVE_TAG_ON: // emit a single line_to + { + x1 = int26p6_to_dbl(point->x); + y1 = int26p6_to_dbl(point->y); + if(flip_y) y1 = -y1; + mtx.transform(&x1, &y1); + path.line_to(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1))); + //path.line_to(conv(point->x), flip_y ? -conv(point->y) : conv(point->y)); + continue; + } + + case FT_CURVE_TAG_CONIC: // consume conic arcs + { + v_control.x = point->x; + v_control.y = point->y; + + Do_Conic: + if(point < limit) + { + FT_Vector vec; + FT_Vector v_middle; + + point++; + tags++; + tag = FT_CURVE_TAG(tags[0]); + + vec.x = point->x; + vec.y = point->y; + + if(tag == FT_CURVE_TAG_ON) + { + x1 = int26p6_to_dbl(v_control.x); + y1 = int26p6_to_dbl(v_control.y); + x2 = int26p6_to_dbl(vec.x); + y2 = int26p6_to_dbl(vec.y); + if(flip_y) { y1 = -y1; y2 = -y2; } + mtx.transform(&x1, &y1); + mtx.transform(&x2, &y2); + path.curve3(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1)), + value_type(dbl_to_int26p6(x2)), + value_type(dbl_to_int26p6(y2))); + continue; + } + + if(tag != FT_CURVE_TAG_CONIC) return false; + + v_middle.x = (v_control.x + vec.x) / 2; + v_middle.y = (v_control.y + vec.y) / 2; + + x1 = int26p6_to_dbl(v_control.x); + y1 = int26p6_to_dbl(v_control.y); + x2 = int26p6_to_dbl(v_middle.x); + y2 = int26p6_to_dbl(v_middle.y); + if(flip_y) { y1 = -y1; y2 = -y2; } + mtx.transform(&x1, &y1); + mtx.transform(&x2, &y2); + path.curve3(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1)), + value_type(dbl_to_int26p6(x2)), + value_type(dbl_to_int26p6(y2))); + + //path.curve3(conv(v_control.x), + // flip_y ? -conv(v_control.y) : conv(v_control.y), + // conv(v_middle.x), + // flip_y ? -conv(v_middle.y) : conv(v_middle.y)); + + v_control = vec; + goto Do_Conic; + } + + x1 = int26p6_to_dbl(v_control.x); + y1 = int26p6_to_dbl(v_control.y); + x2 = int26p6_to_dbl(v_start.x); + y2 = int26p6_to_dbl(v_start.y); + if(flip_y) { y1 = -y1; y2 = -y2; } + mtx.transform(&x1, &y1); + mtx.transform(&x2, &y2); + path.curve3(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1)), + value_type(dbl_to_int26p6(x2)), + value_type(dbl_to_int26p6(y2))); + + //path.curve3(conv(v_control.x), + // flip_y ? -conv(v_control.y) : conv(v_control.y), + // conv(v_start.x), + // flip_y ? -conv(v_start.y) : conv(v_start.y)); + goto Close; + } + + default: // FT_CURVE_TAG_CUBIC + { + FT_Vector vec1, vec2; + + if(point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC) + { + return false; + } + + vec1.x = point[0].x; + vec1.y = point[0].y; + vec2.x = point[1].x; + vec2.y = point[1].y; + + point += 2; + tags += 2; + + if(point <= limit) + { + FT_Vector vec; + + vec.x = point->x; + vec.y = point->y; + + x1 = int26p6_to_dbl(vec1.x); + y1 = int26p6_to_dbl(vec1.y); + x2 = int26p6_to_dbl(vec2.x); + y2 = int26p6_to_dbl(vec2.y); + x3 = int26p6_to_dbl(vec.x); + y3 = int26p6_to_dbl(vec.y); + if(flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; } + mtx.transform(&x1, &y1); + mtx.transform(&x2, &y2); + mtx.transform(&x3, &y3); + path.curve4(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1)), + value_type(dbl_to_int26p6(x2)), + value_type(dbl_to_int26p6(y2)), + value_type(dbl_to_int26p6(x3)), + value_type(dbl_to_int26p6(y3))); + + //path.curve4(conv(vec1.x), + // flip_y ? -conv(vec1.y) : conv(vec1.y), + // conv(vec2.x), + // flip_y ? -conv(vec2.y) : conv(vec2.y), + // conv(vec.x), + // flip_y ? -conv(vec.y) : conv(vec.y)); + continue; + } + + x1 = int26p6_to_dbl(vec1.x); + y1 = int26p6_to_dbl(vec1.y); + x2 = int26p6_to_dbl(vec2.x); + y2 = int26p6_to_dbl(vec2.y); + x3 = int26p6_to_dbl(v_start.x); + y3 = int26p6_to_dbl(v_start.y); + if(flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; } + mtx.transform(&x1, &y1); + mtx.transform(&x2, &y2); + mtx.transform(&x3, &y3); + path.curve4(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1)), + value_type(dbl_to_int26p6(x2)), + value_type(dbl_to_int26p6(y2)), + value_type(dbl_to_int26p6(x3)), + value_type(dbl_to_int26p6(y3))); + + //path.curve4(conv(vec1.x), + // flip_y ? -conv(vec1.y) : conv(vec1.y), + // conv(vec2.x), + // flip_y ? -conv(vec2.y) : conv(vec2.y), + // conv(v_start.x), + // flip_y ? -conv(v_start.y) : conv(v_start.y)); + goto Close; + } + } + } + + path.close_polygon(); + + Close: + first = last + 1; + } + + return true; + } + + + + //------------------------------------------------------------------------ + template + void decompose_ft_bitmap_mono(const FT_Bitmap& bitmap, + int x, int y, + bool flip_y, + Scanline& sl, + ScanlineStorage& storage) + { + int i; + const int8u* buf = (const int8u*)bitmap.buffer; + int pitch = bitmap.pitch; + sl.reset(x, x + bitmap.width); + storage.prepare(); + if(flip_y) + { + buf += bitmap.pitch * (bitmap.rows - 1); + y += bitmap.rows; + pitch = -pitch; + } + for(i = 0; i < bitmap.rows; i++) + { + sl.reset_spans(); + bitset_iterator bits(buf, 0); + int j; + for(j = 0; j < bitmap.width; j++) + { + if(bits.bit()) sl.add_cell(x + j, cover_full); + ++bits; + } + buf += pitch; + if(sl.num_spans()) + { + sl.finalize(y - i - 1); + storage.render(sl); + } + } + } + + + + //------------------------------------------------------------------------ + template + void decompose_ft_bitmap_gray8(const FT_Bitmap& bitmap, + int x, int y, + bool flip_y, + Rasterizer& ras, + Scanline& sl, + ScanlineStorage& storage) + { + int i, j; + const int8u* buf = (const int8u*)bitmap.buffer; + int pitch = bitmap.pitch; + sl.reset(x, x + bitmap.width); + storage.prepare(); + if(flip_y) + { + buf += bitmap.pitch * (bitmap.rows - 1); + y += bitmap.rows; + pitch = -pitch; + } + for(i = 0; i < bitmap.rows; i++) + { + sl.reset_spans(); + const int8u* p = buf; + for(j = 0; j < bitmap.width; j++) + { + if(*p) sl.add_cell(x + j, ras.apply_gamma(*p)); + ++p; + } + buf += pitch; + if(sl.num_spans()) + { + sl.finalize(y - i - 1); + storage.render(sl); + } + } + } + + + + + + + + + //------------------------------------------------------------------------ + bool font_engine_freetype_base::loaded_face::prepare_glyph(unsigned glyph_code, prepared_glyph *prepared) const + { + bool success=false; + prepared->glyph_index = FT_Get_Char_Index(m_ft_face, glyph_code); + int error = FT_Load_Glyph(m_ft_face, + prepared->glyph_index, + m_hinting ? FT_LOAD_DEFAULT : FT_LOAD_NO_HINTING); + // m_hinting ? FT_LOAD_FORCE_AUTOHINT : FT_LOAD_NO_HINTING); + if(error == 0) + { + prepared->glyph_code=glyph_code; + switch(m_rendering) + { + case glyph_ren_native_mono: + error = FT_Render_Glyph(m_ft_face->glyph, FT_RENDER_MODE_MONO); + if(error == 0) + { + decompose_ft_bitmap_mono(m_ft_face->glyph->bitmap, + m_ft_face->glyph->bitmap_left, + m_flip_y ? -m_ft_face->glyph->bitmap_top : + m_ft_face->glyph->bitmap_top, + m_flip_y, + m_engine.m_scanline_bin, + m_engine.m_scanlines_bin); + prepared->bounds.x1 = m_engine.m_scanlines_bin.min_x(); + prepared->bounds.y1 = m_engine.m_scanlines_bin.min_y(); + prepared->bounds.x2 = m_engine.m_scanlines_bin.max_x() + 1; + prepared->bounds.y2 = m_engine.m_scanlines_bin.max_y() + 1; + prepared->data_size = m_engine.m_scanlines_bin.byte_size(); + prepared->data_type = glyph_data_mono; + prepared->advance_x = int26p6_to_dbl(m_ft_face->glyph->advance.x); + prepared->advance_y = int26p6_to_dbl(m_ft_face->glyph->advance.y); + success=true; + } + break; + + + case glyph_ren_native_gray8: + error = FT_Render_Glyph(m_ft_face->glyph, FT_RENDER_MODE_NORMAL); + if(error == 0) + { + decompose_ft_bitmap_gray8(m_ft_face->glyph->bitmap, + m_ft_face->glyph->bitmap_left, + m_flip_y ? -m_ft_face->glyph->bitmap_top : + m_ft_face->glyph->bitmap_top, + m_flip_y, + m_engine.m_rasterizer, + m_engine.m_scanline_aa, + m_engine.m_scanlines_aa); + prepared->data_size = m_engine.m_scanlines_aa.byte_size(); + prepared->data_type = glyph_data_gray8; + prepared->advance_x = int26p6_to_dbl(m_ft_face->glyph->advance.x); + prepared->advance_y = int26p6_to_dbl(m_ft_face->glyph->advance.y); + if( m_ft_face->glyph->bitmap.rows!=0 && + m_ft_face->glyph->bitmap.width!=0 ) + { + prepared->bounds.x1 = m_engine.m_scanlines_aa.min_x(); + prepared->bounds.y1 = m_engine.m_scanlines_aa.min_y(); + prepared->bounds.x2 = m_engine.m_scanlines_aa.max_x() + 1; + prepared->bounds.y2 = m_engine.m_scanlines_aa.max_y() + 1; + } + else + { + prepared->bounds.x1 = 0; + prepared->bounds.y1 = 0; + prepared->bounds.x2 = prepared->advance_x; + prepared->bounds.y2 = 0; + } + success=true; + } + break; + + + case glyph_ren_outline: + if(error == 0) + { + if(m_engine.m_flag32) + { + m_engine.m_path32.remove_all(); + if(decompose_ft_outline(m_ft_face->glyph->outline, + m_flip_y, + m_affine, + m_engine.m_path32)) + { + rect_d bnd = m_engine.m_path32.bounding_rect(); + prepared->data_size = m_engine.m_path32.byte_size(); + prepared->data_type = glyph_data_outline; + prepared->bounds.x1 = int(floor(bnd.x1)); + prepared->bounds.y1 = int(floor(bnd.y1)); + prepared->bounds.x2 = int(ceil(bnd.x2)); + prepared->bounds.y2 = int(ceil(bnd.y2)); + prepared->advance_x = int26p6_to_dbl(m_ft_face->glyph->advance.x); + prepared->advance_y = int26p6_to_dbl(m_ft_face->glyph->advance.y); + m_affine.transform(&prepared->advance_x, &prepared->advance_y); + success=true; + } + } + else + { + m_engine.m_path16.remove_all(); + if(decompose_ft_outline(m_ft_face->glyph->outline, + m_flip_y, + m_affine, + m_engine.m_path16)) + { + rect_d bnd = m_engine.m_path16.bounding_rect(); + prepared->data_size = m_engine.m_path16.byte_size(); + prepared->data_type = glyph_data_outline; + prepared->bounds.x1 = int(floor(bnd.x1)); + prepared->bounds.y1 = int(floor(bnd.y1)); + prepared->bounds.x2 = int(ceil(bnd.x2)); + prepared->bounds.y2 = int(ceil(bnd.y2)); + prepared->advance_x = int26p6_to_dbl(m_ft_face->glyph->advance.x); + prepared->advance_y = int26p6_to_dbl(m_ft_face->glyph->advance.y); + m_affine.transform(&prepared->advance_x, &prepared->advance_y); + success=true; + } + } + } + break; + + case glyph_ren_agg_mono: + if(error == 0) + { + m_engine.m_rasterizer.reset(); + if(m_engine.m_flag32) + { + m_engine.m_path32.remove_all(); + decompose_ft_outline(m_ft_face->glyph->outline, + m_flip_y, + m_affine, + m_engine.m_path32); + m_engine.m_rasterizer.add_path(m_engine.m_curves32); + } + else + { + m_engine.m_path16.remove_all(); + decompose_ft_outline(m_ft_face->glyph->outline, + m_flip_y, + m_affine, + m_engine.m_path16); + m_engine.m_rasterizer.add_path(m_engine.m_curves16); + } + m_engine.m_scanlines_bin.prepare(); // Remove all + render_scanlines(m_engine.m_rasterizer, m_engine.m_scanline_bin, m_engine.m_scanlines_bin); + prepared->bounds.x1 = m_engine.m_scanlines_bin.min_x(); + prepared->bounds.y1 = m_engine.m_scanlines_bin.min_y(); + prepared->bounds.x2 = m_engine.m_scanlines_bin.max_x() + 1; + prepared->bounds.y2 = m_engine.m_scanlines_bin.max_y() + 1; + prepared->data_size = m_engine.m_scanlines_bin.byte_size(); + prepared->data_type = glyph_data_mono; + prepared->advance_x = int26p6_to_dbl(m_ft_face->glyph->advance.x); + prepared->advance_y = int26p6_to_dbl(m_ft_face->glyph->advance.y); + m_affine.transform(&prepared->advance_x, &prepared->advance_y); + success=true; + } + break; + + + case glyph_ren_agg_gray8: + if(error == 0) + { + m_engine.m_rasterizer.reset(); + if(m_engine.m_flag32) + { + m_engine.m_path32.remove_all(); + decompose_ft_outline(m_ft_face->glyph->outline, + m_flip_y, + m_affine, + m_engine.m_path32); + m_engine.m_rasterizer.add_path(m_engine.m_curves32); + } + else + { + m_engine.m_path16.remove_all(); + decompose_ft_outline(m_ft_face->glyph->outline, + m_flip_y, + m_affine, + m_engine.m_path16); + m_engine.m_rasterizer.add_path(m_engine.m_curves16); + } + m_engine.m_scanlines_aa.prepare(); // Remove all + render_scanlines(m_engine.m_rasterizer, m_engine.m_scanline_aa, m_engine.m_scanlines_aa); + prepared->bounds.x1 = m_engine.m_scanlines_aa.min_x(); + prepared->bounds.y1 = m_engine.m_scanlines_aa.min_y(); + prepared->bounds.x2 = m_engine.m_scanlines_aa.max_x() + 1; + prepared->bounds.y2 = m_engine.m_scanlines_aa.max_y() + 1; + prepared->data_size = m_engine.m_scanlines_aa.byte_size(); + prepared->data_type = glyph_data_gray8; + prepared->advance_x = int26p6_to_dbl(m_ft_face->glyph->advance.x); + prepared->advance_y = int26p6_to_dbl(m_ft_face->glyph->advance.y); + m_affine.transform(&prepared->advance_x, &prepared->advance_y); + success=true; + } + break; + } + } + return success; + } + + //------------------------------------------------------------------------ + void font_engine_freetype_base::loaded_face::write_glyph_to(prepared_glyph *prepared, int8u* data) const + { + if(data && prepared->data_size) + { + switch(prepared->data_type) + { + default: return; + case glyph_data_mono: m_engine.m_scanlines_bin.serialize(data); break; + case glyph_data_gray8: m_engine.m_scanlines_aa.serialize(data); break; + case glyph_data_outline: + if(m_engine.m_flag32) + { + m_engine.m_path32.serialize(data); + } + else + { + m_engine.m_path16.serialize(data); + } + break; + case glyph_data_invalid: break; + } + } + } + + //------------------------------------------------------------------------ + bool font_engine_freetype_base::loaded_face::add_kerning( + unsigned first, unsigned second, double* x, double* y) + { + bool success=false; + if(first && second && FT_HAS_KERNING(m_ft_face)) + { + FT_Vector delta; + int error= FT_Get_Kerning(m_ft_face, first, second, + FT_KERNING_DEFAULT, &delta); + if( error==0 ) + { + double dx = int26p6_to_dbl(delta.x); + double dy = int26p6_to_dbl(delta.y); + if( m_rendering == glyph_ren_outline || + m_rendering == glyph_ren_agg_mono || + m_rendering == glyph_ren_agg_gray8) + { + m_affine.transform_2x2(&dx, &dy); + } + *x += dx; + *y += dy; + } + success=true; + } + return success; + } + + //------------------------------------------------------------------------ + void font_engine_freetype_base::loaded_face::set_face_name() + { + if( !stricmp(m_ft_face->style_name,"Regular") ) + { + std::size_t len=std::strlen(m_ft_face->family_name)+1; + m_face_name=new char[len]; + std::strcpy(m_face_name, m_ft_face->family_name); + } + else + { + std::size_t len=std::strlen(m_ft_face->family_name)+1+std::strlen(m_ft_face->style_name)+1; + m_face_name=new char[len]; + std::sprintf( m_face_name, "%s %s", m_ft_face->family_name, m_ft_face->style_name ); + } + } + + + + + + + + + + //------------------------------------------------------------------------ + font_engine_freetype_base::~font_engine_freetype_base() + { + if(m_library_initialized) FT_Done_FreeType(m_library); + } + + //------------------------------------------------------------------------ + + static FT_Error ft_init_freeType( FT_Library *alibrary, FT_Memory memory ) + { + FT_Error error; + + error = FT_New_Library( memory, alibrary ); + if ( error ) + { }// FT_Done_Memory( memory ); + else + FT_Add_Default_Modules( *alibrary ); + + return error; + } + + font_engine_freetype_base::font_engine_freetype_base( bool flag32, void *ftMemory) + :m_flag32(flag32) + ,m_last_error(0) + ,m_library_initialized(false) + ,m_path16() + ,m_path32() + ,m_curves16(m_path16) + ,m_curves32(m_path32) + ,m_scanline_aa() + ,m_scanline_bin() + ,m_scanlines_aa() + ,m_scanlines_bin() + ,m_rasterizer() + { + m_curves16.approximation_scale(4.0); + m_curves32.approximation_scale(4.0); + m_last_error = ft_init_freeType(&m_library,FT_Memory(ftMemory)); + if(m_last_error == 0) m_library_initialized = true; + } + + //------------------------------------------------------------------------ + font_engine_freetype_base::loaded_face *font_engine_freetype_base::load_face( + const void* buffer, std::size_t bytes) + { + loaded_face *face=0; + if(m_library_initialized) + { + FT_Face ft_face; + int error = FT_New_Memory_Face( + m_library, + (const FT_Byte*)buffer, + bytes, + 0, + &ft_face ); + if( error==0 ) + { + face=create_loaded_face(ft_face); + } + } + return face; + } + //------------------------------------------------------------------------ + font_engine_freetype_base::loaded_face *font_engine_freetype_base::load_face_file( + const char* file_name ) + { + loaded_face *face=0; + if(m_library_initialized) + { + FT_Face ft_face; + int error = FT_New_Face( + m_library, + file_name, + 0, + &ft_face ); + if( error==0 ) + { + face=create_loaded_face(ft_face); + } + } + return face; + } + + //------------------------------------------------------------------------ + font_engine_freetype_base::loaded_face *font_engine_freetype_base::create_loaded_face(FT_Face ft_face) + { + loaded_face *face=new loaded_face( *this, ft_face ); + + return face; + } + + //------------------------------------------------------------------------ + /* + bool font_engine_freetype_base::attach(const char* file_name) + { + if(m_cur_face) + { + m_last_error = FT_Attach_File(m_cur_face, file_name); + return m_last_error == 0; + } + return false; + } + */ +} +} + + diff --git a/agg/font_freetype/agg_font_freetype2.h b/agg/font_freetype/agg_font_freetype2.h new file mode 100644 index 0000000..60e5f22 --- /dev/null +++ b/agg/font_freetype/agg_font_freetype2.h @@ -0,0 +1,331 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// See implementation agg_font_freetype.cpp +// +//---------------------------------------------------------------------------- + +#ifndef AGG_FONT_FREETYPE_INCLUDED +#define AGG_FONT_FREETYPE_INCLUDED + +#include +#include FT_FREETYPE_H + + +#include +#include "agg_scanline_storage_aa.h" +#include "agg_scanline_storage_bin.h" +#include "agg_scanline_u.h" +#include "agg_scanline_bin.h" +#include "agg_path_storage_integer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_conv_curve.h" +#include "agg_font_cache_manager.h" +#include "agg_font_cache_manager2.h" +#include "agg_trans_affine.h" + +namespace agg { +namespace fman { + + + //-----------------------------------------------font_engine_freetype_base + class font_engine_freetype_base + { + public: + struct prepared_glyph + { + unsigned glyph_code; + unsigned glyph_index; + unsigned data_size; + glyph_data_type data_type; + rect_i bounds; + double advance_x; + double advance_y; + }; + + class loaded_face + { + public: + loaded_face( font_engine_freetype_base &engine, FT_Face face ) + : m_engine( engine ) + , m_ft_face( face ) + , m_dpi( 0 ) + , m_height( 0 ) + , m_width( 0 ) + , m_rendering( glyph_ren_native_gray8 ) + , m_hinting( false ) + , m_flip_y( true ) + , m_char_map( FT_ENCODING_NONE ) + { + set_face_name(); + } + + ~loaded_face() + { + FT_Done_Face( m_ft_face); + delete[] m_face_name; + } + + unsigned num_faces() const + { + return m_ft_face->num_faces; + } + + const char *name() const + { + return m_face_name; + } + + unsigned resolution() const + { + return m_dpi; + } + + double height() const + { + return m_height; + } + + double width() const + { + return m_width; + } + + double ascent() const + { + return m_ft_face->ascender*height()/m_ft_face->height; + } + + double descent() const + { + return m_ft_face->descender*height()/m_ft_face->height; + } + + double ascent_b() const + { + return m_ft_face->bbox.yMax*height()/m_ft_face->height; + } + + double descent_b() const + { + return m_ft_face->bbox.yMin*height()/m_ft_face->height; + } + + bool hinting() const + { + return m_hinting; + } + + bool flip_y() const + { + return m_flip_y; + } + + const trans_affine &transform() const + { + return m_affine; + } + + FT_Encoding char_map() const + { + return m_char_map; + } + + void set_hinting( bool h ) + { + m_hinting=h; + } + + /* + void set_resolution(int dpi) + { m_dpi=dpi; update_char_size(); } + void set_height( double h ) + { m_height=int(h*64.0); update_char_size(); } + void set_width( double w ) + { m_width=int(w*64.0); update_char_size(); } + void set_flip_y(bool f) + { m_flip_y=f; } + void set_transform(const trans_affine& affine) + { m_affine=affine; } + int set_char_map(FT_Encoding char_map) + { FT_Select_Charmap(m_ft_face, char_map); } + */ + void select_instance( + double height, + double width, + bool hinting, + glyph_rendering rendering ) + { + rendering=capable_rendering(rendering); + + if( m_height != height || + m_width != width || + m_hinting != hinting || + m_rendering != rendering ) + { + m_height = height; + m_width = width; + m_hinting = hinting; + m_rendering = rendering; + update_char_size(); + } + } + + glyph_rendering capable_rendering( glyph_rendering rendering ) const + { + switch(rendering) + { + case glyph_ren_native_mono: + case glyph_ren_native_gray8: + break; + + case glyph_ren_outline: + if(!FT_IS_SCALABLE(m_ft_face)) + rendering = glyph_ren_native_gray8; + break; + + case glyph_ren_agg_mono: + if(!FT_IS_SCALABLE(m_ft_face)) + rendering = glyph_ren_native_mono; + break; + + case glyph_ren_agg_gray8: + if(!FT_IS_SCALABLE(m_ft_face)) + rendering = glyph_ren_native_gray8; + break; + }; + return rendering; + } + + void update_char_size() + { + if( m_dpi ) + FT_Set_Char_Size( m_ft_face, int(m_width*64), int(m_height*64), m_dpi, m_dpi ); + else + FT_Set_Pixel_Sizes( m_ft_face, int(m_width), int(m_height) ); + } + + bool prepare_glyph(unsigned glyph_code, prepared_glyph *prepared ) const; + bool add_kerning(unsigned first, unsigned second, double* x, double* y); + void write_glyph_to(prepared_glyph *prepared, int8u* data) const; + + private: + void set_face_name(); + + loaded_face(const loaded_face &); + loaded_face &operator=(const loaded_face &); + + private: + font_engine_freetype_base &m_engine; + FT_Face m_ft_face; + char *m_face_name; + int m_dpi; + double m_height; + double m_width; + glyph_rendering m_rendering; + bool m_hinting; + bool m_flip_y; + trans_affine m_affine; + FT_Encoding m_char_map; + }; + + //-------------------------------------------------------------------- + typedef serialized_scanlines_adaptor_aa gray8_adaptor_type; + typedef serialized_scanlines_adaptor_bin mono_adaptor_type; + typedef scanline_storage_aa8 scanlines_aa_type; + typedef scanline_storage_bin scanlines_bin_type; + + //-------------------------------------------------------------------- + ~font_engine_freetype_base(); + font_engine_freetype_base(bool flag32, void *ftMemory=0); + + // Load families and faces + //-------------------------------------------------------------------- + loaded_face *load_face(const void* buffer, std::size_t bytes); + loaded_face *load_face_file(const char* file_name); + loaded_face *create_loaded_face(FT_Face ft_face); // internal + void unload_face(loaded_face *face); + + // Set Gamma + //-------------------------------------------------------------------- + template void gamma(const GammaF& f) + { + m_rasterizer.gamma(f); + } + + private: + font_engine_freetype_base(const font_engine_freetype_base&); + const font_engine_freetype_base& operator = (const font_engine_freetype_base&); + + bool m_flag32; + int m_last_error; + bool m_library_initialized; + FT_Library m_library; // handle to library + + path_storage_integer m_path16; + path_storage_integer m_path32; + conv_curve > m_curves16; + conv_curve > m_curves32; + scanline_u8 m_scanline_aa; + scanline_bin m_scanline_bin; + scanlines_aa_type m_scanlines_aa; + scanlines_bin_type m_scanlines_bin; + rasterizer_scanline_aa<> m_rasterizer; + }; + + + + + //------------------------------------------------font_engine_freetype_int16 + // This class uses values of type int16 (10.6 format) for the vector cache. + // The vector cache is compact, but when rendering glyphs of height + // more that 200 there integer overflow can occur. + // + class font_engine_freetype_int16 : public font_engine_freetype_base + { + public: + typedef serialized_integer_path_adaptor path_adaptor_type; + typedef font_engine_freetype_base::gray8_adaptor_type gray8_adaptor_type; + typedef font_engine_freetype_base::mono_adaptor_type mono_adaptor_type; + typedef font_engine_freetype_base::scanlines_aa_type scanlines_aa_type; + typedef font_engine_freetype_base::scanlines_bin_type scanlines_bin_type; + + font_engine_freetype_int16(void *ftMemory = 0) : + font_engine_freetype_base(false, ftMemory) {} + }; + + //------------------------------------------------font_engine_freetype_int32 + // This class uses values of type int32 (26.6 format) for the vector cache. + // The vector cache is twice larger than in font_engine_freetype_int16, + // but it allows you to render glyphs of very large sizes. + // + class font_engine_freetype_int32 : public font_engine_freetype_base + { + public: + typedef serialized_integer_path_adaptor path_adaptor_type; + typedef font_engine_freetype_base::gray8_adaptor_type gray8_adaptor_type; + typedef font_engine_freetype_base::mono_adaptor_type mono_adaptor_type; + typedef font_engine_freetype_base::scanlines_aa_type scanlines_aa_type; + typedef font_engine_freetype_base::scanlines_bin_type scanlines_bin_type; + + font_engine_freetype_int32(void *ftMemory = 0) : + font_engine_freetype_base(true, ftMemory) {} + }; + + +} +} + +#endif diff --git a/agg/include/Makefile.am b/agg/include/Makefile.am new file mode 100644 index 0000000..6399aed --- /dev/null +++ b/agg/include/Makefile.am @@ -0,0 +1,49 @@ +SUBDIRS = ctrl util platform + +aggincludedir = $(includedir)/agg2 +agginclude_HEADERS = \ + agg_alpha_mask_u8.h agg_glyph_raster_bin.h agg_span_allocator.h \ + agg_arc.h agg_gsv_text.h agg_span_converter.h \ + agg_array.h agg_image_accessors.h agg_span_gouraud.h \ + agg_arrowhead.h agg_image_filters.h agg_span_gouraud_gray.h \ + agg_basics.h agg_line_aa_basics.h agg_span_gouraud_rgba.h \ + agg_bezier_arc.h agg_math.h agg_span_gradient.h \ + agg_bitset_iterator.h agg_blur.h agg_math_stroke.h \ + agg_span_gradient_alpha.h agg_gradient_lut.h \ + agg_bounding_rect.h agg_path_length.h agg_span_image_filter.h \ + agg_bspline.h agg_path_storage.h agg_span_image_filter_gray.h \ + agg_clip_liang_barsky.h agg_path_storage_integer.h agg_span_image_filter_rgb.h \ + agg_color_gray.h agg_pattern_filters_rgba.h agg_span_image_filter_rgba.h \ + agg_color_rgba.h agg_pixfmt_amask_adaptor.h agg_span_interpolator_adaptor.h \ + agg_config.h agg_pixfmt_gray.h agg_span_interpolator_linear.h \ + agg_conv_adaptor_vcgen.h agg_pixfmt_rgb.h agg_span_interpolator_persp.h \ + agg_conv_adaptor_vpgen.h agg_pixfmt_rgb_packed.h agg_span_interpolator_trans.h \ + agg_conv_bspline.h agg_pixfmt_rgba.h agg_pixfmt_transposer.h \ + agg_span_pattern_gray.h \ + agg_conv_clip_polygon.h agg_rasterizer_cells_aa.h agg_span_pattern_rgb.h \ + agg_conv_clip_polyline.h agg_rasterizer_compound_aa.h agg_span_pattern_rgba.h \ + agg_conv_close_polygon.h agg_rasterizer_outline.h agg_span_solid.h \ + agg_conv_concat.h agg_rasterizer_outline_aa.h agg_span_subdiv_adaptor.h \ + agg_conv_contour.h agg_rasterizer_scanline_aa.h agg_trans_affine.h \ + agg_conv_curve.h agg_rasterizer_sl_clip.h agg_trans_bilinear.h \ + agg_conv_dash.h agg_renderer_base.h agg_trans_double_path.h \ + agg_conv_gpc.h agg_renderer_markers.h \ + agg_conv_marker.h agg_renderer_mclip.h agg_trans_perspective.h \ + agg_conv_marker_adaptor.h agg_renderer_outline_aa.h agg_trans_single_path.h \ + agg_conv_segmentator.h agg_renderer_outline_image.h agg_trans_viewport.h \ + agg_conv_shorten_path.h agg_renderer_primitives.h agg_trans_warp_magnifier.h \ + agg_conv_smooth_poly1.h agg_renderer_raster_text.h agg_vcgen_bspline.h \ + agg_conv_stroke.h agg_renderer_scanline.h agg_vcgen_contour.h \ + agg_conv_transform.h agg_rendering_buffer.h agg_vcgen_dash.h \ + agg_conv_unclose_polygon.h agg_rendering_buffer_dynarow.h agg_vcgen_markers_term.h \ + agg_curves.h agg_rounded_rect.h agg_vcgen_smooth_poly1.h \ + agg_scanline_bin.h agg_vcgen_stroke.h \ + agg_dda_line.h agg_scanline_boolean_algebra.h agg_vcgen_vertex_sequence.h \ + agg_ellipse.h agg_scanline_p.h agg_vertex_sequence.h \ + agg_ellipse_bresenham.h agg_scanline_storage_aa.h agg_vpgen_clip_polygon.h \ + agg_embedded_raster_fonts.h agg_scanline_storage_bin.h agg_vpgen_clip_polyline.h \ + agg_font_cache_manager.h agg_scanline_u.h agg_vpgen_segmentator.h \ + agg_gamma_functions.h agg_shorten_path.h \ + agg_gamma_lut.h agg_simul_eq.h \ + agg_font_cache_manager2.h agg_pixfmt_base.h agg_rasterizer_scanline_aa_nogamma.h \ + agg_span_gradient_contour.h agg_span_gradient_image.h diff --git a/agg2/include/agg_alpha_mask_u8.h b/agg/include/agg_alpha_mask_u8.h similarity index 83% rename from agg2/include/agg_alpha_mask_u8.h rename to agg/include/agg_alpha_mask_u8.h index 0b16663..997d2c5 100644 --- a/agg2/include/agg_alpha_mask_u8.h +++ b/agg/include/agg_alpha_mask_u8.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -19,7 +19,7 @@ #ifndef AGG_ALPHA_MASK_U8_INCLUDED #define AGG_ALPHA_MASK_U8_INCLUDED -#include +#include #include "agg_basics.h" #include "agg_rendering_buffer.h" @@ -49,7 +49,7 @@ namespace agg public: typedef int8u cover_type; typedef alpha_mask_u8 self_type; - enum + enum cover_scale_e { cover_shift = 8, cover_none = 0, @@ -57,7 +57,7 @@ namespace agg }; alpha_mask_u8() : m_rbuf(0) {} - alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {} + explicit alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {} void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; } @@ -70,10 +70,10 @@ namespace agg { if(x >= 0 && y >= 0 && x < (int)m_rbuf->width() && - y <= (int)m_rbuf->height()) + y < (int)m_rbuf->height()) { return (cover_type)m_mask_function.calculate( - m_rbuf->row(y) + x * Step + Offset); + m_rbuf->row_ptr(y) + x * Step + Offset); } return 0; } @@ -83,11 +83,11 @@ namespace agg { if(x >= 0 && y >= 0 && x < (int)m_rbuf->width() && - y <= (int)m_rbuf->height()) + y < (int)m_rbuf->height()) { - return (cover_type)((val * + return (cover_type)((cover_full + val * m_mask_function.calculate( - m_rbuf->row(y) + x * Step + Offset)) >> + m_rbuf->row_ptr(y) + x * Step + Offset)) >> cover_shift); } return 0; @@ -105,7 +105,7 @@ namespace agg if(y < 0 || y > ymax) { - memset(dst, 0, num_pix * sizeof(cover_type)); + std::memset(dst, 0, num_pix * sizeof(cover_type)); return; } @@ -114,10 +114,10 @@ namespace agg count += x; if(count <= 0) { - memset(dst, 0, num_pix * sizeof(cover_type)); + std::memset(dst, 0, num_pix * sizeof(cover_type)); return; } - memset(covers, 0, -x * sizeof(cover_type)); + std::memset(covers, 0, -x * sizeof(cover_type)); covers -= x; x = 0; } @@ -128,13 +128,13 @@ namespace agg count -= rest; if(count <= 0) { - memset(dst, 0, num_pix * sizeof(cover_type)); + std::memset(dst, 0, num_pix * sizeof(cover_type)); return; } - memset(covers + count, 0, rest * sizeof(cover_type)); + std::memset(covers + count, 0, rest * sizeof(cover_type)); } - const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { *covers++ = (cover_type)m_mask_function.calculate(mask); @@ -155,7 +155,7 @@ namespace agg if(y < 0 || y > ymax) { - memset(dst, 0, num_pix * sizeof(cover_type)); + std::memset(dst, 0, num_pix * sizeof(cover_type)); return; } @@ -164,10 +164,10 @@ namespace agg count += x; if(count <= 0) { - memset(dst, 0, num_pix * sizeof(cover_type)); + std::memset(dst, 0, num_pix * sizeof(cover_type)); return; } - memset(covers, 0, -x * sizeof(cover_type)); + std::memset(covers, 0, -x * sizeof(cover_type)); covers -= x; x = 0; } @@ -178,16 +178,16 @@ namespace agg count -= rest; if(count <= 0) { - memset(dst, 0, num_pix * sizeof(cover_type)); + std::memset(dst, 0, num_pix * sizeof(cover_type)); return; } - memset(covers + count, 0, rest * sizeof(cover_type)); + std::memset(covers + count, 0, rest * sizeof(cover_type)); } - const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { - *covers = (cover_type)(((*covers) * + *covers = (cover_type)((cover_full + (*covers) * m_mask_function.calculate(mask)) >> cover_shift); ++covers; @@ -207,7 +207,7 @@ namespace agg if(x < 0 || x > xmax) { - memset(dst, 0, num_pix * sizeof(cover_type)); + std::memset(dst, 0, num_pix * sizeof(cover_type)); return; } @@ -216,10 +216,10 @@ namespace agg count += y; if(count <= 0) { - memset(dst, 0, num_pix * sizeof(cover_type)); + std::memset(dst, 0, num_pix * sizeof(cover_type)); return; } - memset(covers, 0, -y * sizeof(cover_type)); + std::memset(covers, 0, -y * sizeof(cover_type)); covers -= y; y = 0; } @@ -230,13 +230,13 @@ namespace agg count -= rest; if(count <= 0) { - memset(dst, 0, num_pix * sizeof(cover_type)); + std::memset(dst, 0, num_pix * sizeof(cover_type)); return; } - memset(covers + count, 0, rest * sizeof(cover_type)); + std::memset(covers + count, 0, rest * sizeof(cover_type)); } - const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { *covers++ = (cover_type)m_mask_function.calculate(mask); @@ -256,7 +256,7 @@ namespace agg if(x < 0 || x > xmax) { - memset(dst, 0, num_pix * sizeof(cover_type)); + std::memset(dst, 0, num_pix * sizeof(cover_type)); return; } @@ -265,10 +265,10 @@ namespace agg count += y; if(count <= 0) { - memset(dst, 0, num_pix * sizeof(cover_type)); + std::memset(dst, 0, num_pix * sizeof(cover_type)); return; } - memset(covers, 0, -y * sizeof(cover_type)); + std::memset(covers, 0, -y * sizeof(cover_type)); covers -= y; y = 0; } @@ -279,16 +279,16 @@ namespace agg count -= rest; if(count <= 0) { - memset(dst, 0, num_pix * sizeof(cover_type)); + std::memset(dst, 0, num_pix * sizeof(cover_type)); return; } - memset(covers + count, 0, rest * sizeof(cover_type)); + std::memset(covers + count, 0, rest * sizeof(cover_type)); } - const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { - *covers = (cover_type)(((*covers) * + *covers = (cover_type)((cover_full + (*covers) * m_mask_function.calculate(mask)) >> cover_shift); ++covers; @@ -353,7 +353,7 @@ namespace agg public: typedef int8u cover_type; typedef amask_no_clip_u8 self_type; - enum + enum cover_scale_e { cover_shift = 8, cover_none = 0, @@ -361,7 +361,7 @@ namespace agg }; amask_no_clip_u8() : m_rbuf(0) {} - amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {} + explicit amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {} void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; } @@ -373,16 +373,16 @@ namespace agg cover_type pixel(int x, int y) const { return (cover_type)m_mask_function.calculate( - m_rbuf->row(y) + x * Step + Offset); + m_rbuf->row_ptr(y) + x * Step + Offset); } //-------------------------------------------------------------------- cover_type combine_pixel(int x, int y, cover_type val) const { - return (cover_type)((val * + return (cover_type)((cover_full + val * m_mask_function.calculate( - m_rbuf->row(y) + x * Step + Offset)) >> + m_rbuf->row_ptr(y) + x * Step + Offset)) >> cover_shift); } @@ -390,7 +390,7 @@ namespace agg //-------------------------------------------------------------------- void fill_hspan(int x, int y, cover_type* dst, int num_pix) const { - const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { *dst++ = (cover_type)m_mask_function.calculate(mask); @@ -404,10 +404,10 @@ namespace agg //-------------------------------------------------------------------- void combine_hspan(int x, int y, cover_type* dst, int num_pix) const { - const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { - *dst = (cover_type)(((*dst) * + *dst = (cover_type)((cover_full + (*dst) * m_mask_function.calculate(mask)) >> cover_shift); ++dst; @@ -420,7 +420,7 @@ namespace agg //-------------------------------------------------------------------- void fill_vspan(int x, int y, cover_type* dst, int num_pix) const { - const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { *dst++ = (cover_type)m_mask_function.calculate(mask); @@ -433,10 +433,10 @@ namespace agg //-------------------------------------------------------------------- void combine_vspan(int x, int y, cover_type* dst, int num_pix) const { - const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { - *dst = (cover_type)(((*dst) * + *dst = (cover_type)((cover_full + (*dst) * m_mask_function.calculate(mask)) >> cover_shift); ++dst; diff --git a/agg2/include/agg_arc.h b/agg/include/agg_arc.h similarity index 94% rename from agg2/include/agg_arc.h rename to agg/include/agg_arc.h index 2dff508..56ac487 100644 --- a/agg2/include/agg_arc.h +++ b/agg/include/agg_arc.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -20,7 +20,6 @@ #ifndef AGG_ARC_INCLUDED #define AGG_ARC_INCLUDED -#include #include "agg_basics.h" namespace agg diff --git a/agg/include/agg_array.h b/agg/include/agg_array.h new file mode 100644 index 0000000..b48010b --- /dev/null +++ b/agg/include/agg_array.h @@ -0,0 +1,1119 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +#ifndef AGG_ARRAY_INCLUDED +#define AGG_ARRAY_INCLUDED + +#include +#include +#include "agg_basics.h" + +namespace agg +{ + + //-------------------------------------------------------pod_array_adaptor + template class pod_array_adaptor + { + public: + typedef T value_type; + pod_array_adaptor(T* array, unsigned size) : + m_array(array), m_size(size) {} + + unsigned size() const { return m_size; } + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + + private: + T* m_array; + unsigned m_size; + }; + + + //---------------------------------------------------------pod_auto_array + template class pod_auto_array + { + public: + typedef T value_type; + typedef pod_auto_array self_type; + + pod_auto_array() {} + explicit pod_auto_array(const T* c) + { + std::memcpy(m_array, c, sizeof(T) * Size); + } + + const self_type& operator = (const T* c) + { + std::memcpy(m_array, c, sizeof(T) * Size); + return *this; + } + + static unsigned size() { return Size; } + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + + private: + T m_array[Size]; + }; + + + //--------------------------------------------------------pod_auto_vector + template class pod_auto_vector + { + public: + typedef T value_type; + typedef pod_auto_vector self_type; + + pod_auto_vector() : m_size(0) {} + + void remove_all() { m_size = 0; } + void clear() { m_size = 0; } + void add(const T& v) { m_array[m_size++] = v; } + void push_back(const T& v) { m_array[m_size++] = v; } + void inc_size(unsigned size) { m_size += size; } + + unsigned size() const { return m_size; } + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + + private: + T m_array[Size]; + unsigned m_size; + }; + + + //---------------------------------------------------------------pod_array + template class pod_array + { + public: + typedef T value_type; + typedef pod_array self_type; + + ~pod_array() { pod_allocator::deallocate(m_array, m_size); } + pod_array() : m_array(0), m_size(0) {} + + pod_array(unsigned size) : + m_array(pod_allocator::allocate(size)), + m_size(size) + {} + + pod_array(const self_type& v) : + m_array(pod_allocator::allocate(v.m_size)), + m_size(v.m_size) + { + std::memcpy(m_array, v.m_array, sizeof(T) * m_size); + } + + void resize(unsigned size) + { + if(size != m_size) + { + pod_allocator::deallocate(m_array, m_size); + m_array = pod_allocator::allocate(m_size = size); + } + } + const self_type& operator = (const self_type& v) + { + resize(v.size()); + std::memcpy(m_array, v.m_array, sizeof(T) * m_size); + return *this; + } + + unsigned size() const { return m_size; } + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + + const T* data() const { return m_array; } + T* data() { return m_array; } + private: + T* m_array; + unsigned m_size; + }; + + + + //--------------------------------------------------------------pod_vector + // A simple class template to store Plain Old Data, a vector + // of a fixed size. The data is continous in memory + //------------------------------------------------------------------------ + template class pod_vector + { + public: + typedef T value_type; + + ~pod_vector() { pod_allocator::deallocate(m_array, m_capacity); } + pod_vector() : m_size(0), m_capacity(0), m_array(0) {} + pod_vector(unsigned cap, unsigned extra_tail=0); + + // Copying + pod_vector(const pod_vector&); + const pod_vector& operator = (const pod_vector&); + + // Set new capacity. All data is lost, size is set to zero. + void capacity(unsigned cap, unsigned extra_tail=0); + unsigned capacity() const { return m_capacity; } + + // Allocate n elements. All data is lost, + // but elements can be accessed in range 0...size-1. + void allocate(unsigned size, unsigned extra_tail=0); + + // Resize keeping the content. + void resize(unsigned new_size); + + void zero() + { + std::memset(m_array, 0, sizeof(T) * m_size); + } + + void add(const T& v) { m_array[m_size++] = v; } + void push_back(const T& v) { m_array[m_size++] = v; } + void insert_at(unsigned pos, const T& val); + void inc_size(unsigned size) { m_size += size; } + unsigned size() const { return m_size; } + unsigned byte_size() const { return m_size * sizeof(T); } + void serialize(int8u* ptr) const; + void deserialize(const int8u* data, unsigned byte_size); + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + + const T* data() const { return m_array; } + T* data() { return m_array; } + + void remove_all() { m_size = 0; } + void clear() { m_size = 0; } + void cut_at(unsigned num) { if(num < m_size) m_size = num; } + + private: + unsigned m_size; + unsigned m_capacity; + T* m_array; + }; + + //------------------------------------------------------------------------ + template + void pod_vector::capacity(unsigned cap, unsigned extra_tail) + { + m_size = 0; + if(cap > m_capacity) + { + pod_allocator::deallocate(m_array, m_capacity); + m_capacity = cap + extra_tail; + m_array = m_capacity ? pod_allocator::allocate(m_capacity) : 0; + } + } + + //------------------------------------------------------------------------ + template + void pod_vector::allocate(unsigned size, unsigned extra_tail) + { + capacity(size, extra_tail); + m_size = size; + } + + + //------------------------------------------------------------------------ + template + void pod_vector::resize(unsigned new_size) + { + if(new_size > m_size) + { + if(new_size > m_capacity) + { + T* data = pod_allocator::allocate(new_size); + std::memcpy(data, m_array, m_size * sizeof(T)); + pod_allocator::deallocate(m_array, m_capacity); + m_array = data; + } + } + else + { + m_size = new_size; + } + } + + //------------------------------------------------------------------------ + template pod_vector::pod_vector(unsigned cap, unsigned extra_tail) : + m_size(0), + m_capacity(cap + extra_tail), + m_array(pod_allocator::allocate(m_capacity)) {} + + //------------------------------------------------------------------------ + template pod_vector::pod_vector(const pod_vector& v) : + m_size(v.m_size), + m_capacity(v.m_capacity), + m_array(v.m_capacity ? pod_allocator::allocate(v.m_capacity) : 0) + { + std::memcpy(m_array, v.m_array, sizeof(T) * v.m_size); + } + + //------------------------------------------------------------------------ + template const pod_vector& + pod_vector::operator = (const pod_vector&v) + { + allocate(v.m_size); + if(v.m_size) std::memcpy(m_array, v.m_array, sizeof(T) * v.m_size); + return *this; + } + + //------------------------------------------------------------------------ + template void pod_vector::serialize(int8u* ptr) const + { + if(m_size) std::memcpy(ptr, m_array, m_size * sizeof(T)); + } + + //------------------------------------------------------------------------ + template + void pod_vector::deserialize(const int8u* data, unsigned byte_size) + { + byte_size /= sizeof(T); + allocate(byte_size); + if(byte_size) std::memcpy(m_array, data, byte_size * sizeof(T)); + } + + //------------------------------------------------------------------------ + template + void pod_vector::insert_at(unsigned pos, const T& val) + { + if(pos >= m_size) + { + m_array[m_size] = val; + } + else + { + std::memmove(m_array + pos + 1, m_array + pos, (m_size - pos) * sizeof(T)); + m_array[pos] = val; + } + ++m_size; + } + + //---------------------------------------------------------------pod_bvector + // A simple class template to store Plain Old Data, similar to std::deque + // It doesn't reallocate memory but instead, uses blocks of data of size + // of (1 << S), that is, power of two. The data is NOT contiguous in memory, + // so the only valid access method is operator [] or curr(), prev(), next() + // + // There reallocs occure only when the pool of pointers to blocks needs + // to be extended (it happens very rarely). You can control the value + // of increment to reallocate the pointer buffer. See the second constructor. + // By default, the incremeent value equals (1 << S), i.e., the block size. + //------------------------------------------------------------------------ + template class pod_bvector + { + public: + enum block_scale_e + { + block_shift = S, + block_size = 1 << block_shift, + block_mask = block_size - 1 + }; + + typedef T value_type; + + ~pod_bvector(); + pod_bvector(); + pod_bvector(unsigned block_ptr_inc); + + // Copying + pod_bvector(const pod_bvector& v); + const pod_bvector& operator = (const pod_bvector& v); + + void remove_all() { m_size = 0; } + void clear() { m_size = 0; } + void free_all() { free_tail(0); } + void free_tail(unsigned size); + void add(const T& val); + void push_back(const T& val) { add(val); } + void modify_last(const T& val); + void remove_last(); + + int allocate_continuous_block(unsigned num_elements); + + void add_array(const T* ptr, unsigned num_elem) + { + while(num_elem--) + { + add(*ptr++); + } + } + + template void add_data(DataAccessor& data) + { + while(data.size()) + { + add(*data); + ++data; + } + } + + void cut_at(unsigned size) + { + if(size < m_size) m_size = size; + } + + unsigned size() const { return m_size; } + + const T& operator [] (unsigned i) const + { + return m_blocks[i >> block_shift][i & block_mask]; + } + + T& operator [] (unsigned i) + { + return m_blocks[i >> block_shift][i & block_mask]; + } + + const T& at(unsigned i) const + { + return m_blocks[i >> block_shift][i & block_mask]; + } + + T& at(unsigned i) + { + return m_blocks[i >> block_shift][i & block_mask]; + } + + T value_at(unsigned i) const + { + return m_blocks[i >> block_shift][i & block_mask]; + } + + const T& curr(unsigned idx) const + { + return (*this)[idx]; + } + + T& curr(unsigned idx) + { + return (*this)[idx]; + } + + const T& prev(unsigned idx) const + { + return (*this)[(idx + m_size - 1) % m_size]; + } + + T& prev(unsigned idx) + { + return (*this)[(idx + m_size - 1) % m_size]; + } + + const T& next(unsigned idx) const + { + return (*this)[(idx + 1) % m_size]; + } + + T& next(unsigned idx) + { + return (*this)[(idx + 1) % m_size]; + } + + const T& last() const + { + return (*this)[m_size - 1]; + } + + T& last() + { + return (*this)[m_size - 1]; + } + + unsigned byte_size() const; + void serialize(int8u* ptr) const; + void deserialize(const int8u* data, unsigned byte_size); + void deserialize(unsigned start, const T& empty_val, + const int8u* data, unsigned byte_size); + + template + void deserialize(ByteAccessor data) + { + remove_all(); + unsigned elem_size = data.size() / sizeof(T); + + for(unsigned i = 0; i < elem_size; ++i) + { + int8u* ptr = (int8u*)data_ptr(); + for(unsigned j = 0; j < sizeof(T); ++j) + { + *ptr++ = *data; + ++data; + } + ++m_size; + } + } + + template + void deserialize(unsigned start, const T& empty_val, ByteAccessor data) + { + while(m_size < start) + { + add(empty_val); + } + + unsigned elem_size = data.size() / sizeof(T); + for(unsigned i = 0; i < elem_size; ++i) + { + int8u* ptr; + if(start + i < m_size) + { + ptr = (int8u*)(&((*this)[start + i])); + } + else + { + ptr = (int8u*)data_ptr(); + ++m_size; + } + for(unsigned j = 0; j < sizeof(T); ++j) + { + *ptr++ = *data; + ++data; + } + } + } + + const T* block(unsigned nb) const { return m_blocks[nb]; } + + private: + void allocate_block(unsigned nb); + T* data_ptr(); + + unsigned m_size; + unsigned m_num_blocks; + unsigned m_max_blocks; + T** m_blocks; + unsigned m_block_ptr_inc; + }; + + + //------------------------------------------------------------------------ + template pod_bvector::~pod_bvector() + { + if(m_num_blocks) + { + T** blk = m_blocks + m_num_blocks - 1; + while(m_num_blocks--) + { + pod_allocator::deallocate(*blk, block_size); + --blk; + } + } + pod_allocator::deallocate(m_blocks, m_max_blocks); + } + + + //------------------------------------------------------------------------ + template + void pod_bvector::free_tail(unsigned size) + { + if(size < m_size) + { + unsigned nb = (size + block_mask) >> block_shift; + while(m_num_blocks > nb) + { + pod_allocator::deallocate(m_blocks[--m_num_blocks], block_size); + } + if(m_num_blocks == 0) + { + pod_allocator::deallocate(m_blocks, m_max_blocks); + m_blocks = 0; + m_max_blocks = 0; + } + m_size = size; + } + } + + + //------------------------------------------------------------------------ + template pod_bvector::pod_bvector() : + m_size(0), + m_num_blocks(0), + m_max_blocks(0), + m_blocks(0), + m_block_ptr_inc(block_size) + { + } + + + //------------------------------------------------------------------------ + template + pod_bvector::pod_bvector(unsigned block_ptr_inc) : + m_size(0), + m_num_blocks(0), + m_max_blocks(0), + m_blocks(0), + m_block_ptr_inc(block_ptr_inc) + { + } + + + //------------------------------------------------------------------------ + template + pod_bvector::pod_bvector(const pod_bvector& v) : + m_size(v.m_size), + m_num_blocks(v.m_num_blocks), + m_max_blocks(v.m_max_blocks), + m_blocks(v.m_max_blocks ? + pod_allocator::allocate(v.m_max_blocks) : + 0), + m_block_ptr_inc(v.m_block_ptr_inc) + { + unsigned i; + for(i = 0; i < v.m_num_blocks; ++i) + { + m_blocks[i] = pod_allocator::allocate(block_size); + std::memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T)); + } + } + + + //------------------------------------------------------------------------ + template + const pod_bvector& + pod_bvector::operator = (const pod_bvector& v) + { + unsigned i; + for(i = m_num_blocks; i < v.m_num_blocks; ++i) + { + allocate_block(i); + } + for(i = 0; i < v.m_num_blocks; ++i) + { + std::memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T)); + } + m_size = v.m_size; + return *this; + } + + + //------------------------------------------------------------------------ + template + void pod_bvector::allocate_block(unsigned nb) + { + if(nb >= m_max_blocks) + { + T** new_blocks = pod_allocator::allocate(m_max_blocks + m_block_ptr_inc); + + if(m_blocks) + { + std::memcpy(new_blocks, + m_blocks, + m_num_blocks * sizeof(T*)); + + pod_allocator::deallocate(m_blocks, m_max_blocks); + } + m_blocks = new_blocks; + m_max_blocks += m_block_ptr_inc; + } + m_blocks[nb] = pod_allocator::allocate(block_size); + m_num_blocks++; + } + + + + //------------------------------------------------------------------------ + template + inline T* pod_bvector::data_ptr() + { + unsigned nb = m_size >> block_shift; + if(nb >= m_num_blocks) + { + allocate_block(nb); + } + return m_blocks[nb] + (m_size & block_mask); + } + + + + //------------------------------------------------------------------------ + template + inline void pod_bvector::add(const T& val) + { + *data_ptr() = val; + ++m_size; + } + + + //------------------------------------------------------------------------ + template + inline void pod_bvector::remove_last() + { + if(m_size) --m_size; + } + + + //------------------------------------------------------------------------ + template + void pod_bvector::modify_last(const T& val) + { + remove_last(); + add(val); + } + + + //------------------------------------------------------------------------ + template + int pod_bvector::allocate_continuous_block(unsigned num_elements) + { + if(num_elements < block_size) + { + data_ptr(); // Allocate initial block if necessary + unsigned rest = block_size - (m_size & block_mask); + unsigned index; + if(num_elements <= rest) + { + // The rest of the block is good, we can use it + //----------------- + index = m_size; + m_size += num_elements; + return index; + } + + // New block + //--------------- + m_size += rest; + data_ptr(); + index = m_size; + m_size += num_elements; + return index; + } + return -1; // Impossible to allocate + } + + + //------------------------------------------------------------------------ + template + unsigned pod_bvector::byte_size() const + { + return m_size * sizeof(T); + } + + + //------------------------------------------------------------------------ + template + void pod_bvector::serialize(int8u* ptr) const + { + unsigned i; + for(i = 0; i < m_size; i++) + { + std::memcpy(ptr, &(*this)[i], sizeof(T)); + ptr += sizeof(T); + } + } + + //------------------------------------------------------------------------ + template + void pod_bvector::deserialize(const int8u* data, unsigned byte_size) + { + remove_all(); + byte_size /= sizeof(T); + for(unsigned i = 0; i < byte_size; ++i) + { + T* ptr = data_ptr(); + std::memcpy(ptr, data, sizeof(T)); + ++m_size; + data += sizeof(T); + } + } + + + // Replace or add a number of elements starting from "start" position + //------------------------------------------------------------------------ + template + void pod_bvector::deserialize(unsigned start, const T& empty_val, + const int8u* data, unsigned byte_size) + { + while(m_size < start) + { + add(empty_val); + } + + byte_size /= sizeof(T); + for(unsigned i = 0; i < byte_size; ++i) + { + if(start + i < m_size) + { + std::memcpy(&((*this)[start + i]), data, sizeof(T)); + } + else + { + T* ptr = data_ptr(); + std::memcpy(ptr, data, sizeof(T)); + ++m_size; + } + data += sizeof(T); + } + } + + + //---------------------------------------------------------block_allocator + // Allocator for arbitrary POD data. Most usable in different cache + // systems for efficient memory allocations. + // Memory is allocated with blocks of fixed size ("block_size" in + // the constructor). If required size exceeds the block size the allocator + // creates a new block of the required size. However, the most efficient + // use is when the average reqired size is much less than the block size. + //------------------------------------------------------------------------ + class block_allocator + { + struct block_type + { + int8u* data; + unsigned size; + }; + + public: + void remove_all() + { + if(m_num_blocks) + { + block_type* blk = m_blocks + m_num_blocks - 1; + while(m_num_blocks--) + { + pod_allocator::deallocate(blk->data, blk->size); + --blk; + } + pod_allocator::deallocate(m_blocks, m_max_blocks); + } + m_num_blocks = 0; + m_max_blocks = 0; + m_blocks = 0; + m_buf_ptr = 0; + m_rest = 0; + } + + ~block_allocator() + { + remove_all(); + } + + block_allocator(unsigned block_size, unsigned block_ptr_inc=256-8) : + m_block_size(block_size), + m_block_ptr_inc(block_ptr_inc), + m_num_blocks(0), + m_max_blocks(0), + m_blocks(0), + m_buf_ptr(0), + m_rest(0) + { + } + + + int8u* allocate(unsigned size, unsigned alignment=1) + { + if(size == 0) return 0; + if(size <= m_rest) + { + int8u* ptr = m_buf_ptr; + if(alignment > 1) + { + unsigned align = + (alignment - unsigned((std::size_t)ptr) % alignment) % alignment; + + size += align; + ptr += align; + if(size <= m_rest) + { + m_rest -= size; + m_buf_ptr += size; + return ptr; + } + allocate_block(size); + return allocate(size - align, alignment); + } + m_rest -= size; + m_buf_ptr += size; + return ptr; + } + allocate_block(size + alignment - 1); + return allocate(size, alignment); + } + + + private: + void allocate_block(unsigned size) + { + if(size < m_block_size) size = m_block_size; + if(m_num_blocks >= m_max_blocks) + { + block_type* new_blocks = + pod_allocator::allocate(m_max_blocks + m_block_ptr_inc); + + if(m_blocks) + { + std::memcpy(new_blocks, + m_blocks, + m_num_blocks * sizeof(block_type)); + pod_allocator::deallocate(m_blocks, m_max_blocks); + } + m_blocks = new_blocks; + m_max_blocks += m_block_ptr_inc; + } + + m_blocks[m_num_blocks].size = size; + m_blocks[m_num_blocks].data = + m_buf_ptr = + pod_allocator::allocate(size); + + m_num_blocks++; + m_rest = size; + } + + unsigned m_block_size; + unsigned m_block_ptr_inc; + unsigned m_num_blocks; + unsigned m_max_blocks; + block_type* m_blocks; + int8u* m_buf_ptr; + unsigned m_rest; + }; + + + + + + + + + //------------------------------------------------------------------------ + enum quick_sort_threshold_e + { + quick_sort_threshold = 9 + }; + + + //-----------------------------------------------------------swap_elements + template inline void swap_elements(T& a, T& b) + { + T temp = a; + a = b; + b = temp; + } + + + //--------------------------------------------------------------quick_sort + template + void quick_sort(Array& arr, Less less) + { + if(arr.size() < 2) return; + + typename Array::value_type* e1; + typename Array::value_type* e2; + + int stack[80]; + int* top = stack; + int limit = arr.size(); + int base = 0; + + for(;;) + { + int len = limit - base; + + int i; + int j; + int pivot; + + if(len > quick_sort_threshold) + { + // we use base + len/2 as the pivot + pivot = base + len / 2; + swap_elements(arr[base], arr[pivot]); + + i = base + 1; + j = limit - 1; + + // now ensure that *i <= *base <= *j + e1 = &(arr[j]); + e2 = &(arr[i]); + if(less(*e1, *e2)) swap_elements(*e1, *e2); + + e1 = &(arr[base]); + e2 = &(arr[i]); + if(less(*e1, *e2)) swap_elements(*e1, *e2); + + e1 = &(arr[j]); + e2 = &(arr[base]); + if(less(*e1, *e2)) swap_elements(*e1, *e2); + + for(;;) + { + do i++; while( less(arr[i], arr[base]) ); + do j--; while( less(arr[base], arr[j]) ); + + if( i > j ) + { + break; + } + + swap_elements(arr[i], arr[j]); + } + + swap_elements(arr[base], arr[j]); + + // now, push the largest sub-array + if(j - base > limit - i) + { + top[0] = base; + top[1] = j; + base = i; + } + else + { + top[0] = i; + top[1] = limit; + limit = j; + } + top += 2; + } + else + { + // the sub-array is small, perform insertion sort + j = base; + i = j + 1; + + for(; i < limit; j = i, i++) + { + for(; less(*(e1 = &(arr[j + 1])), *(e2 = &(arr[j]))); j--) + { + swap_elements(*e1, *e2); + if(j == base) + { + break; + } + } + } + if(top > stack) + { + top -= 2; + base = top[0]; + limit = top[1]; + } + else + { + break; + } + } + } + } + + + + + //------------------------------------------------------remove_duplicates + // Remove duplicates from a sorted array. It doesn't cut the + // tail of the array, it just returns the number of remaining elements. + //----------------------------------------------------------------------- + template + unsigned remove_duplicates(Array& arr, Equal equal) + { + if(arr.size() < 2) return arr.size(); + + unsigned i, j; + for(i = 1, j = 1; i < arr.size(); i++) + { + typename Array::value_type& e = arr[i]; + if(!equal(e, arr[i - 1])) + { + arr[j++] = e; + } + } + return j; + } + + //--------------------------------------------------------invert_container + template void invert_container(Array& arr) + { + int i = 0; + int j = arr.size() - 1; + while(i < j) + { + swap_elements(arr[i++], arr[j--]); + } + } + + //------------------------------------------------------binary_search_pos + template + unsigned binary_search_pos(const Array& arr, const Value& val, Less less) + { + if(arr.size() == 0) return 0; + + unsigned beg = 0; + unsigned end = arr.size() - 1; + + if(less(val, arr[0])) return 0; + if(less(arr[end], val)) return end + 1; + + while(end - beg > 1) + { + unsigned mid = (end + beg) >> 1; + if(less(val, arr[mid])) end = mid; + else beg = mid; + } + + //if(beg <= 0 && less(val, arr[0])) return 0; + //if(end >= arr.size() - 1 && less(arr[end], val)) ++end; + + return end; + } + + //----------------------------------------------------------range_adaptor + template class range_adaptor + { + public: + typedef typename Array::value_type value_type; + + range_adaptor(Array& array, unsigned start, unsigned size) : + m_array(array), m_start(start), m_size(size) + {} + + unsigned size() const { return m_size; } + const value_type& operator [] (unsigned i) const { return m_array[m_start + i]; } + value_type& operator [] (unsigned i) { return m_array[m_start + i]; } + const value_type& at(unsigned i) const { return m_array[m_start + i]; } + value_type& at(unsigned i) { return m_array[m_start + i]; } + value_type value_at(unsigned i) const { return m_array[m_start + i]; } + + private: + Array& m_array; + unsigned m_start; + unsigned m_size; + }; + + //---------------------------------------------------------------int_less + inline bool int_less(int a, int b) { return a < b; } + + //------------------------------------------------------------int_greater + inline bool int_greater(int a, int b) { return a > b; } + + //----------------------------------------------------------unsigned_less + inline bool unsigned_less(unsigned a, unsigned b) { return a < b; } + + //-------------------------------------------------------unsigned_greater + inline bool unsigned_greater(unsigned a, unsigned b) { return a > b; } +} + +#endif diff --git a/agg2/include/agg_arrowhead.h b/agg/include/agg_arrowhead.h similarity index 93% rename from agg2/include/agg_arrowhead.h rename to agg/include/agg_arrowhead.h index 2c38608..5e029dd 100644 --- a/agg2/include/agg_arrowhead.h +++ b/agg/include/agg_arrowhead.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -57,7 +57,7 @@ namespace agg void tail() { m_tail_flag = true; } void no_tail() { m_tail_flag = false; } - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: diff --git a/agg/include/agg_basics.h b/agg/include/agg_basics.h new file mode 100644 index 0000000..62364d1 --- /dev/null +++ b/agg/include/agg_basics.h @@ -0,0 +1,574 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_BASICS_INCLUDED +#define AGG_BASICS_INCLUDED + +#include +#include "agg_config.h" + +//---------------------------------------------------------AGG_CUSTOM_ALLOCATOR +#ifdef AGG_CUSTOM_ALLOCATOR +#include "agg_allocator.h" +#else +namespace agg +{ + // The policy of all AGG containers and memory allocation strategy + // in general is that no allocated data requires explicit construction. + // It means that the allocator can be really simple; you can even + // replace new/delete to malloc/free. The constructors and destructors + // won't be called in this case, however everything will remain working. + // The second argument of deallocate() is the size of the allocated + // block. You can use this information if you wish. + //------------------------------------------------------------pod_allocator + template struct pod_allocator + { + static T* allocate(unsigned num) { return new T [num]; } + static void deallocate(T* ptr, unsigned) { delete [] ptr; } + }; + + // Single object allocator. It's also can be replaced with your custom + // allocator. The difference is that it can only allocate a single + // object and the constructor and destructor must be called. + // In AGG there is no need to allocate an array of objects with + // calling their constructors (only single ones). So that, if you + // replace these new/delete to malloc/free make sure that the in-place + // new is called and take care of calling the destructor too. + //------------------------------------------------------------obj_allocator + template struct obj_allocator + { + static T* allocate() { return new T; } + static void deallocate(T* ptr) { delete ptr; } + }; +} +#endif + + +//-------------------------------------------------------- Default basic types +// +// If the compiler has different capacity of the basic types you can redefine +// them via the compiler command line or by generating agg_config.h that is +// empty by default. +// +#ifndef AGG_INT8 +#define AGG_INT8 signed char +#endif + +#ifndef AGG_INT8U +#define AGG_INT8U unsigned char +#endif + +#ifndef AGG_INT16 +#define AGG_INT16 short +#endif + +#ifndef AGG_INT16U +#define AGG_INT16U unsigned short +#endif + +#ifndef AGG_INT32 +#define AGG_INT32 int +#endif + +#ifndef AGG_INT32U +#define AGG_INT32U unsigned +#endif + +#ifndef AGG_INT64 +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define AGG_INT64 signed __int64 +#else +#define AGG_INT64 signed long long +#endif +#endif + +#ifndef AGG_INT64U +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define AGG_INT64U unsigned __int64 +#else +#define AGG_INT64U unsigned long long +#endif +#endif + +//------------------------------------------------ Some fixes for MS Visual C++ +#if defined(_MSC_VER) +#pragma warning(disable:4786) // Identifier was truncated... +#endif + +#if defined(_MSC_VER) +#define AGG_INLINE __forceinline +#else +#define AGG_INLINE inline +#endif + +namespace agg +{ + //------------------------------------------------------------------------- + typedef AGG_INT8 int8; //----int8 + typedef AGG_INT8U int8u; //----int8u + typedef AGG_INT16 int16; //----int16 + typedef AGG_INT16U int16u; //----int16u + typedef AGG_INT32 int32; //----int32 + typedef AGG_INT32U int32u; //----int32u + typedef AGG_INT64 int64; //----int64 + typedef AGG_INT64U int64u; //----int64u + +#if defined(AGG_FISTP) +#pragma warning(push) +#pragma warning(disable : 4035) //Disable warning "no return value" + AGG_INLINE int iround(double v) //-------iround + { + int t; + __asm fld qword ptr [v] + __asm fistp dword ptr [t] + __asm mov eax, dword ptr [t] + } + AGG_INLINE unsigned uround(double v) //-------uround + { + unsigned t; + __asm fld qword ptr [v] + __asm fistp dword ptr [t] + __asm mov eax, dword ptr [t] + } +#pragma warning(pop) + AGG_INLINE int ifloor(double v) + { + return int(floor(v)); + } + AGG_INLINE unsigned ufloor(double v) //-------ufloor + { + return unsigned(floor(v)); + } + AGG_INLINE int iceil(double v) + { + return int(ceil(v)); + } + AGG_INLINE unsigned uceil(double v) //--------uceil + { + return unsigned(ceil(v)); + } +#elif defined(AGG_QIFIST) + AGG_INLINE int iround(double v) + { + return int(v); + } + AGG_INLINE int uround(double v) + { + return unsigned(v); + } + AGG_INLINE int ifloor(double v) + { + return int(std::floor(v)); + } + AGG_INLINE unsigned ufloor(double v) + { + return unsigned(std::floor(v)); + } + AGG_INLINE int iceil(double v) + { + return int(std::ceil(v)); + } + AGG_INLINE unsigned uceil(double v) + { + return unsigned(std::ceil(v)); + } +#else + AGG_INLINE int iround(double v) + { + return int((v < 0.0) ? v - 0.5 : v + 0.5); + } + AGG_INLINE int uround(double v) + { + return unsigned(v + 0.5); + } + AGG_INLINE int ifloor(double v) + { + int i = int(v); + return i - (i > v); + } + AGG_INLINE unsigned ufloor(double v) + { + return unsigned(v); + } + AGG_INLINE int iceil(double v) + { + return int(std::ceil(v)); + } + AGG_INLINE unsigned uceil(double v) + { + return unsigned(std::ceil(v)); + } +#endif + + //---------------------------------------------------------------saturation + template 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 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< struct rect_base + { + typedef T value_type; + typedef rect_base 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); + } + + bool overlaps(const self_type& r) const + { + return !(r.x1 > x2 || r.x2 < x1 + || r.y1 > y2 || r.y2 < y1); + } + }; + + //-----------------------------------------------------intersect_rectangles + template + 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 + 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 rect_i; //----rect_i + typedef rect_base rect_f; //----rect_f + typedef rect_base 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 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 point_i; //-----point_i + typedef point_base point_f; //-----point_f + typedef point_base point_d; //-----point_d + + //-------------------------------------------------------------vertex_base + template 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 vertex_i; //-----vertex_i + typedef vertex_base vertex_f; //-----vertex_f + typedef vertex_base vertex_d; //-----vertex_d + + //----------------------------------------------------------------row_info + template 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 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 inline bool is_equal_eps(T v1, T v2, T epsilon) + { + bool neg1 = v1 < 0.0; + bool neg2 = v2 < 0.0; + + if (neg1 != neg2) + return std::fabs(v1) < epsilon && std::fabs(v2) < epsilon; + + int int1, int2; + std::frexp(v1, &int1); + std::frexp(v2, &int2); + int min12 = int1 < int2 ? int1 : int2; + + v1 = std::ldexp(v1, -min12); + v2 = std::ldexp(v2, -min12); + + return std::fabs(v1 - v2) < epsilon; + } +} + + +#endif + diff --git a/agg2/include/agg_bezier_arc.h b/agg/include/agg_bezier_arc.h similarity index 92% rename from agg2/include/agg_bezier_arc.h rename to agg/include/agg_bezier_arc.h index 4e3d0db..cfd9308 100644 --- a/agg2/include/agg_bezier_arc.h +++ b/agg/include/agg_bezier_arc.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -39,7 +39,8 @@ namespace agg class bezier_arc { public: - bezier_arc() : m_vertex(26) {} + //-------------------------------------------------------------------- + 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, @@ -48,6 +49,7 @@ namespace agg init(x, y, rx, ry, start_angle, sweep_angle); } + //-------------------------------------------------------------------- void init(double x, double y, double rx, double ry, double start_angle, @@ -66,7 +68,7 @@ namespace agg *x = m_vertices[m_vertex]; *y = m_vertices[m_vertex + 1]; m_vertex += 2; - return (m_vertex == 2) ? path_cmd_move_to : path_cmd_curve4; + return (m_vertex == 2) ? unsigned(path_cmd_move_to) : m_cmd; } // Supplemantary functions. num_vertices() actually returns doubled @@ -80,6 +82,7 @@ namespace agg unsigned m_vertex; unsigned m_num_vertices; double m_vertices[26]; + unsigned m_cmd; }; diff --git a/agg2/include/agg_bitset_iterator.h b/agg/include/agg_bitset_iterator.h similarity index 92% rename from agg2/include/agg_bitset_iterator.h rename to agg/include/agg_bitset_iterator.h index 7264398..7382d5c 100644 --- a/agg2/include/agg_bitset_iterator.h +++ b/agg/include/agg_bitset_iterator.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. diff --git a/agg/include/agg_blur.h b/agg/include/agg_blur.h new file mode 100644 index 0000000..fd38e94 --- /dev/null +++ b/agg/include/agg_blur.h @@ -0,0 +1,1505 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// The Stack Blur Algorithm was invented by Mario Klingemann, +// mario@quasimondo.com and described here: +// http://incubator.quasimondo.com/processing/fast_blur_deluxe.php +// (search phrase "Stackblur: Fast But Goodlooking"). +// The major improvement is that there's no more division table +// that was very expensive to create for large blur radii. Insted, +// for 8-bit per channel and radius not exceeding 254 the division is +// replaced by multiplication and shift. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_BLUR_INCLUDED +#define AGG_BLUR_INCLUDED + +#include +#include +#include "agg_array.h" +#include "agg_pixfmt_base.h" +#include "agg_pixfmt_transposer.h" + +namespace agg +{ + + template struct stack_blur_tables + { + static int16u const g_stack_blur8_mul[255]; + static int8u const g_stack_blur8_shr[255]; + }; + + //------------------------------------------------------------------------ + template + int16u const stack_blur_tables::g_stack_blur8_mul[255] = + { + 512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512, + 454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512, + 482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456, + 437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512, + 497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328, + 320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456, + 446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335, + 329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512, + 505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405, + 399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328, + 324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271, + 268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456, + 451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388, + 385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335, + 332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292, + 289,287,285,282,280,278,275,273,271,269,267,265,263,261,259 + }; + + //------------------------------------------------------------------------ + template + int8u const stack_blur_tables::g_stack_blur8_shr[255] = + { + 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, + 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 + }; + + + + //==============================================================stack_blur + template class stack_blur + { + public: + typedef ColorT color_type; + typedef CalculatorT calculator_type; + + //-------------------------------------------------------------------- + template void blur_x(Img& img, unsigned radius) + { + if(radius < 1) return; + + unsigned x, y, xp, i; + unsigned stack_ptr; + unsigned stack_start; + + color_type pix; + color_type* stack_pix; + calculator_type sum; + calculator_type sum_in; + calculator_type sum_out; + + unsigned w = img.width(); + unsigned h = img.height(); + unsigned wm = w - 1; + unsigned div = radius * 2 + 1; + + unsigned div_sum = (radius + 1) * (radius + 1); + unsigned mul_sum = 0; + unsigned shr_sum = 0; + unsigned max_val = color_type::base_mask; + + if(max_val <= 255 && radius < 255) + { + mul_sum = stack_blur_tables::g_stack_blur8_mul[radius]; + shr_sum = stack_blur_tables::g_stack_blur8_shr[radius]; + } + + m_buf.allocate(w, 128); + m_stack.allocate(div, 32); + + for(y = 0; y < h; y++) + { + sum.clear(); + sum_in.clear(); + sum_out.clear(); + + pix = img.pixel(0, y); + for(i = 0; i <= radius; i++) + { + m_stack[i] = pix; + sum.add(pix, i + 1); + sum_out.add(pix); + } + for(i = 1; i <= radius; i++) + { + pix = img.pixel((i > wm) ? wm : i, y); + m_stack[i + radius] = pix; + sum.add(pix, radius + 1 - i); + sum_in.add(pix); + } + + stack_ptr = radius; + for(x = 0; x < w; x++) + { + if(mul_sum) sum.calc_pix(m_buf[x], mul_sum, shr_sum); + else sum.calc_pix(m_buf[x], div_sum); + + sum.sub(sum_out); + + stack_start = stack_ptr + div - radius; + if(stack_start >= div) stack_start -= div; + stack_pix = &m_stack[stack_start]; + + sum_out.sub(*stack_pix); + + xp = x + radius + 1; + if(xp > wm) xp = wm; + pix = img.pixel(xp, y); + + *stack_pix = pix; + + sum_in.add(pix); + sum.add(sum_in); + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix = &m_stack[stack_ptr]; + + sum_out.add(*stack_pix); + sum_in.sub(*stack_pix); + } + img.copy_color_hspan(0, y, w, &m_buf[0]); + } + } + + //-------------------------------------------------------------------- + template void blur_y(Img& img, unsigned radius) + { + pixfmt_transposer img2(img); + blur_x(img2, radius); + } + + //-------------------------------------------------------------------- + template void blur(Img& img, unsigned radius) + { + blur_x(img, radius); + pixfmt_transposer img2(img); + blur_x(img2, radius); + } + + private: + pod_vector m_buf; + pod_vector m_stack; + }; + + //====================================================stack_blur_calc_rgba + template struct stack_blur_calc_rgba + { + typedef T value_type; + value_type r,g,b,a; + + AGG_INLINE void clear() + { + r = g = b = a = 0; + } + + template AGG_INLINE void add(const ArgT& v) + { + r += v.r; + g += v.g; + b += v.b; + a += v.a; + } + + template AGG_INLINE void add(const ArgT& v, unsigned k) + { + r += v.r * k; + g += v.g * k; + b += v.b * k; + a += v.a * k; + } + + template AGG_INLINE void sub(const ArgT& v) + { + r -= v.r; + g -= v.g; + b -= v.b; + a -= v.a; + } + + template AGG_INLINE void calc_pix(ArgT& v, unsigned div) + { + typedef typename ArgT::value_type value_type; + v.r = value_type(r / div); + v.g = value_type(g / div); + v.b = value_type(b / div); + v.a = value_type(a / div); + } + + template + AGG_INLINE void calc_pix(ArgT& v, unsigned mul, unsigned shr) + { + typedef typename ArgT::value_type value_type; + v.r = value_type((r * mul) >> shr); + v.g = value_type((g * mul) >> shr); + v.b = value_type((b * mul) >> shr); + v.a = value_type((a * mul) >> shr); + } + }; + + + //=====================================================stack_blur_calc_rgb + template struct stack_blur_calc_rgb + { + typedef T value_type; + value_type r,g,b; + + AGG_INLINE void clear() + { + r = g = b = 0; + } + + template AGG_INLINE void add(const ArgT& v) + { + r += v.r; + g += v.g; + b += v.b; + } + + template AGG_INLINE void add(const ArgT& v, unsigned k) + { + r += v.r * k; + g += v.g * k; + b += v.b * k; + } + + template AGG_INLINE void sub(const ArgT& v) + { + r -= v.r; + g -= v.g; + b -= v.b; + } + + template AGG_INLINE void calc_pix(ArgT& v, unsigned div) + { + typedef typename ArgT::value_type value_type; + v.r = value_type(r / div); + v.g = value_type(g / div); + v.b = value_type(b / div); + } + + template + AGG_INLINE void calc_pix(ArgT& v, unsigned mul, unsigned shr) + { + typedef typename ArgT::value_type value_type; + v.r = value_type((r * mul) >> shr); + v.g = value_type((g * mul) >> shr); + v.b = value_type((b * mul) >> shr); + } + }; + + + //====================================================stack_blur_calc_gray + template struct stack_blur_calc_gray + { + typedef T value_type; + value_type v; + + AGG_INLINE void clear() + { + v = 0; + } + + template AGG_INLINE void add(const ArgT& a) + { + v += a.v; + } + + template AGG_INLINE void add(const ArgT& a, unsigned k) + { + v += a.v * k; + } + + template AGG_INLINE void sub(const ArgT& a) + { + v -= a.v; + } + + template AGG_INLINE void calc_pix(ArgT& a, unsigned div) + { + typedef typename ArgT::value_type value_type; + a.v = value_type(v / div); + } + + template + AGG_INLINE void calc_pix(ArgT& a, unsigned mul, unsigned shr) + { + typedef typename ArgT::value_type value_type; + a.v = value_type((v * mul) >> shr); + } + }; + + + + //========================================================stack_blur_gray8 + template + void stack_blur_gray8(Img& img, unsigned rx, unsigned ry) + { + unsigned x, y, xp, yp, i; + unsigned stack_ptr; + unsigned stack_start; + + const int8u* src_pix_ptr; + int8u* dst_pix_ptr; + unsigned pix; + unsigned stack_pix; + unsigned sum; + unsigned sum_in; + unsigned sum_out; + + unsigned w = img.width(); + unsigned h = img.height(); + unsigned wm = w - 1; + unsigned hm = h - 1; + + unsigned div; + unsigned mul_sum; + unsigned shr_sum; + + pod_vector stack; + + if(rx > 0) + { + if(rx > 254) rx = 254; + div = rx * 2 + 1; + mul_sum = stack_blur_tables::g_stack_blur8_mul[rx]; + shr_sum = stack_blur_tables::g_stack_blur8_shr[rx]; + stack.allocate(div); + + for(y = 0; y < h; y++) + { + sum = sum_in = sum_out = 0; + + src_pix_ptr = img.pix_ptr(0, y); + pix = *src_pix_ptr; + for(i = 0; i <= rx; i++) + { + stack[i] = pix; + sum += pix * (i + 1); + sum_out += pix; + } + for(i = 1; i <= rx; i++) + { + if(i <= wm) src_pix_ptr += Img::pix_width; + pix = *src_pix_ptr; + stack[i + rx] = pix; + sum += pix * (rx + 1 - i); + sum_in += pix; + } + + stack_ptr = rx; + xp = rx; + if(xp > wm) xp = wm; + src_pix_ptr = img.pix_ptr(xp, y); + dst_pix_ptr = img.pix_ptr(0, y); + for(x = 0; x < w; x++) + { + *dst_pix_ptr = (sum * mul_sum) >> shr_sum; + dst_pix_ptr += Img::pix_width; + + sum -= sum_out; + + stack_start = stack_ptr + div - rx; + if(stack_start >= div) stack_start -= div; + sum_out -= stack[stack_start]; + + if(xp < wm) + { + src_pix_ptr += Img::pix_width; + pix = *src_pix_ptr; + ++xp; + } + + stack[stack_start] = pix; + + sum_in += pix; + sum += sum_in; + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix = stack[stack_ptr]; + + sum_out += stack_pix; + sum_in -= stack_pix; + } + } + } + + if(ry > 0) + { + if(ry > 254) ry = 254; + div = ry * 2 + 1; + mul_sum = stack_blur_tables::g_stack_blur8_mul[ry]; + shr_sum = stack_blur_tables::g_stack_blur8_shr[ry]; + stack.allocate(div); + + int stride = img.stride(); + for(x = 0; x < w; x++) + { + sum = sum_in = sum_out = 0; + + src_pix_ptr = img.pix_ptr(x, 0); + pix = *src_pix_ptr; + for(i = 0; i <= ry; i++) + { + stack[i] = pix; + sum += pix * (i + 1); + sum_out += pix; + } + for(i = 1; i <= ry; i++) + { + if(i <= hm) src_pix_ptr += stride; + pix = *src_pix_ptr; + stack[i + ry] = pix; + sum += pix * (ry + 1 - i); + sum_in += pix; + } + + stack_ptr = ry; + yp = ry; + if(yp > hm) yp = hm; + src_pix_ptr = img.pix_ptr(x, yp); + dst_pix_ptr = img.pix_ptr(x, 0); + for(y = 0; y < h; y++) + { + *dst_pix_ptr = (sum * mul_sum) >> shr_sum; + dst_pix_ptr += stride; + + sum -= sum_out; + + stack_start = stack_ptr + div - ry; + if(stack_start >= div) stack_start -= div; + sum_out -= stack[stack_start]; + + if(yp < hm) + { + src_pix_ptr += stride; + pix = *src_pix_ptr; + ++yp; + } + + stack[stack_start] = pix; + + sum_in += pix; + sum += sum_in; + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix = stack[stack_ptr]; + + sum_out += stack_pix; + sum_in -= stack_pix; + } + } + } + } + + + + //========================================================stack_blur_rgb24 + template + void stack_blur_rgb24(Img& img, unsigned rx, unsigned ry) + { + typedef typename Img::color_type color_type; + typedef typename Img::order_type order_type; + enum order_e + { + R = order_type::R, + G = order_type::G, + B = order_type::B + }; + + unsigned x, y, xp, yp, i; + unsigned stack_ptr; + unsigned stack_start; + + const int8u* src_pix_ptr; + int8u* dst_pix_ptr; + color_type* stack_pix_ptr; + + unsigned sum_r; + unsigned sum_g; + unsigned sum_b; + unsigned sum_in_r; + unsigned sum_in_g; + unsigned sum_in_b; + unsigned sum_out_r; + unsigned sum_out_g; + unsigned sum_out_b; + + unsigned w = img.width(); + unsigned h = img.height(); + unsigned wm = w - 1; + unsigned hm = h - 1; + + unsigned div; + unsigned mul_sum; + unsigned shr_sum; + + pod_vector stack; + + if(rx > 0) + { + if(rx > 254) rx = 254; + div = rx * 2 + 1; + mul_sum = stack_blur_tables::g_stack_blur8_mul[rx]; + shr_sum = stack_blur_tables::g_stack_blur8_shr[rx]; + stack.allocate(div); + + for(y = 0; y < h; y++) + { + sum_r = + sum_g = + sum_b = + sum_in_r = + sum_in_g = + sum_in_b = + sum_out_r = + sum_out_g = + sum_out_b = 0; + + src_pix_ptr = img.pix_ptr(0, y); + for(i = 0; i <= rx; i++) + { + stack_pix_ptr = &stack[i]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + sum_r += src_pix_ptr[R] * (i + 1); + sum_g += src_pix_ptr[G] * (i + 1); + sum_b += src_pix_ptr[B] * (i + 1); + sum_out_r += src_pix_ptr[R]; + sum_out_g += src_pix_ptr[G]; + sum_out_b += src_pix_ptr[B]; + } + for(i = 1; i <= rx; i++) + { + if(i <= wm) src_pix_ptr += Img::pix_width; + stack_pix_ptr = &stack[i + rx]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + sum_r += src_pix_ptr[R] * (rx + 1 - i); + sum_g += src_pix_ptr[G] * (rx + 1 - i); + sum_b += src_pix_ptr[B] * (rx + 1 - i); + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + } + + stack_ptr = rx; + xp = rx; + if(xp > wm) xp = wm; + src_pix_ptr = img.pix_ptr(xp, y); + dst_pix_ptr = img.pix_ptr(0, y); + for(x = 0; x < w; x++) + { + dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; + dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; + dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; + dst_pix_ptr += Img::pix_width; + + sum_r -= sum_out_r; + sum_g -= sum_out_g; + sum_b -= sum_out_b; + + stack_start = stack_ptr + div - rx; + if(stack_start >= div) stack_start -= div; + stack_pix_ptr = &stack[stack_start]; + + sum_out_r -= stack_pix_ptr->r; + sum_out_g -= stack_pix_ptr->g; + sum_out_b -= stack_pix_ptr->b; + + if(xp < wm) + { + src_pix_ptr += Img::pix_width; + ++xp; + } + + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + sum_r += sum_in_r; + sum_g += sum_in_g; + sum_b += sum_in_b; + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix_ptr = &stack[stack_ptr]; + + sum_out_r += stack_pix_ptr->r; + sum_out_g += stack_pix_ptr->g; + sum_out_b += stack_pix_ptr->b; + sum_in_r -= stack_pix_ptr->r; + sum_in_g -= stack_pix_ptr->g; + sum_in_b -= stack_pix_ptr->b; + } + } + } + + if(ry > 0) + { + if(ry > 254) ry = 254; + div = ry * 2 + 1; + mul_sum = stack_blur_tables::g_stack_blur8_mul[ry]; + shr_sum = stack_blur_tables::g_stack_blur8_shr[ry]; + stack.allocate(div); + + int stride = img.stride(); + for(x = 0; x < w; x++) + { + sum_r = + sum_g = + sum_b = + sum_in_r = + sum_in_g = + sum_in_b = + sum_out_r = + sum_out_g = + sum_out_b = 0; + + src_pix_ptr = img.pix_ptr(x, 0); + for(i = 0; i <= ry; i++) + { + stack_pix_ptr = &stack[i]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + sum_r += src_pix_ptr[R] * (i + 1); + sum_g += src_pix_ptr[G] * (i + 1); + sum_b += src_pix_ptr[B] * (i + 1); + sum_out_r += src_pix_ptr[R]; + sum_out_g += src_pix_ptr[G]; + sum_out_b += src_pix_ptr[B]; + } + for(i = 1; i <= ry; i++) + { + if(i <= hm) src_pix_ptr += stride; + stack_pix_ptr = &stack[i + ry]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + sum_r += src_pix_ptr[R] * (ry + 1 - i); + sum_g += src_pix_ptr[G] * (ry + 1 - i); + sum_b += src_pix_ptr[B] * (ry + 1 - i); + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + } + + stack_ptr = ry; + yp = ry; + if(yp > hm) yp = hm; + src_pix_ptr = img.pix_ptr(x, yp); + dst_pix_ptr = img.pix_ptr(x, 0); + for(y = 0; y < h; y++) + { + dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; + dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; + dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; + dst_pix_ptr += stride; + + sum_r -= sum_out_r; + sum_g -= sum_out_g; + sum_b -= sum_out_b; + + stack_start = stack_ptr + div - ry; + if(stack_start >= div) stack_start -= div; + + stack_pix_ptr = &stack[stack_start]; + sum_out_r -= stack_pix_ptr->r; + sum_out_g -= stack_pix_ptr->g; + sum_out_b -= stack_pix_ptr->b; + + if(yp < hm) + { + src_pix_ptr += stride; + ++yp; + } + + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + sum_r += sum_in_r; + sum_g += sum_in_g; + sum_b += sum_in_b; + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix_ptr = &stack[stack_ptr]; + + sum_out_r += stack_pix_ptr->r; + sum_out_g += stack_pix_ptr->g; + sum_out_b += stack_pix_ptr->b; + sum_in_r -= stack_pix_ptr->r; + sum_in_g -= stack_pix_ptr->g; + sum_in_b -= stack_pix_ptr->b; + } + } + } + } + + + + //=======================================================stack_blur_rgba32 + template + void stack_blur_rgba32(Img& img, unsigned rx, unsigned ry) + { + typedef typename Img::color_type color_type; + typedef typename Img::order_type order_type; + enum order_e + { + R = order_type::R, + G = order_type::G, + B = order_type::B, + A = order_type::A + }; + + unsigned x, y, xp, yp, i; + unsigned stack_ptr; + unsigned stack_start; + + const int8u* src_pix_ptr; + int8u* dst_pix_ptr; + color_type* stack_pix_ptr; + + unsigned sum_r; + unsigned sum_g; + unsigned sum_b; + unsigned sum_a; + unsigned sum_in_r; + unsigned sum_in_g; + unsigned sum_in_b; + unsigned sum_in_a; + unsigned sum_out_r; + unsigned sum_out_g; + unsigned sum_out_b; + unsigned sum_out_a; + + unsigned w = img.width(); + unsigned h = img.height(); + unsigned wm = w - 1; + unsigned hm = h - 1; + + unsigned div; + unsigned mul_sum; + unsigned shr_sum; + + pod_vector stack; + + if(rx > 0) + { + if(rx > 254) rx = 254; + div = rx * 2 + 1; + mul_sum = stack_blur_tables::g_stack_blur8_mul[rx]; + shr_sum = stack_blur_tables::g_stack_blur8_shr[rx]; + stack.allocate(div); + + for(y = 0; y < h; y++) + { + sum_r = + sum_g = + sum_b = + sum_a = + sum_in_r = + sum_in_g = + sum_in_b = + sum_in_a = + sum_out_r = + sum_out_g = + sum_out_b = + sum_out_a = 0; + + src_pix_ptr = img.pix_ptr(0, y); + for(i = 0; i <= rx; i++) + { + stack_pix_ptr = &stack[i]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + stack_pix_ptr->a = src_pix_ptr[A]; + sum_r += src_pix_ptr[R] * (i + 1); + sum_g += src_pix_ptr[G] * (i + 1); + sum_b += src_pix_ptr[B] * (i + 1); + sum_a += src_pix_ptr[A] * (i + 1); + sum_out_r += src_pix_ptr[R]; + sum_out_g += src_pix_ptr[G]; + sum_out_b += src_pix_ptr[B]; + sum_out_a += src_pix_ptr[A]; + } + for(i = 1; i <= rx; i++) + { + if(i <= wm) src_pix_ptr += Img::pix_width; + stack_pix_ptr = &stack[i + rx]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + stack_pix_ptr->a = src_pix_ptr[A]; + sum_r += src_pix_ptr[R] * (rx + 1 - i); + sum_g += src_pix_ptr[G] * (rx + 1 - i); + sum_b += src_pix_ptr[B] * (rx + 1 - i); + sum_a += src_pix_ptr[A] * (rx + 1 - i); + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + sum_in_a += src_pix_ptr[A]; + } + + stack_ptr = rx; + xp = rx; + if(xp > wm) xp = wm; + src_pix_ptr = img.pix_ptr(xp, y); + dst_pix_ptr = img.pix_ptr(0, y); + for(x = 0; x < w; x++) + { + dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; + dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; + dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; + dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum; + dst_pix_ptr += Img::pix_width; + + sum_r -= sum_out_r; + sum_g -= sum_out_g; + sum_b -= sum_out_b; + sum_a -= sum_out_a; + + stack_start = stack_ptr + div - rx; + if(stack_start >= div) stack_start -= div; + stack_pix_ptr = &stack[stack_start]; + + sum_out_r -= stack_pix_ptr->r; + sum_out_g -= stack_pix_ptr->g; + sum_out_b -= stack_pix_ptr->b; + sum_out_a -= stack_pix_ptr->a; + + if(xp < wm) + { + src_pix_ptr += Img::pix_width; + ++xp; + } + + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + stack_pix_ptr->a = src_pix_ptr[A]; + + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + sum_in_a += src_pix_ptr[A]; + sum_r += sum_in_r; + sum_g += sum_in_g; + sum_b += sum_in_b; + sum_a += sum_in_a; + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix_ptr = &stack[stack_ptr]; + + sum_out_r += stack_pix_ptr->r; + sum_out_g += stack_pix_ptr->g; + sum_out_b += stack_pix_ptr->b; + sum_out_a += stack_pix_ptr->a; + sum_in_r -= stack_pix_ptr->r; + sum_in_g -= stack_pix_ptr->g; + sum_in_b -= stack_pix_ptr->b; + sum_in_a -= stack_pix_ptr->a; + } + } + } + + if(ry > 0) + { + if(ry > 254) ry = 254; + div = ry * 2 + 1; + mul_sum = stack_blur_tables::g_stack_blur8_mul[ry]; + shr_sum = stack_blur_tables::g_stack_blur8_shr[ry]; + stack.allocate(div); + + int stride = img.stride(); + for(x = 0; x < w; x++) + { + sum_r = + sum_g = + sum_b = + sum_a = + sum_in_r = + sum_in_g = + sum_in_b = + sum_in_a = + sum_out_r = + sum_out_g = + sum_out_b = + sum_out_a = 0; + + src_pix_ptr = img.pix_ptr(x, 0); + for(i = 0; i <= ry; i++) + { + stack_pix_ptr = &stack[i]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + stack_pix_ptr->a = src_pix_ptr[A]; + sum_r += src_pix_ptr[R] * (i + 1); + sum_g += src_pix_ptr[G] * (i + 1); + sum_b += src_pix_ptr[B] * (i + 1); + sum_a += src_pix_ptr[A] * (i + 1); + sum_out_r += src_pix_ptr[R]; + sum_out_g += src_pix_ptr[G]; + sum_out_b += src_pix_ptr[B]; + sum_out_a += src_pix_ptr[A]; + } + for(i = 1; i <= ry; i++) + { + if(i <= hm) src_pix_ptr += stride; + stack_pix_ptr = &stack[i + ry]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + stack_pix_ptr->a = src_pix_ptr[A]; + sum_r += src_pix_ptr[R] * (ry + 1 - i); + sum_g += src_pix_ptr[G] * (ry + 1 - i); + sum_b += src_pix_ptr[B] * (ry + 1 - i); + sum_a += src_pix_ptr[A] * (ry + 1 - i); + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + sum_in_a += src_pix_ptr[A]; + } + + stack_ptr = ry; + yp = ry; + if(yp > hm) yp = hm; + src_pix_ptr = img.pix_ptr(x, yp); + dst_pix_ptr = img.pix_ptr(x, 0); + for(y = 0; y < h; y++) + { + dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; + dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; + dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; + dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum; + dst_pix_ptr += stride; + + sum_r -= sum_out_r; + sum_g -= sum_out_g; + sum_b -= sum_out_b; + sum_a -= sum_out_a; + + stack_start = stack_ptr + div - ry; + if(stack_start >= div) stack_start -= div; + + stack_pix_ptr = &stack[stack_start]; + sum_out_r -= stack_pix_ptr->r; + sum_out_g -= stack_pix_ptr->g; + sum_out_b -= stack_pix_ptr->b; + sum_out_a -= stack_pix_ptr->a; + + if(yp < hm) + { + src_pix_ptr += stride; + ++yp; + } + + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + stack_pix_ptr->a = src_pix_ptr[A]; + + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + sum_in_a += src_pix_ptr[A]; + sum_r += sum_in_r; + sum_g += sum_in_g; + sum_b += sum_in_b; + sum_a += sum_in_a; + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix_ptr = &stack[stack_ptr]; + + sum_out_r += stack_pix_ptr->r; + sum_out_g += stack_pix_ptr->g; + sum_out_b += stack_pix_ptr->b; + sum_out_a += stack_pix_ptr->a; + sum_in_r -= stack_pix_ptr->r; + sum_in_g -= stack_pix_ptr->g; + sum_in_b -= stack_pix_ptr->b; + sum_in_a -= stack_pix_ptr->a; + } + } + } + } + + + + //===========================================================recursive_blur + template class recursive_blur + { + public: + typedef ColorT color_type; + typedef CalculatorT calculator_type; + typedef typename color_type::value_type value_type; + typedef typename calculator_type::value_type calc_type; + + //-------------------------------------------------------------------- + template void blur_x(Img& img, double radius) + { + if(radius < 0.62) return; + if(img.width() < 3) return; + + calc_type s = calc_type(radius * 0.5); + calc_type q = calc_type((s < 2.5) ? + 3.97156 - 4.14554 * std::sqrt(1 - 0.26891 * s) : + 0.98711 * s - 0.96330); + + calc_type q2 = calc_type(q * q); + calc_type q3 = calc_type(q2 * q); + + calc_type b0 = calc_type(1.0 / (1.578250 + + 2.444130 * q + + 1.428100 * q2 + + 0.422205 * q3)); + + calc_type b1 = calc_type( 2.44413 * q + + 2.85619 * q2 + + 1.26661 * q3); + + calc_type b2 = calc_type(-1.42810 * q2 + + -1.26661 * q3); + + calc_type b3 = calc_type(0.422205 * q3); + + calc_type b = calc_type(1 - (b1 + b2 + b3) * b0); + + b1 *= b0; + b2 *= b0; + b3 *= b0; + + int w = img.width(); + int h = img.height(); + int wm = w-1; + int x, y; + + m_sum1.allocate(w); + m_sum2.allocate(w); + m_buf.allocate(w); + + for(y = 0; y < h; y++) + { + calculator_type c; + c.from_pix(img.pixel(0, y)); + m_sum1[0].calc(b, b1, b2, b3, c, c, c, c); + c.from_pix(img.pixel(1, y)); + m_sum1[1].calc(b, b1, b2, b3, c, m_sum1[0], m_sum1[0], m_sum1[0]); + c.from_pix(img.pixel(2, y)); + m_sum1[2].calc(b, b1, b2, b3, c, m_sum1[1], m_sum1[0], m_sum1[0]); + + for(x = 3; x < w; ++x) + { + c.from_pix(img.pixel(x, y)); + m_sum1[x].calc(b, b1, b2, b3, c, m_sum1[x-1], m_sum1[x-2], m_sum1[x-3]); + } + + m_sum2[wm ].calc(b, b1, b2, b3, m_sum1[wm ], m_sum1[wm ], m_sum1[wm], m_sum1[wm]); + m_sum2[wm-1].calc(b, b1, b2, b3, m_sum1[wm-1], m_sum2[wm ], m_sum2[wm], m_sum2[wm]); + m_sum2[wm-2].calc(b, b1, b2, b3, m_sum1[wm-2], m_sum2[wm-1], m_sum2[wm], m_sum2[wm]); + m_sum2[wm ].to_pix(m_buf[wm ]); + m_sum2[wm-1].to_pix(m_buf[wm-1]); + m_sum2[wm-2].to_pix(m_buf[wm-2]); + + for(x = wm-3; x >= 0; --x) + { + m_sum2[x].calc(b, b1, b2, b3, m_sum1[x], m_sum2[x+1], m_sum2[x+2], m_sum2[x+3]); + m_sum2[x].to_pix(m_buf[x]); + } + img.copy_color_hspan(0, y, w, &m_buf[0]); + } + } + + //-------------------------------------------------------------------- + template void blur_y(Img& img, double radius) + { + pixfmt_transposer img2(img); + blur_x(img2, radius); + } + + //-------------------------------------------------------------------- + template void blur(Img& img, double radius) + { + blur_x(img, radius); + pixfmt_transposer img2(img); + blur_x(img2, radius); + } + + private: + agg::pod_vector m_sum1; + agg::pod_vector m_sum2; + agg::pod_vector m_buf; + }; + + + //=================================================recursive_blur_calc_rgba + template struct recursive_blur_calc_rgba + { + typedef T value_type; + typedef recursive_blur_calc_rgba self_type; + + value_type r,g,b,a; + + template + AGG_INLINE void from_pix(const ColorT& c) + { + r = c.r; + g = c.g; + b = c.b; + a = c.a; + } + + AGG_INLINE void calc(value_type b1, + value_type b2, + value_type b3, + value_type b4, + const self_type& c1, + const self_type& c2, + const self_type& c3, + const self_type& c4) + { + r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r; + g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g; + b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b; + a = b1*c1.a + b2*c2.a + b3*c3.a + b4*c4.a; + } + + template + AGG_INLINE void to_pix(ColorT& c) const + { + typedef typename ColorT::value_type cv_type; + c.r = cv_type(r); + c.g = cv_type(g); + c.b = cv_type(b); + c.a = cv_type(a); + } + }; + + + //=================================================recursive_blur_calc_rgb + template struct recursive_blur_calc_rgb + { + typedef T value_type; + typedef recursive_blur_calc_rgb self_type; + + value_type r,g,b; + + template + AGG_INLINE void from_pix(const ColorT& c) + { + r = c.r; + g = c.g; + b = c.b; + } + + AGG_INLINE void calc(value_type b1, + value_type b2, + value_type b3, + value_type b4, + const self_type& c1, + const self_type& c2, + const self_type& c3, + const self_type& c4) + { + r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r; + g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g; + b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b; + } + + template + AGG_INLINE void to_pix(ColorT& c) const + { + typedef typename ColorT::value_type cv_type; + c.r = cv_type(r); + c.g = cv_type(g); + c.b = cv_type(b); + } + }; + + + //================================================recursive_blur_calc_gray + template struct recursive_blur_calc_gray + { + typedef T value_type; + typedef recursive_blur_calc_gray self_type; + + value_type v; + + template + AGG_INLINE void from_pix(const ColorT& c) + { + v = c.v; + } + + AGG_INLINE void calc(value_type b1, + value_type b2, + value_type b3, + value_type b4, + const self_type& c1, + const self_type& c2, + const self_type& c3, + const self_type& c4) + { + v = b1*c1.v + b2*c2.v + b3*c3.v + b4*c4.v; + } + + template + AGG_INLINE void to_pix(ColorT& c) const + { + typedef typename ColorT::value_type cv_type; + c.v = cv_type(v); + } + }; + + //================================================slight_blur + // Special-purpose filter for applying a Gaussian blur with a radius small enough + // that the blur only affects adjacent pixels. A Gaussian curve with a standard + // deviation of r/2 is used, as per the HTML/CSS spec. At 3 standard deviations, + // the contribution drops to less than 0.005, i.e. less than half a percent, + // therefore the radius can be at least 1.33 before errors become significant. + // This filter is useful for smoothing artifacts caused by detail rendered + // at the pixel scale, e.g. single-pixel lines. Note that the filter should + // only be used with premultiplied pixel formats (or those without alpha). + // See the "line_thickness" example for a demonstration. + template + class slight_blur + { + public: + typedef typename PixFmt::pixel_type pixel_type; + typedef typename PixFmt::value_type value_type; + typedef typename PixFmt::order_type order_type; + + slight_blur(double r = 1.33) + { + radius(r); + } + + void radius(double r) + { + if (r > 0) + { + // Sample the gaussian curve at 0 and r/2 standard deviations. + // At 3 standard deviations, the response is < 0.005. + double pi = 3.14159; + double n = 2 / r; + m_g0 = 1 / std::sqrt(2 * pi); + m_g1 = m_g0 * exp(-n * n); + + // Normalize. + double sum = m_g0 + 2 * m_g1; + m_g0 /= sum; + m_g1 /= sum; + } + else + { + m_g0 = 1; + m_g1 = 0; + } + } + + void blur(PixFmt& img, rect_i bounds) + { + // Make sure we stay within the image area. + bounds.clip(rect_i(0, 0, img.width() - 1, img.height() - 1)); + + int w = bounds.x2 - bounds.x1 + 1; + int h = bounds.y2 - bounds.y1 + 1; + + if (w < 3 || h < 3) return; + + // Allocate 3 rows of buffer space. + m_buf.allocate(w * 3); + + // Set up row pointers + pixel_type * begin = &m_buf[0]; + pixel_type * r0 = begin; + pixel_type * r1 = r0 + w; + pixel_type * r2 = r1 + w; + pixel_type * end = r2 + w; + + // Horizontally blur the first two input rows. + calc_row(img, bounds.x1, bounds.y1, w, r0); + std::memcpy(r1, r0, w * sizeof(pixel_type)); + + for (int y = 0; ; ) + { + // Get pointer to first pixel. + pixel_type* p = img.pix_value_ptr(bounds.x1, bounds.y1 + y, bounds.x1 + w); + + // Horizontally blur the row below. + if (y + 1 < h) + { + calc_row(img, bounds.x1, bounds.y1 + y + 1, w, r2); + } + else + { + std::memcpy(r2, r1, w * sizeof(pixel_type)); // duplicate bottom row + } + + // Combine blurred rows into destination. + for (int x = 0; x < w; ++x) + { + calc_pixel(*r0++, *r1++, *r2++, *p++); + } + + if (++y >= h) break; + + // Wrap bottom row pointer around to top of buffer. + if (r2 == end) r2 = begin; + else if (r1 == end) r1 = begin; + else if (r0 == end) r0 = begin; + } + } + + private: + void calc_row(PixFmt& img, int x, int y, int w, pixel_type* row) + { + const int wm = w - 1; + + pixel_type* p = img.pix_value_ptr(x, y, w); + + pixel_type c[3]; + pixel_type* p0 = c; + pixel_type* p1 = c + 1; + pixel_type* p2 = c + 2; + pixel_type* end = c + 3; + *p0 = *p1 = *p; + + for (int x = 0; x < wm; ++x) + { + *p2 = *(p = p->next()); + + calc_pixel(*p0++, *p1++, *p2++, *row++); + + if (p0 == end) p0 = c; + else if (p1 == end) p1 = c; + else if (p2 == end) p2 = c; + } + + calc_pixel(*p0, *p1, *p1, *row); + } + + void calc_pixel( + pixel_type const & c1, + pixel_type const & c2, + pixel_type const & c3, + pixel_type & x) + { + calc_pixel(c1, c2, c3, x, PixFmt::pixfmt_category()); + } + + void calc_pixel( + pixel_type const & c1, + pixel_type const & c2, + pixel_type const & c3, + pixel_type & x, + pixfmt_gray_tag) + { + x.c[0] = calc_value(c1.c[0], c2.c[0], c3.c[0]); + } + + void calc_pixel( + pixel_type const & c1, + pixel_type const & c2, + pixel_type const & c3, + pixel_type & x, + pixfmt_rgb_tag) + { + enum { R = order_type::R, G = order_type::G, B = order_type::B }; + x.c[R] = calc_value(c1.c[R], c2.c[R], c3.c[R]); + x.c[G] = calc_value(c1.c[G], c2.c[G], c3.c[G]); + x.c[B] = calc_value(c1.c[B], c2.c[B], c3.c[B]); + } + + void calc_pixel( + pixel_type const & c1, + pixel_type const & c2, + pixel_type const & c3, + pixel_type & x, + pixfmt_rgba_tag) + { + enum { R = order_type::R, G = order_type::G, B = order_type::B, A = order_type::A }; + x.c[R] = calc_value(c1.c[R], c2.c[R], c3.c[R]); + x.c[G] = calc_value(c1.c[G], c2.c[G], c3.c[G]); + x.c[B] = calc_value(c1.c[B], c2.c[B], c3.c[B]); + x.c[A] = calc_value(c1.c[A], c2.c[A], c3.c[A]); + } + + value_type calc_value(value_type v1, value_type v2, value_type v3) + { + return value_type(m_g1 * v1 + m_g0 * v2 + m_g1 * v3); + } + + double m_g0, m_g1; + pod_vector m_buf; + }; + + // Helper functions for applying blur to a surface without having to create an intermediate object. + + template + void apply_slight_blur(PixFmt& img, const rect_i& bounds, double r = 1) + { + if (r > 0) slight_blur(r).blur(img, bounds); + } + + template + void apply_slight_blur(PixFmt& img, double r = 1) + { + if (r > 0) slight_blur(r).blur(img, rect_i(0, 0, img.width() - 1, img.height() - 1)); + } + + template + void apply_slight_blur(renderer_base& img, const rect_i& bounds, double r = 1) + { + if (r > 0) slight_blur(r).blur(img.ren(), bounds); + } + + template + void apply_slight_blur(renderer_base& img, double r = 1) + { + if (r > 0) slight_blur(r).blur(img.ren(), img.clip_box()); + } +} + + + + +#endif diff --git a/agg2/include/agg_bounding_rect.h b/agg/include/agg_bounding_rect.h similarity index 91% rename from agg2/include/agg_bounding_rect.h rename to agg/include/agg_bounding_rect.h index 5715a58..f13b863 100644 --- a/agg2/include/agg_bounding_rect.h +++ b/agg/include/agg_bounding_rect.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -35,6 +35,11 @@ namespace agg 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]); @@ -74,6 +79,11 @@ namespace agg 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))) diff --git a/agg2/include/agg_bspline.h b/agg/include/agg_bspline.h similarity index 87% rename from agg2/include/agg_bspline.h rename to agg/include/agg_bspline.h index 1ccdefb..2c1ed9a 100644 --- a/agg2/include/agg_bspline.h +++ b/agg/include/agg_bspline.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -20,7 +20,7 @@ #ifndef AGG_BSPLINE_INCLUDED #define AGG_BSPLINE_INCLUDED -#include "agg_basics.h" +#include "agg_array.h" namespace agg { @@ -40,7 +40,6 @@ namespace agg class bspline { public: - ~bspline(); bspline(); bspline(int num); bspline(int num, const double* x, const double* y); @@ -63,12 +62,12 @@ namespace agg 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; - double* m_am; - mutable int m_last_idx; + int m_max; + int m_num; + double* m_x; + double* m_y; + pod_array m_am; + mutable int m_last_idx; }; diff --git a/agg2/include/agg_clip_liang_barsky.h b/agg/include/agg_clip_liang_barsky.h similarity index 51% rename from agg2/include/agg_clip_liang_barsky.h rename to agg/include/agg_clip_liang_barsky.h index 897c0f2..4b5fedb 100644 --- a/agg2/include/agg_clip_liang_barsky.h +++ b/agg/include/agg_clip_liang_barsky.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -24,6 +24,60 @@ 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 + inline unsigned clipping_flags(T x, T y, const rect_base& clip_box) + { + return (x > clip_box.x2) | + ((y > clip_box.y2) << 1) | + ((x < clip_box.x1) << 2) | + ((y < clip_box.y1) << 3); + } + + //--------------------------------------------------------clipping_flags_x + template + inline unsigned clipping_flags_x(T x, const rect_base& clip_box) + { + return (x > clip_box.x2) | ((x < clip_box.x1) << 2); + } + + + //--------------------------------------------------------clipping_flags_y + template + inline unsigned clipping_flags_y(T y, const rect_base& clip_box) + { + return ((y > clip_box.y2) << 1) | ((y < clip_box.y1) << 3); + } + + //-------------------------------------------------------clip_liang_barsky template inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2, @@ -173,8 +227,107 @@ namespace agg } return np; } - + + + //---------------------------------------------------------------------------- + template + bool clip_move_point(T x1, T y1, T x2, T y2, + const rect_base& 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 + unsigned clip_line_segment(T* x1, T* y1, T* x2, T* y2, + const rect_base& clip_box) + { + unsigned f1 = clipping_flags(*x1, *y1, clip_box); + unsigned f2 = clipping_flags(*x2, *y2, clip_box); + unsigned ret = 0; + + if((f2 | f1) == 0) + { + // Fully visible + return 0; + } + + if((f1 & clipping_flags_x_clipped) != 0 && + (f1 & clipping_flags_x_clipped) == (f2 & clipping_flags_x_clipped)) + { + // Fully clipped + return 4; + } + + if((f1 & clipping_flags_y_clipped) != 0 && + (f1 & clipping_flags_y_clipped) == (f2 & clipping_flags_y_clipped)) + { + // Fully clipped + return 4; + } + + T tx1 = *x1; + T ty1 = *y1; + T tx2 = *x2; + T ty2 = *y2; + if(f1) + { + if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x1, y1, f1)) + { + return 4; + } + if(*x1 == *x2 && *y1 == *y2) + { + return 4; + } + ret |= 1; + } + if(f2) + { + if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x2, y2, f2)) + { + return 4; + } + if(*x1 == *x2 && *y1 == *y2) + { + return 4; + } + ret |= 2; + } + return ret; + } + } + #endif diff --git a/agg/include/agg_color_gray.h b/agg/include/agg_color_gray.h new file mode 100644 index 0000000..f66588c --- /dev/null +++ b/agg/include/agg_color_gray.h @@ -0,0 +1,1047 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- +// +// color types gray8, gray16 +// +//---------------------------------------------------------------------------- + +#ifndef AGG_COLOR_GRAY_INCLUDED +#define AGG_COLOR_GRAY_INCLUDED + +#include "agg_basics.h" +#include "agg_color_rgba.h" + +namespace agg +{ + + //===================================================================gray8 + template + struct gray8T + { + typedef int8u value_type; + typedef int32u calc_type; + typedef int32 long_type; + enum base_scale_e + { + base_shift = 8, + base_scale = 1 << base_shift, + base_mask = base_scale - 1, + base_MSB = 1 << (base_shift - 1) + }; + typedef gray8T self_type; + + value_type v; + value_type a; + + static value_type luminance(const rgba& c) + { + // Calculate grayscale value as per ITU-R BT.709. + return value_type(uround((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * base_mask)); + } + + static value_type luminance(const rgba8& c) + { + // Calculate grayscale value as per ITU-R BT.709. + return value_type((55u * c.r + 184u * c.g + 18u * c.b) >> 8); + } + + static void convert(gray8T& dst, const gray8T& src) + { + dst.v = sRGB_conv::rgb_from_sRGB(src.v); + dst.a = src.a; + } + + static void convert(gray8T& dst, const gray8T& src) + { + dst.v = sRGB_conv::rgb_to_sRGB(src.v); + dst.a = src.a; + } + + static void convert(gray8T& dst, const rgba8& src) + { + dst.v = luminance(src); + dst.a = src.a; + } + + static void convert(gray8T& dst, const srgba8& src) + { + // The RGB weights are only valid for linear values. + convert(dst, rgba8(src)); + } + + static void convert(gray8T& dst, const rgba8& src) + { + dst.v = sRGB_conv::rgb_to_sRGB(luminance(src)); + dst.a = src.a; + } + + static void convert(gray8T& dst, const srgba8& src) + { + // The RGB weights are only valid for linear values. + convert(dst, rgba8(src)); + } + + //-------------------------------------------------------------------- + gray8T() {} + + //-------------------------------------------------------------------- + explicit 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 rgba& c) : + v(luminance(c)), + a(value_type(uround(c.a * base_mask))) {} + + //-------------------------------------------------------------------- + template + gray8T(const gray8T& c) + { + convert(*this, c); + } + + //-------------------------------------------------------------------- + template + gray8T(const rgba8T& c) + { + convert(*this, c); + } + + //-------------------------------------------------------------------- + template + T convert_from_sRGB() const + { + typename T::value_type y = sRGB_conv::rgb_from_sRGB(v); + return T(y, y, y, sRGB_conv::alpha_from_sRGB(a)); + } + + template + T convert_to_sRGB() const + { + typename T::value_type y = sRGB_conv::rgb_to_sRGB(v); + return T(y, y, y, sRGB_conv::alpha_to_sRGB(a)); + } + + //-------------------------------------------------------------------- + rgba8 make_rgba8(const linear&) const + { + return rgba8(v, v, v, a); + } + + rgba8 make_rgba8(const sRGB&) const + { + return convert_from_sRGB(); + } + + operator rgba8() const + { + return make_rgba8(Colorspace()); + } + + //-------------------------------------------------------------------- + srgba8 make_srgba8(const linear&) const + { + return convert_to_sRGB(); + } + + srgba8 make_srgba8(const sRGB&) const + { + return srgba8(v, v, v, a); + } + + operator srgba8() const + { + return make_rgba8(Colorspace()); + } + + //-------------------------------------------------------------------- + rgba16 make_rgba16(const linear&) const + { + rgba16::value_type rgb = (v << 8) | v; + return rgba16(rgb, rgb, rgb, (a << 8) | a); + } + + rgba16 make_rgba16(const sRGB&) const + { + return convert_from_sRGB(); + } + + operator rgba16() const + { + return make_rgba16(Colorspace()); + } + + //-------------------------------------------------------------------- + rgba32 make_rgba32(const linear&) const + { + rgba32::value_type v32 = v / 255.0f; + return rgba32(v32, v32, v32, a / 255.0f); + } + + rgba32 make_rgba32(const sRGB&) const + { + return convert_from_sRGB(); + } + + operator rgba32() const + { + return make_rgba32(Colorspace()); + } + + //-------------------------------------------------------------------- + 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 empty_value() + { + return 0; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type full_value() + { + return base_mask; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_transparent() const + { + return a == 0; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_opaque() const + { + return a == base_mask; + } + + //-------------------------------------------------------------------- + // Fixed-point multiply, exact over int8u. + static AGG_INLINE value_type multiply(value_type a, value_type b) + { + calc_type t = a * b + base_MSB; + return value_type(((t >> base_shift) + t) >> base_shift); + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type demultiply(value_type a, value_type b) + { + if (a * b == 0) + { + return 0; + } + else if (a >= b) + { + return base_mask; + } + else return value_type((a * base_mask + (b >> 1)) / b); + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downscale(T a) + { + return a >> base_shift; + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downshift(T a, unsigned n) + { + return a >> n; + } + + //-------------------------------------------------------------------- + // 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 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); + } + + //-------------------------------------------------------------------- + // Interpolate p to q by a. + static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a) + { + int t = (q - p) * a + base_MSB - (p > q); + return value_type(p + (((t >> base_shift) + t) >> base_shift)); + } + + //-------------------------------------------------------------------- + self_type& clear() + { + v = a = 0; + return *this; + } + + //-------------------------------------------------------------------- + self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + 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)); + return *this; + } + + //-------------------------------------------------------------------- + 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); + } + return *this; + } + + //-------------------------------------------------------------------- + self_type& demultiply() + { + if (a < base_mask) + { + if (a == 0) + { + v = 0; + } + else + { + calc_type v_ = (calc_type(v) * base_mask) / a; + v = value_type((v_ > base_mask) ? (value_type)base_mask : v_); + } + } + return *this; + } + + //-------------------------------------------------------------------- + self_type gradient(self_type c, double k) const + { + self_type ret; + calc_type ik = uround(k * base_scale); + ret.v = lerp(v, c.v, ik); + ret.a = lerp(a, c.a, ik); + return ret; + } + + //-------------------------------------------------------------------- + AGG_INLINE void add(const self_type& c, unsigned cover) + { + calc_type cv, ca; + if (cover == cover_mask) + { + if (c.a == base_mask) + { + *this = c; + return; + } + else + { + cv = v + c.v; + ca = a + c.a; + } + } + else + { + cv = v + mult_cover(c.v, cover); + ca = a + mult_cover(c.a, cover); + } + v = (value_type)((cv > calc_type(base_mask)) ? calc_type(base_mask) : cv); + a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca); + } + + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0); } + }; + + typedef gray8T gray8; + typedef gray8T sgray8; + + + //==================================================================gray16 + struct gray16 + { + typedef int16u value_type; + typedef int32u calc_type; + typedef int64 long_type; + enum base_scale_e + { + base_shift = 16, + base_scale = 1 << base_shift, + base_mask = base_scale - 1, + base_MSB = 1 << (base_shift - 1) + }; + typedef gray16 self_type; + + value_type v; + value_type a; + + static value_type luminance(const rgba& c) + { + // Calculate grayscale value as per ITU-R BT.709. + return value_type(uround((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * base_mask)); + } + + static value_type luminance(const rgba16& c) + { + // Calculate grayscale value as per ITU-R BT.709. + 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 srgba8& c) + { + return luminance(rgba16(c)); + } + + static value_type luminance(const rgba32& c) + { + return luminance(rgba(c)); + } + + //-------------------------------------------------------------------- + gray16() {} + + //-------------------------------------------------------------------- + explicit gray16(unsigned v_, unsigned a_ = base_mask) : + v(int16u(v_)), a(int16u(a_)) {} + + //-------------------------------------------------------------------- + gray16(const self_type& c, unsigned a_) : + v(c.v), a(value_type(a_)) {} + + //-------------------------------------------------------------------- + gray16(const rgba& c) : + v(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 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 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::rgb_from_sRGB(c.v)), + a(sRGB_conv::alpha_from_sRGB(c.a)) {} + + //-------------------------------------------------------------------- + operator rgba8() const + { + return rgba8(v >> 8, v >> 8, v >> 8, a >> 8); + } + + //-------------------------------------------------------------------- + operator srgba8() const + { + value_type y = sRGB_conv::rgb_to_sRGB(v); + return srgba8(y, y, y, sRGB_conv::alpha_to_sRGB(a)); + } + + //-------------------------------------------------------------------- + operator rgba16() const + { + return rgba16(v, v, v, a); + } + + //-------------------------------------------------------------------- + operator rgba32() const + { + rgba32::value_type v32 = v / 65535.0f; + return rgba32(v32, v32, v32, a / 65535.0f); + } + + //-------------------------------------------------------------------- + operator gray8() const + { + return gray8(v >> 8, a >> 8); + } + + //-------------------------------------------------------------------- + operator sgray8() const + { + return sgray8( + sRGB_conv::rgb_to_sRGB(v), + sRGB_conv::alpha_to_sRGB(a)); + } + + //-------------------------------------------------------------------- + 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 empty_value() + { + return 0; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type full_value() + { + return base_mask; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_transparent() const + { + return a == 0; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_opaque() const + { + return a == base_mask; + } + + //-------------------------------------------------------------------- + // Fixed-point multiply, exact over int16u. + static AGG_INLINE value_type multiply(value_type a, value_type b) + { + calc_type t = a * b + base_MSB; + return value_type(((t >> base_shift) + t) >> base_shift); + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type demultiply(value_type a, value_type b) + { + if (a * b == 0) + { + return 0; + } + else if (a >= b) + { + return base_mask; + } + else return value_type((a * base_mask + (b >> 1)) / b); + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downscale(T a) + { + return a >> base_shift; + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downshift(T a, unsigned n) + { + return a >> n; + } + + //-------------------------------------------------------------------- + // 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 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); + } + + //-------------------------------------------------------------------- + // Interpolate p to q by a. + static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a) + { + int t = (q - p) * a + base_MSB - (p > q); + return value_type(p + (((t >> base_shift) + t) >> base_shift)); + } + + //-------------------------------------------------------------------- + self_type& clear() + { + v = a = 0; + return *this; + } + + //-------------------------------------------------------------------- + self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + 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)); + return *this; + } + + //-------------------------------------------------------------------- + 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); + } + return *this; + } + + //-------------------------------------------------------------------- + self_type& demultiply() + { + if (a < base_mask) + { + if (a == 0) + { + v = 0; + } + else + { + calc_type v_ = (calc_type(v) * base_mask) / a; + v = (v_ > base_mask) ? value_type(base_mask) : value_type(v_); + } + } + return *this; + } + + //-------------------------------------------------------------------- + self_type gradient(self_type c, double k) const + { + self_type ret; + calc_type ik = uround(k * base_scale); + ret.v = lerp(v, c.v, ik); + ret.a = lerp(a, c.a, ik); + return ret; + } + + //-------------------------------------------------------------------- + AGG_INLINE void add(const self_type& c, unsigned cover) + { + calc_type cv, ca; + if (cover == cover_mask) + { + if (c.a == base_mask) + { + *this = c; + return; + } + else + { + cv = v + c.v; + ca = a + c.a; + } + } + else + { + cv = v + mult_cover(c.v, cover); + ca = a + mult_cover(c.a, cover); + } + v = (value_type)((cv > calc_type(base_mask)) ? calc_type(base_mask) : cv); + a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca); + } + + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0); } + }; + + + //===================================================================gray32 + struct gray32 + { + typedef float value_type; + typedef double calc_type; + typedef double long_type; + typedef gray32 self_type; + + value_type v; + value_type a; + + // Calculate grayscale value as per ITU-R BT.709. + static value_type luminance(double r, double g, double b) + { + 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 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 rgba16& c) + { + return luminance(c.r / 65535.0, c.g / 65535.0, c.g / 65535.0); + } + + //-------------------------------------------------------------------- + gray32() {} + + //-------------------------------------------------------------------- + explicit 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 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 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 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 sgray8& c) : + v(sRGB_conv::rgb_from_sRGB(c.v)), + a(sRGB_conv::alpha_from_sRGB(c.a)) {} + + //-------------------------------------------------------------------- + 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 gray8() const + { + return gray8(uround(v * 255.0), uround(a * 255.0)); + } + + //-------------------------------------------------------------------- + operator sgray8() const + { + // Return (non-premultiplied) sRGB values. + return sgray8( + sRGB_conv::rgb_to_sRGB(v), + sRGB_conv::alpha_to_sRGB(a)); + } + + //-------------------------------------------------------------------- + operator gray16() const + { + return gray16(uround(v * 65535.0), uround(a * 65535.0)); + } + + //-------------------------------------------------------------------- + operator rgba8() const + { + rgba8::value_type y = uround(v * 255.0); + return rgba8(y, y, y, uround(a * 255.0)); + } + + //-------------------------------------------------------------------- + operator srgba8() const + { + srgba8::value_type y = sRGB_conv::rgb_to_sRGB(v); + return srgba8(y, y, y, sRGB_conv::alpha_to_sRGB(a)); + } + + //-------------------------------------------------------------------- + operator rgba16() const + { + rgba16::value_type y = uround(v * 65535.0); + return rgba16(y, y, y, uround(a * 65535.0)); + } + + //-------------------------------------------------------------------- + operator rgba32() const + { + return rgba32(v, v, v, 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 empty_value() + { + return 0; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type full_value() + { + return 1; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_transparent() const + { + return a <= 0; + } + + //-------------------------------------------------------------------- + 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 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); + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downscale(T a) + { + return a; + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downshift(T a, unsigned n) + { + return n > 0 ? a / (1 << n) : a; + } + + //-------------------------------------------------------------------- + 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)); + } + + //-------------------------------------------------------------------- + // 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 (1 - a) * p + q; // more accurate than "p + q - p * a" + } + + //-------------------------------------------------------------------- + // Interpolate p to q by a. + static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a) + { + // The form "p + a * (q - p)" avoids a multiplication, but may produce an + // inaccurate result. For example, "p + (q - p)" may not be exactly equal + // to q. Therefore, stick to the basic expression, which at least produces + // the correct result at either extreme. + return (1 - a) * p + a * q; + } + + //-------------------------------------------------------------------- + self_type& clear() + { + v = a = 0; + return *this; + } + + //-------------------------------------------------------------------- + self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + self_type& opacity(double a_) + { + if (a_ < 0) a = 0; + else if (a_ > 1) a = 1; + else a = value_type(a_); + return *this; + } + + //-------------------------------------------------------------------- + double opacity() const + { + return a; + } + + + //-------------------------------------------------------------------- + self_type& premultiply() + { + 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; + 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)); + } + + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0); } + }; +} + + + + +#endif diff --git a/agg/include/agg_color_rgba.h b/agg/include/agg_color_rgba.h new file mode 100644 index 0000000..0f5ab8a --- /dev/null +++ b/agg/include/agg_color_rgba.h @@ -0,0 +1,1353 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_COLOR_RGBA_INCLUDED +#define AGG_COLOR_RGBA_INCLUDED + +#include +#include "agg_basics.h" +#include "agg_gamma_lut.h" + +namespace agg +{ + // Supported component orders for RGB and RGBA pixel formats + //======================================================================= + struct order_rgb { enum rgb_e { R=0, G=1, B=2, N=3 }; }; + struct order_bgr { enum bgr_e { B=0, G=1, R=2, N=3 }; }; + struct order_rgba { enum rgba_e { R=0, G=1, B=2, A=3, N=4 }; }; + struct order_argb { enum argb_e { A=0, R=1, G=2, B=3, N=4 }; }; + struct order_abgr { enum abgr_e { A=0, B=1, G=2, R=3, N=4 }; }; + struct order_bgra { enum bgra_e { B=0, G=1, R=2, A=3, N=4 }; }; + + // Colorspace tag types. + struct linear {}; + struct sRGB {}; + + //====================================================================rgba + struct rgba + { + typedef double value_type; + + double r; + double g; + double b; + double a; + + //-------------------------------------------------------------------- + rgba() {} + + //-------------------------------------------------------------------- + rgba(double r_, double g_, double b_, double a_=1.0) : + r(r_), g(g_), b(b_), a(a_) {} + + //-------------------------------------------------------------------- + rgba(const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) {} + + //-------------------------------------------------------------------- + rgba& clear() + { + r = g = b = a = 0; + return *this; + } + + //-------------------------------------------------------------------- + rgba& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + rgba& opacity(double a_) + { + if (a_ < 0) a = 0; + else if (a_ > 1) a = 1; + else a = a_; + return *this; + } + + //-------------------------------------------------------------------- + double opacity() const + { + return a; + } + + //-------------------------------------------------------------------- + rgba& premultiply() + { + r *= a; + g *= a; + b *= a; + return *this; + } + + //-------------------------------------------------------------------- + rgba& premultiply(double a_) + { + if (a <= 0 || a_ <= 0) + { + r = g = b = a = 0; + } + else + { + a_ /= a; + r *= a_; + g *= a_; + b *= a_; + a = a_; + } + return *this; + } + + //-------------------------------------------------------------------- + rgba& demultiply() + { + if (a == 0) + { + r = g = b = 0; + } + else + { + double a_ = 1.0 / a; + r *= a_; + g *= a_; + b *= a_; + } + return *this; + } + + + //-------------------------------------------------------------------- + rgba gradient(rgba c, double k) const + { + rgba ret; + ret.r = r + (c.r - r) * k; + ret.g = g + (c.g - g) * k; + ret.b = b + (c.b - b) * k; + ret.a = a + (c.a - a) * k; + return ret; + } + + rgba& operator+=(const rgba& c) + { + r += c.r; + g += c.g; + b += c.b; + a += c.a; + return *this; + } + + rgba& operator*=(double k) + { + r *= k; + g *= k; + b *= k; + a *= k; + return *this; + } + + //-------------------------------------------------------------------- + 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); + } + + }; + + inline rgba operator+(const rgba& a, const rgba& b) + { + return rgba(a) += b; + } + + inline rgba operator*(const rgba& a, double b) + { + return rgba(a) *= b; + } + + //------------------------------------------------------------------------ + inline rgba rgba::from_wavelength(double wl, double gamma) + { + rgba t(0.0, 0.0, 0.0); + + if (wl >= 380.0 && wl <= 440.0) + { + t.r = -1.0 * (wl - 440.0) / (440.0 - 380.0); + t.b = 1.0; + } + else if (wl >= 440.0 && wl <= 490.0) + { + t.g = (wl - 440.0) / (490.0 - 440.0); + t.b = 1.0; + } + else if (wl >= 490.0 && wl <= 510.0) + { + t.g = 1.0; + t.b = -1.0 * (wl - 510.0) / (510.0 - 490.0); + } + else if (wl >= 510.0 && wl <= 580.0) + { + t.r = (wl - 510.0) / (580.0 - 510.0); + t.g = 1.0; + } + else if (wl >= 580.0 && wl <= 645.0) + { + t.r = 1.0; + t.g = -1.0 * (wl - 645.0) / (645.0 - 580.0); + } + else if (wl >= 645.0 && wl <= 780.0) + { + t.r = 1.0; + } + + double s = 1.0; + if (wl > 700.0) s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0); + else if (wl < 420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0); + + t.r = std::pow(t.r * s, gamma); + t.g = std::pow(t.g * s, gamma); + t.b = std::pow(t.b * s, gamma); + return t; + } + + inline rgba rgba_pre(double r, double g, double b, double a) + { + return rgba(r, g, b, a).premultiply(); + } + + + //===================================================================rgba8 + template + struct rgba8T + { + typedef int8u value_type; + typedef int32u calc_type; + typedef int32 long_type; + enum base_scale_e + { + base_shift = 8, + base_scale = 1 << base_shift, + base_mask = base_scale - 1, + base_MSB = 1 << (base_shift - 1) + }; + typedef rgba8T self_type; + + + value_type r; + value_type g; + value_type b; + value_type a; + + static void convert(rgba8T& dst, const rgba8T& src) + { + dst.r = sRGB_conv::rgb_from_sRGB(src.r); + dst.g = sRGB_conv::rgb_from_sRGB(src.g); + dst.b = sRGB_conv::rgb_from_sRGB(src.b); + dst.a = src.a; + } + + static void convert(rgba8T& dst, const rgba8T& src) + { + dst.r = sRGB_conv::rgb_to_sRGB(src.r); + dst.g = sRGB_conv::rgb_to_sRGB(src.g); + dst.b = sRGB_conv::rgb_to_sRGB(src.b); + dst.a = src.a; + } + + static void convert(rgba8T& dst, const rgba& src) + { + dst.r = value_type(uround(src.r * base_mask)); + dst.g = value_type(uround(src.g * base_mask)); + dst.b = value_type(uround(src.b * base_mask)); + dst.a = value_type(uround(src.a * base_mask)); + } + + static void convert(rgba8T& dst, const rgba& src) + { + // Use the "float" table. + dst.r = sRGB_conv::rgb_to_sRGB(float(src.r)); + dst.g = sRGB_conv::rgb_to_sRGB(float(src.g)); + dst.b = sRGB_conv::rgb_to_sRGB(float(src.b)); + dst.a = sRGB_conv::alpha_to_sRGB(float(src.a)); + } + + static void convert(rgba& dst, const rgba8T& src) + { + dst.r = src.r / 255.0; + dst.g = src.g / 255.0; + dst.b = src.b / 255.0; + dst.a = src.a / 255.0; + } + + static void convert(rgba& dst, const rgba8T& src) + { + // Use the "float" table. + dst.r = sRGB_conv::rgb_from_sRGB(src.r); + dst.g = sRGB_conv::rgb_from_sRGB(src.g); + dst.b = sRGB_conv::rgb_from_sRGB(src.b); + dst.a = sRGB_conv::alpha_from_sRGB(src.a); + } + + //-------------------------------------------------------------------- + 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(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_)) {} + + //-------------------------------------------------------------------- + template + rgba8T(const rgba8T& c) + { + convert(*this, c); + } + + //-------------------------------------------------------------------- + operator rgba() const + { + rgba c; + convert(c, *this); + return c; + } + + //-------------------------------------------------------------------- + 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 empty_value() + { + return 0; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type full_value() + { + return base_mask; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_transparent() const + { + return a == 0; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_opaque() const + { + return a == base_mask; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type invert(value_type x) + { + return base_mask - x; + } + + //-------------------------------------------------------------------- + // Fixed-point multiply, exact over int8u. + static AGG_INLINE value_type multiply(value_type a, value_type b) + { + calc_type t = a * b + base_MSB; + return value_type(((t >> base_shift) + t) >> base_shift); + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type demultiply(value_type a, value_type b) + { + if (a * b == 0) + { + return 0; + } + else if (a >= b) + { + return base_mask; + } + else return value_type((a * base_mask + (b >> 1)) / b); + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downscale(T a) + { + return a >> base_shift; + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downshift(T a, unsigned n) + { + return a >> n; + } + + //-------------------------------------------------------------------- + // 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 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); + } + + //-------------------------------------------------------------------- + // Interpolate p to q by a. + static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a) + { + int t = (q - p) * a + base_MSB - (p > q); + return value_type(p + (((t >> base_shift) + t) >> base_shift)); + } + + //-------------------------------------------------------------------- + self_type& clear() + { + r = g = b = a = 0; + return *this; + } + + //-------------------------------------------------------------------- + self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + 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)); + return *this; + } + + //-------------------------------------------------------------------- + double opacity() const + { + return double(a) / double(base_mask); + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type& premultiply() + { + if (a != base_mask) + { + if (a == 0) + { + r = g = b = 0; + } + else + { + r = multiply(r, a); + g = multiply(g, a); + b = multiply(b, a); + } + } + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type& premultiply(unsigned a_) + { + if (a != base_mask || a_ < base_mask) + { + if (a == 0 || a_ == 0) + { + r = g = b = a = 0; + } + else + { + calc_type r_ = (calc_type(r) * a_) / a; + calc_type g_ = (calc_type(g) * a_) / a; + calc_type b_ = (calc_type(b) * a_) / a; + r = value_type((r_ > a_) ? a_ : r_); + g = value_type((g_ > a_) ? a_ : g_); + b = value_type((b_ > a_) ? a_ : b_); + a = value_type(a_); + } + } + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type& demultiply() + { + if (a < base_mask) + { + if (a == 0) + { + r = g = b = 0; + } + else + { + calc_type r_ = (calc_type(r) * base_mask) / a; + calc_type g_ = (calc_type(g) * base_mask) / a; + calc_type b_ = (calc_type(b) * base_mask) / a; + r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_); + g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_); + b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_); + } + } + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type gradient(const self_type& c, double k) const + { + self_type ret; + calc_type ik = uround(k * base_mask); + ret.r = lerp(r, c.r, ik); + ret.g = lerp(g, c.g, ik); + ret.b = lerp(b, c.b, ik); + ret.a = lerp(a, c.a, ik); + return ret; + } + + //-------------------------------------------------------------------- + AGG_INLINE void add(const self_type& c, unsigned cover) + { + calc_type cr, cg, cb, ca; + if (cover == cover_mask) + { + if (c.a == base_mask) + { + *this = c; + return; + } + else + { + cr = r + c.r; + cg = g + c.g; + cb = b + c.b; + ca = a + c.a; + } + } + else + { + cr = r + mult_cover(c.r, cover); + cg = g + mult_cover(c.g, cover); + cb = b + mult_cover(c.b, cover); + ca = a + mult_cover(c.a, cover); + } + r = (value_type)((cr > calc_type(base_mask)) ? calc_type(base_mask) : cr); + g = (value_type)((cg > calc_type(base_mask)) ? calc_type(base_mask) : cg); + b = (value_type)((cb > calc_type(base_mask)) ? calc_type(base_mask) : cb); + a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca); + } + + //-------------------------------------------------------------------- + template + AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma) + { + r = gamma.dir(r); + g = gamma.dir(g); + b = gamma.dir(b); + } + + //-------------------------------------------------------------------- + template + AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma) + { + r = gamma.inv(r); + g = gamma.inv(g); + b = gamma.inv(b); + } + + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0,0,0); } + + //-------------------------------------------------------------------- + static self_type from_wavelength(double wl, double gamma = 1.0) + { + return self_type(rgba::from_wavelength(wl, gamma)); + } + }; + + typedef rgba8T rgba8; + typedef rgba8T srgba8; + + + //-------------------------------------------------------------rgb8_packed + inline rgba8 rgb8_packed(unsigned v) + { + return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); + } + + //-------------------------------------------------------------bgr8_packed + inline rgba8 bgr8_packed(unsigned v) + { + return rgba8(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF); + } + + //------------------------------------------------------------argb8_packed + inline rgba8 argb8_packed(unsigned v) + { + return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24); + } + + //---------------------------------------------------------rgba8_gamma_dir + template + rgba8 rgba8_gamma_dir(rgba8 c, const GammaLUT& gamma) + { + return rgba8(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a); + } + + //---------------------------------------------------------rgba8_gamma_inv + template + rgba8 rgba8_gamma_inv(rgba8 c, const GammaLUT& gamma) + { + return rgba8(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a); + } + + + + //==================================================================rgba16 + struct rgba16 + { + typedef int16u value_type; + typedef int32u calc_type; + typedef int64 long_type; + enum base_scale_e + { + base_shift = 16, + base_scale = 1 << base_shift, + base_mask = base_scale - 1, + base_MSB = 1 << (base_shift - 1) + }; + typedef rgba16 self_type; + + value_type r; + value_type g; + value_type b; + value_type a; + + //-------------------------------------------------------------------- + rgba16() {} + + //-------------------------------------------------------------------- + rgba16(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) : + r(value_type(r_)), + g(value_type(g_)), + b(value_type(b_)), + a(value_type(a_)) {} + + //-------------------------------------------------------------------- + rgba16(const self_type& c, unsigned a_) : + r(c.r), g(c.g), b(c.b), a(value_type(a_)) {} + + //-------------------------------------------------------------------- + rgba16(const rgba& c) : + r((value_type)uround(c.r * double(base_mask))), + g((value_type)uround(c.g * double(base_mask))), + b((value_type)uround(c.b * double(base_mask))), + a((value_type)uround(c.a * double(base_mask))) {} + + //-------------------------------------------------------------------- + rgba16(const 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::rgb_from_sRGB(c.r)), + g(sRGB_conv::rgb_from_sRGB(c.g)), + b(sRGB_conv::rgb_from_sRGB(c.b)), + a(sRGB_conv::alpha_from_sRGB(c.a)) {} + + //-------------------------------------------------------------------- + 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 srgba8() const + { + // Return (non-premultiplied) sRGB values. + return srgba8( + sRGB_conv::rgb_to_sRGB(r), + sRGB_conv::rgb_to_sRGB(g), + sRGB_conv::rgb_to_sRGB(b), + sRGB_conv::alpha_to_sRGB(a)); + } + + //-------------------------------------------------------------------- + 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 empty_value() + { + return 0; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type full_value() + { + return base_mask; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_transparent() const + { + return a == 0; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_opaque() const + { + return a == base_mask; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type invert(value_type x) + { + return base_mask - x; + } + + //-------------------------------------------------------------------- + // Fixed-point multiply, exact over int16u. + static AGG_INLINE value_type multiply(value_type a, value_type b) + { + calc_type t = a * b + base_MSB; + return value_type(((t >> base_shift) + t) >> base_shift); + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type demultiply(value_type a, value_type b) + { + if (a * b == 0) + { + return 0; + } + else if (a >= b) + { + return base_mask; + } + else return value_type((a * base_mask + (b >> 1)) / b); + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downscale(T a) + { + return a >> base_shift; + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downshift(T a, unsigned n) + { + return a >> n; + } + + //-------------------------------------------------------------------- + // 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 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); + } + + //-------------------------------------------------------------------- + // Interpolate p to q by a. + static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a) + { + int t = (q - p) * a + base_MSB - (p > q); + return value_type(p + (((t >> base_shift) + t) >> base_shift)); + } + + //-------------------------------------------------------------------- + self_type& clear() + { + r = g = b = a = 0; + return *this; + } + + //-------------------------------------------------------------------- + self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type& opacity(double a_) + { + 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); + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type& premultiply() + { + if (a != base_mask) + { + if (a == 0) + { + r = g = b = 0; + } + else + { + r = multiply(r, a); + g = multiply(g, a); + b = multiply(b, a); + } + } + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type& premultiply(unsigned a_) + { + if (a < base_mask || a_ < base_mask) + { + if (a == 0 || a_ == 0) + { + r = g = b = a = 0; + } + else + { + calc_type r_ = (calc_type(r) * a_) / a; + calc_type g_ = (calc_type(g) * a_) / a; + calc_type b_ = (calc_type(b) * a_) / a; + r = value_type((r_ > a_) ? a_ : r_); + g = value_type((g_ > a_) ? a_ : g_); + b = value_type((b_ > a_) ? a_ : b_); + a = value_type(a_); + } + } + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type& demultiply() + { + if (a < base_mask) + { + if (a == 0) + { + r = g = b = 0; + } + else + { + calc_type r_ = (calc_type(r) * base_mask) / a; + calc_type g_ = (calc_type(g) * base_mask) / a; + calc_type b_ = (calc_type(b) * base_mask) / a; + r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_); + g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_); + b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_); + } + } + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type gradient(const self_type& c, double k) const + { + self_type ret; + calc_type ik = uround(k * base_mask); + ret.r = lerp(r, c.r, ik); + ret.g = lerp(g, c.g, ik); + ret.b = lerp(b, c.b, ik); + ret.a = lerp(a, c.a, ik); + return ret; + } + + //-------------------------------------------------------------------- + AGG_INLINE void add(const self_type& c, unsigned cover) + { + calc_type cr, cg, cb, ca; + if (cover == cover_mask) + { + if (c.a == base_mask) + { + *this = c; + return; + } + else + { + cr = r + c.r; + cg = g + c.g; + cb = b + c.b; + ca = a + c.a; + } + } + else + { + cr = r + mult_cover(c.r, cover); + cg = g + mult_cover(c.g, cover); + cb = b + mult_cover(c.b, cover); + ca = a + mult_cover(c.a, cover); + } + r = (value_type)((cr > calc_type(base_mask)) ? calc_type(base_mask) : cr); + g = (value_type)((cg > calc_type(base_mask)) ? calc_type(base_mask) : cg); + b = (value_type)((cb > calc_type(base_mask)) ? calc_type(base_mask) : cb); + a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca); + } + + //-------------------------------------------------------------------- + template + AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma) + { + r = gamma.dir(r); + g = gamma.dir(g); + b = gamma.dir(b); + } + + //-------------------------------------------------------------------- + template + AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma) + { + r = gamma.inv(r); + g = gamma.inv(g); + b = gamma.inv(b); + } + + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0,0,0); } + + //-------------------------------------------------------------------- + static self_type from_wavelength(double wl, double gamma = 1.0) + { + return self_type(rgba::from_wavelength(wl, gamma)); + } + }; + + + //------------------------------------------------------rgba16_gamma_dir + template + rgba16 rgba16_gamma_dir(rgba16 c, const GammaLUT& gamma) + { + return rgba16(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a); + } + + //------------------------------------------------------rgba16_gamma_inv + template + rgba16 rgba16_gamma_inv(rgba16 c, const GammaLUT& gamma) + { + return rgba16(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a); + } + + //====================================================================rgba32 + struct rgba32 + { + typedef float value_type; + typedef double calc_type; + typedef double long_type; + typedef rgba32 self_type; + + value_type r; + value_type g; + value_type b; + value_type a; + + //-------------------------------------------------------------------- + rgba32() {} + + //-------------------------------------------------------------------- + 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 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 srgba8& c) : + r(sRGB_conv::rgb_from_sRGB(c.r)), + g(sRGB_conv::rgb_from_sRGB(c.g)), + b(sRGB_conv::rgb_from_sRGB(c.b)), + a(sRGB_conv::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)) {} + + //-------------------------------------------------------------------- + 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 srgba8() const + { + return srgba8( + sRGB_conv::rgb_to_sRGB(r), + sRGB_conv::rgb_to_sRGB(g), + sRGB_conv::rgb_to_sRGB(b), + sRGB_conv::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)); + } + + //-------------------------------------------------------------------- + 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 empty_value() + { + return 0; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type full_value() + { + return 1; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_transparent() const + { + return a <= 0; + } + + //-------------------------------------------------------------------- + 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 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); + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downscale(T a) + { + return a; + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downshift(T a, unsigned n) + { + return n > 0 ? a / (1 << n) : a; + } + + //-------------------------------------------------------------------- + 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)); + } + + //-------------------------------------------------------------------- + // 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 (1 - a) * p + q; // more accurate than "p + q - p * a" + } + + //-------------------------------------------------------------------- + // Interpolate p to q by a. + static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a) + { + // The form "p + a * (q - p)" avoids a multiplication, but may produce an + // inaccurate result. For example, "p + (q - p)" may not be exactly equal + // to q. Therefore, stick to the basic expression, which at least produces + // the correct result at either extreme. + return (1 - a) * p + a * q; + } + + //-------------------------------------------------------------------- + self_type& clear() + { + r = g = b = a = 0; + return *this; + } + + //-------------------------------------------------------------------- + self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type& opacity(double a_) + { + if (a_ < 0) a = 0; + else if (a_ > 1) a = 1; + else a = value_type(a_); + return *this; + } + + //-------------------------------------------------------------------- + double opacity() const + { + return a; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type& premultiply() + { + if (a < 1) + { + if (a <= 0) + { + r = g = b = 0; + } + else + { + r *= a; + g *= a; + b *= a; + } + } + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type& demultiply() + { + if (a < 1) + { + if (a <= 0) + { + r = g = b = 0; + } + else + { + r /= a; + g /= a; + b /= a; + } + } + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type gradient(const self_type& c, double k) const + { + self_type ret; + ret.r = value_type(r + (c.r - r) * k); + ret.g = value_type(g + (c.g - g) * k); + ret.b = value_type(b + (c.b - b) * k); + ret.a = value_type(a + (c.a - a) * k); + return ret; + } + + //-------------------------------------------------------------------- + AGG_INLINE void add(const self_type& c, unsigned cover) + { + if (cover == cover_mask) + { + if (c.is_opaque()) + { + *this = c; + return; + } + else + { + r += c.r; + g += c.g; + b += c.b; + a += c.a; + } + } + else + { + r += mult_cover(c.r, cover); + g += mult_cover(c.g, cover); + 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; + } + + //-------------------------------------------------------------------- + template + AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma) + { + r = gamma.dir(r); + g = gamma.dir(g); + b = gamma.dir(b); + } + + //-------------------------------------------------------------------- + template + AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma) + { + r = gamma.inv(r); + g = gamma.inv(g); + b = gamma.inv(b); + } + + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0,0,0); } + + //-------------------------------------------------------------------- + static self_type from_wavelength(double wl, double gamma = 1) + { + return self_type(rgba::from_wavelength(wl, gamma)); + } + }; +} + + + +#endif diff --git a/agg/include/agg_config.h b/agg/include/agg_config.h new file mode 100644 index 0000000..fa1dae2 --- /dev/null +++ b/agg/include/agg_config.h @@ -0,0 +1,44 @@ +#ifndef AGG_CONFIG_INCLUDED +#define AGG_CONFIG_INCLUDED + +// This file can be used to redefine certain data types. + +//--------------------------------------- +// 1. Default basic types such as: +// +// AGG_INT8 +// AGG_INT8U +// AGG_INT16 +// AGG_INT16U +// AGG_INT32 +// AGG_INT32U +// AGG_INT64 +// AGG_INT64U +// +// Just replace this file with new defines if necessary. +// For example, if your compiler doesn't have a 64 bit integer type +// you can still use AGG if you define the follows: +// +// #define AGG_INT64 int +// #define AGG_INT64U unsigned +// +// It will result in overflow in 16 bit-per-component image/pattern resampling +// but it won't result any crash and the rest of the library will remain +// fully functional. + + +//--------------------------------------- +// 2. Default rendering_buffer type. Can be: +// +// Provides faster access for massive pixel operations, +// such as blur, image filtering: +// #define AGG_RENDERING_BUFFER row_ptr_cache +// +// Provides cheaper creation and destruction (no mem allocs): +// #define AGG_RENDERING_BUFFER row_accessor +// +// You can still use both of them simultaneously in your applications +// This #define is used only for default rendering_buffer type, +// in short hand typedefs like pixfmt_rgba32. + +#endif diff --git a/agg2/include/agg_conv_adaptor_vcgen.h b/agg/include/agg_conv_adaptor_vcgen.h similarity index 85% rename from agg2/include/agg_conv_adaptor_vcgen.h rename to agg/include/agg_conv_adaptor_vcgen.h index cf53929..a79f220 100644 --- a/agg2/include/agg_conv_adaptor_vcgen.h +++ b/agg/include/agg_conv_adaptor_vcgen.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -17,7 +17,6 @@ #define AGG_CONV_ADAPTOR_VCGEN_INCLUDED #include "agg_basics.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -30,11 +29,6 @@ namespace agg void rewind(unsigned) {} unsigned vertex(double*, double*) { return path_cmd_stop; } - - typedef null_markers source_type; - typedef vertex_iterator iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } }; @@ -51,12 +45,11 @@ namespace agg }; public: - conv_adaptor_vcgen(VertexSource& source) : + explicit conv_adaptor_vcgen(VertexSource& source) : m_source(&source), m_status(initial) {} - - void set_source(VertexSource& source) { m_source = &source; } + void attach(VertexSource& source) { m_source = &source; } Generator& generator() { return m_generator; } const Generator& generator() const { return m_generator; } @@ -64,19 +57,14 @@ namespace agg Markers& markers() { return m_markers; } const Markers& markers() const { return m_markers; } - void rewind(unsigned id) + void rewind(unsigned path_id) { - m_source->rewind(id); + m_source->rewind(path_id); m_status = initial; } unsigned vertex(double* x, double* y); - typedef conv_adaptor_vcgen source_type; - typedef vertex_iterator iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: // Prohibit copying conv_adaptor_vcgen(const conv_adaptor_vcgen&); diff --git a/agg2/include/agg_conv_adaptor_vpgen.h b/agg/include/agg_conv_adaptor_vpgen.h similarity index 61% rename from agg2/include/agg_conv_adaptor_vpgen.h rename to agg/include/agg_conv_adaptor_vpgen.h index b5e5845..d6b545e 100644 --- a/agg2/include/agg_conv_adaptor_vpgen.h +++ b/agg/include/agg_conv_adaptor_vpgen.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -17,7 +17,6 @@ #define AGG_CONV_ADAPTOR_VPGEN_INCLUDED #include "agg_basics.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -26,9 +25,8 @@ namespace agg template class conv_adaptor_vpgen { public: - conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {} - - void set_source(VertexSource& source) { m_source = &source; } + explicit conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {} + void attach(VertexSource& source) { m_source = &source; } VPGen& vpgen() { return m_vpgen; } const VPGen& vpgen() const { return m_vpgen; } @@ -36,11 +34,6 @@ namespace agg void rewind(unsigned path_id); unsigned vertex(double* x, double* y); - typedef conv_adaptor_vpgen source_type; - typedef vertex_iterator iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: conv_adaptor_vpgen(const conv_adaptor_vpgen&); const conv_adaptor_vpgen& @@ -51,6 +44,7 @@ namespace agg double m_start_x; double m_start_y; unsigned m_poly_flags; + int m_vertices; }; @@ -64,6 +58,7 @@ namespace agg m_start_x = 0; m_start_y = 0; m_poly_flags = 0; + m_vertices = 0; } @@ -77,26 +72,51 @@ namespace agg cmd = m_vpgen.vertex(x, y); if(!is_stop(cmd)) break; - if(m_poly_flags) + if(m_poly_flags && !m_vpgen.auto_unclose()) { + *x = 0.0; + *y = 0.0; cmd = m_poly_flags; m_poly_flags = 0; break; } + if(m_vertices < 0) + { + if(m_vertices < -1) + { + m_vertices = 0; + return path_cmd_stop; + } + m_vpgen.move_to(m_start_x, m_start_y); + m_vertices = 1; + continue; + } + double tx, ty; cmd = m_source->vertex(&tx, &ty); if(is_vertex(cmd)) { if(is_move_to(cmd)) { + if(m_vpgen.auto_close() && m_vertices > 2) + { + m_vpgen.line_to(m_start_x, m_start_y); + m_poly_flags = path_cmd_end_poly | path_flags_close; + m_start_x = tx; + m_start_y = ty; + m_vertices = -1; + continue; + } m_vpgen.move_to(tx, ty); - m_start_x = tx; - m_start_y = ty; + m_start_x = tx; + m_start_y = ty; + m_vertices = 1; } else { m_vpgen.line_to(tx, ty); + ++m_vertices; } } else @@ -104,14 +124,26 @@ namespace agg if(is_end_poly(cmd)) { m_poly_flags = cmd; - if(is_closed(cmd)) + if(is_closed(cmd) || m_vpgen.auto_close()) { - m_vpgen.line_to(m_start_x, m_start_y); + 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 { - // The adaptor should be transparent to all unknown commands + // 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; } } diff --git a/agg2/include/agg_conv_bspline.h b/agg/include/agg_conv_bspline.h similarity index 93% rename from agg2/include/agg_conv_bspline.h rename to agg/include/agg_conv_bspline.h index 6fcc147..13d22d9 100644 --- a/agg2/include/agg_conv_bspline.h +++ b/agg/include/agg_conv_bspline.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. diff --git a/agg2/include/agg_conv_clip_polygon.h b/agg/include/agg_conv_clip_polygon.h similarity index 86% rename from agg2/include/agg_conv_clip_polygon.h rename to agg/include/agg_conv_clip_polygon.h index bc7d897..8753763 100644 --- a/agg2/include/agg_conv_clip_polygon.h +++ b/agg/include/agg_conv_clip_polygon.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -29,7 +29,6 @@ #include "agg_basics.h" #include "agg_conv_adaptor_vpgen.h" #include "agg_vpgen_clip_polygon.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -53,11 +52,6 @@ namespace agg double x2() const { return base_type::vpgen().x2(); } double y2() const { return base_type::vpgen().y2(); } - typedef conv_clip_polygon source_type; - typedef vertex_iterator iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: conv_clip_polygon(const conv_clip_polygon&); const conv_clip_polygon& diff --git a/agg/include/agg_conv_clip_polyline.h b/agg/include/agg_conv_clip_polyline.h new file mode 100644 index 0000000..f3fc288 --- /dev/null +++ b/agg/include/agg_conv_clip_polyline.h @@ -0,0 +1,63 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// polyline clipping converter +// There an optimized Liang-Basky algorithm is used. +// The algorithm doesn't optimize the degenerate edges, i.e. it will never +// break a closed polyline into two or more ones, instead, there will be +// degenerate edges coinciding with the respective clipping boundaries. +// This is a sub-optimal solution, because that optimization would require +// extra, rather expensive math while the rasterizer tolerates it quite well, +// without any considerable overhead. +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_CLIP_polyline_INCLUDED +#define AGG_CONV_CLIP_polyline_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_adaptor_vpgen.h" +#include "agg_vpgen_clip_polyline.h" + +namespace agg +{ + + //=======================================================conv_clip_polyline + template + struct conv_clip_polyline : public conv_adaptor_vpgen + { + typedef conv_adaptor_vpgen base_type; + + conv_clip_polyline(VertexSource& vs) : + conv_adaptor_vpgen(vs) {} + + void clip_box(double x1, double y1, double x2, double y2) + { + base_type::vpgen().clip_box(x1, y1, x2, y2); + } + + double x1() const { return base_type::vpgen().x1(); } + double y1() const { return base_type::vpgen().y1(); } + double x2() const { return base_type::vpgen().x2(); } + double y2() const { return base_type::vpgen().y2(); } + + private: + conv_clip_polyline(const conv_clip_polyline&); + const conv_clip_polyline& + operator = (const conv_clip_polyline&); + }; + +} + +#endif diff --git a/agg2/include/agg_conv_close_polygon.h b/agg/include/agg_conv_close_polygon.h similarity index 86% rename from agg2/include/agg_conv_close_polygon.h rename to agg/include/agg_conv_close_polygon.h index 038e778..c46594f 100644 --- a/agg2/include/agg_conv_close_polygon.h +++ b/agg/include/agg_conv_close_polygon.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -17,7 +17,6 @@ #define AGG_CONV_CLOSE_POLYGON_INCLUDED #include "agg_basics.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -26,18 +25,12 @@ namespace agg template class conv_close_polygon { public: - conv_close_polygon(VertexSource& vs) : m_source(&vs) {} - - void set_source(VertexSource& source) { m_source = &source; } + 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); - typedef conv_close_polygon source_type; - typedef vertex_iterator iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: conv_close_polygon(const conv_close_polygon&); const conv_close_polygon& diff --git a/agg2/include/agg_conv_concat.h b/agg/include/agg_conv_concat.h similarity index 77% rename from agg2/include/agg_conv_concat.h rename to agg/include/agg_conv_concat.h index dcd5a5f..745d349 100644 --- a/agg2/include/agg_conv_concat.h +++ b/agg/include/agg_conv_concat.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -17,7 +17,6 @@ #define AGG_CONV_CONCAT_INCLUDED #include "agg_basics.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -29,14 +28,13 @@ namespace agg 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 set_source1(VS1& source) { m_source1 = &source; } - void set_source2(VS2& source) { m_source2 = &source; } - - void rewind(unsigned id) + void rewind(unsigned path_id) { - m_source1->rewind(id); + m_source1->rewind(path_id); m_source2->rewind(0); m_status = 0; } @@ -59,11 +57,6 @@ namespace agg return path_cmd_stop; } - typedef conv_concat source_type; - typedef vertex_iterator iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: conv_concat(const conv_concat&); const conv_concat& diff --git a/agg2/include/agg_conv_contour.h b/agg/include/agg_conv_contour.h similarity index 71% rename from agg2/include/agg_conv_contour.h rename to agg/include/agg_conv_contour.h index c525f16..b4b5a90 100644 --- a/agg2/include/agg_conv_contour.h +++ b/agg/include/agg_conv_contour.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -37,13 +37,21 @@ namespace agg { } + void line_join(line_join_e lj) { base_type::generator().line_join(lj); } + void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); } void width(double w) { base_type::generator().width(w); } void miter_limit(double ml) { base_type::generator().miter_limit(ml); } void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); } + void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); } + void approximation_scale(double as) { base_type::generator().approximation_scale(as); } void auto_detect_orientation(bool v) { base_type::generator().auto_detect_orientation(v); } + line_join_e line_join() const { return base_type::generator().line_join(); } + inner_join_e inner_join() const { return base_type::generator().inner_join(); } double width() const { return base_type::generator().width(); } double miter_limit() const { return base_type::generator().miter_limit(); } + double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); } + double approximation_scale() const { return base_type::generator().approximation_scale(); } bool auto_detect_orientation() const { return base_type::generator().auto_detect_orientation(); } private: diff --git a/agg2/include/agg_conv_curve.h b/agg/include/agg_conv_curve.h similarity index 67% rename from agg2/include/agg_conv_curve.h rename to agg/include/agg_conv_curve.h index fa51ca8..0be3b6f 100644 --- a/agg2/include/agg_conv_curve.h +++ b/agg/include/agg_conv_curve.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -33,14 +33,14 @@ namespace agg // 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 curcular and elliptical. Curves are approximated + // 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, nothig prevents us from doing so). Instead, path_storage + // 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, @@ -51,13 +51,29 @@ namespace agg // 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 conv_curve + template class conv_curve { public: - conv_curve(VertexSource& source) : + typedef Curve3 curve3_type; + typedef Curve4 curve4_type; + typedef conv_curve self_type; + + explicit conv_curve(VertexSource& source) : m_source(&source), m_last_x(0.0), m_last_y(0.0) {} + void attach(VertexSource& source) { m_source = &source; } + + void approximation_method(curve_approximation_method_e v) + { + m_curve3.approximation_method(v); + m_curve4.approximation_method(v); + } - void set_source(VertexSource& source) { m_source = &source; } + curve_approximation_method_e approximation_method() const + { + return m_curve4.approximation_method(); + } void approximation_scale(double s) { @@ -67,36 +83,52 @@ namespace agg double approximation_scale() const { - return m_curve3.approximation_scale(); + return m_curve4.approximation_scale(); } - void rewind(unsigned id); - unsigned vertex(double* x, double* y); + void angle_tolerance(double v) + { + m_curve3.angle_tolerance(v); + m_curve4.angle_tolerance(v); + } - typedef conv_curve source_type; - typedef vertex_iterator iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } + 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 conv_curve&); - const conv_curve& - operator = (const conv_curve&); + conv_curve(const self_type&); + const self_type& operator = (const self_type&); VertexSource* m_source; double m_last_x; double m_last_y; - curve3 m_curve3; - curve4 m_curve4; + curve3_type m_curve3; + curve4_type m_curve4; }; //------------------------------------------------------------------------ - template - void conv_curve::rewind(unsigned id) + template + void conv_curve::rewind(unsigned path_id) { - m_source->rewind(id); + m_source->rewind(path_id); m_last_x = 0.0; m_last_y = 0.0; m_curve3.reset(); @@ -105,8 +137,8 @@ namespace agg //------------------------------------------------------------------------ - template - unsigned conv_curve::vertex(double* x, double* y) + template + unsigned conv_curve::vertex(double* x, double* y) { if(!is_stop(m_curve3.vertex(x, y))) { @@ -122,21 +154,14 @@ namespace agg return path_cmd_line_to; } - double ct2_x; - double ct2_y; - double end_x; - double end_y; + 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_move_to: - case path_cmd_line_to: - m_last_x = *x; - m_last_y = *y; - default: - break; - case path_cmd_curve3: m_source->vertex(&end_x, &end_y); @@ -163,6 +188,8 @@ namespace agg cmd = path_cmd_line_to; break; } + m_last_x = *x; + m_last_y = *y; return cmd; } diff --git a/agg2/include/agg_conv_dash.h b/agg/include/agg_conv_dash.h similarity index 95% rename from agg2/include/agg_conv_dash.h rename to agg/include/agg_conv_dash.h index 6d5723b..23c13ad 100644 --- a/agg2/include/agg_conv_dash.h +++ b/agg/include/agg_conv_dash.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. diff --git a/agg2/include/agg_conv_gpc.h b/agg/include/agg_conv_gpc.h similarity index 88% rename from agg2/include/agg_conv_gpc.h rename to agg/include/agg_conv_gpc.h index d303b9e..6100179 100644 --- a/agg2/include/agg_conv_gpc.h +++ b/agg/include/agg_conv_gpc.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -24,10 +24,9 @@ #ifndef AGG_CONV_GPC_INCLUDED #define AGG_CONV_GPC_INCLUDED -#include +#include #include "agg_basics.h" #include "agg_array.h" -#include "agg_vertex_iterator.h" extern "C" { @@ -63,8 +62,8 @@ namespace agg gpc_vertex* vertices; }; - typedef pod_deque vertex_array_type; - typedef pod_deque contour_header_array_type; + typedef pod_bvector vertex_array_type; + typedef pod_bvector contour_header_array_type; public: @@ -85,25 +84,20 @@ namespace agg 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)); + std::memset(&m_poly_a, 0, sizeof(m_poly_a)); + std::memset(&m_poly_b, 0, sizeof(m_poly_b)); + std::memset(&m_result, 0, sizeof(m_result)); } - void set_source1(VSA& source) { m_src_a = &source; } - void set_source2(VSB& source) { m_src_b = &source; } + 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 id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); - // Iterator - typedef vertex_iterator iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: conv_gpc(const conv_gpc&); const conv_gpc& operator = (const conv_gpc&); @@ -197,11 +191,11 @@ namespace agg int i; for(i = 0; i < p.num_contours; i++) { - delete [] p.contour[i].vertex; + pod_allocator::deallocate(p.contour[i].vertex, + p.contour[i].num_vertices); } - delete [] p.hole; - delete [] p.contour; - memset(&p, 0, sizeof(gpc_polygon)); + pod_allocator::deallocate(p.contour, p.num_contours); + std::memset(&p, 0, sizeof(gpc_polygon)); } @@ -213,7 +207,7 @@ namespace agg { gpc_free_polygon(&m_result); } - memset(&m_result, 0, sizeof(m_result)); + std::memset(&m_result, 0, sizeof(m_result)); } @@ -232,7 +226,7 @@ namespace agg void conv_gpc::start_contour() { contour_header_type h; - memset(&h, 0, sizeof(h)); + std::memset(&h, 0, sizeof(h)); m_contour_accumulator.add(h); m_vertex_accumulator.remove_all(); } @@ -251,7 +245,7 @@ namespace agg //------------------------------------------------------------------------ template - void conv_gpc::end_contour(unsigned orientation) + void conv_gpc::end_contour(unsigned /*orientation*/) { if(m_contour_accumulator.size()) { @@ -266,7 +260,7 @@ namespace agg // TO DO: Clarify the "holes" //if(is_cw(orientation)) h.hole_flag = 1; - h.vertices = new gpc_vertex [h.num_vertices]; + h.vertices = pod_allocator::allocate(h.num_vertices); gpc_vertex* d = h.vertices; int i; for(i = 0; i < h.num_vertices; i++) @@ -294,19 +288,14 @@ namespace agg { p.num_contours = m_contour_accumulator.size(); - // TO DO: Clarify the "holes" - //p.hole = new int[p.num_contours]; p.hole = 0; - - p.contour = new gpc_vertex_list[p.num_contours]; + p.contour = pod_allocator::allocate(p.num_contours); int i; - //int* ph = p.hole; gpc_vertex_list* pv = p.contour; for(i = 0; i < p.num_contours; i++) { const contour_header_type& h = m_contour_accumulator[i]; - // *ph++ = h.hole_flag; pv->num_vertices = h.num_vertices; pv->vertex = h.vertices; ++pv; @@ -356,11 +345,11 @@ namespace agg //------------------------------------------------------------------------ template - void conv_gpc::rewind(unsigned id) + void conv_gpc::rewind(unsigned path_id) { free_result(); - m_src_a->rewind(id); - m_src_b->rewind(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); switch(m_operation) diff --git a/agg2/include/agg_conv_marker.h b/agg/include/agg_conv_marker.h similarity index 89% rename from agg2/include/agg_conv_marker.h rename to agg/include/agg_conv_marker.h index fc84efe..0df56e3 100644 --- a/agg2/include/agg_conv_marker.h +++ b/agg/include/agg_conv_marker.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -19,9 +19,9 @@ #ifndef AGG_CONV_MARKER_INCLUDED #define AGG_CONV_MARKER_INCLUDED +#include #include "agg_basics.h" #include "agg_trans_affine.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -35,14 +35,9 @@ namespace agg trans_affine& transform() { return m_transform; } const trans_affine& transform() const { return m_transform; } - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); - typedef conv_marker source_type; - typedef vertex_iterator iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: conv_marker(const conv_marker&); const conv_marker& @@ -123,7 +118,7 @@ namespace agg } ++m_num_markers; m_mtx = m_transform; - m_mtx *= trans_affine_rotation(atan2(y2 - y1, x2 - x1)); + m_mtx *= trans_affine_rotation(std::atan2(y2 - y1, x2 - x1)); m_mtx *= trans_affine_translation(x1, y1); m_marker_shapes->rewind(m_marker - 1); m_status = polygon; diff --git a/agg2/include/agg_conv_marker_adaptor.h b/agg/include/agg_conv_marker_adaptor.h similarity index 94% rename from agg2/include/agg_conv_marker_adaptor.h rename to agg/include/agg_conv_marker_adaptor.h index d38b5e6..4486d6a 100644 --- a/agg2/include/agg_conv_marker_adaptor.h +++ b/agg/include/agg_conv_marker_adaptor.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. diff --git a/agg2/include/agg_conv_segmentator.h b/agg/include/agg_conv_segmentator.h similarity index 94% rename from agg2/include/agg_conv_segmentator.h rename to agg/include/agg_conv_segmentator.h index 2c1cb6d..e69a9e7 100644 --- a/agg2/include/agg_conv_segmentator.h +++ b/agg/include/agg_conv_segmentator.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. diff --git a/agg2/include/agg_conv_shorten_path.h b/agg/include/agg_conv_shorten_path.h similarity index 94% rename from agg2/include/agg_conv_shorten_path.h rename to agg/include/agg_conv_shorten_path.h index ed179ae..5617e51 100644 --- a/agg2/include/agg_conv_shorten_path.h +++ b/agg/include/agg_conv_shorten_path.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. diff --git a/agg2/include/agg_conv_smooth_poly1.h b/agg/include/agg_conv_smooth_poly1.h similarity index 96% rename from agg2/include/agg_conv_smooth_poly1.h rename to agg/include/agg_conv_smooth_poly1.h index 2364963..4ac4e3d 100644 --- a/agg2/include/agg_conv_smooth_poly1.h +++ b/agg/include/agg_conv_smooth_poly1.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. diff --git a/agg2/include/agg_conv_stroke.h b/agg/include/agg_conv_stroke.h similarity index 74% rename from agg2/include/agg_conv_stroke.h rename to agg/include/agg_conv_stroke.h index 57e7207..e19a6b6 100644 --- a/agg2/include/agg_conv_stroke.h +++ b/agg/include/agg_conv_stroke.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -39,19 +39,23 @@ namespace agg { } - void line_cap(vcgen_stroke::line_cap_e lc) { base_type::generator().line_cap(lc); } - void line_join(vcgen_stroke::line_join_e lj) { base_type::generator().line_join(lj); } + 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); } - vcgen_stroke::line_cap_e line_cap() const { return base_type::generator().line_cap(); } - vcgen_stroke::line_join_e line_join() const { return base_type::generator().line_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); } 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); } diff --git a/agg2/include/agg_conv_transform.h b/agg/include/agg_conv_transform.h similarity index 70% rename from agg2/include/agg_conv_transform.h rename to agg/include/agg_conv_transform.h index 7e3a392..0c88a24 100644 --- a/agg2/include/agg_conv_transform.h +++ b/agg/include/agg_conv_transform.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -21,7 +21,6 @@ #include "agg_basics.h" #include "agg_trans_affine.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -30,14 +29,13 @@ namespace agg template class conv_transform { public: - conv_transform(VertexSource& source, const Transformer& tr) : + conv_transform(VertexSource& source, Transformer& tr) : m_source(&source), m_trans(&tr) {} + void attach(VertexSource& source) { m_source = &source; } - void set_source(VertexSource& source) { m_source = &source; } - - void rewind(unsigned id) + void rewind(unsigned path_id) { - m_source->rewind(id); + m_source->rewind(path_id); } unsigned vertex(double* x, double* y) @@ -50,23 +48,18 @@ namespace agg return cmd; } - void transformer(const Transformer& tr) + void transformer(Transformer& tr) { m_trans = &tr; } - typedef conv_transform source_type; - typedef vertex_iterator iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: conv_transform(const conv_transform&); const conv_transform& operator = (const conv_transform&); VertexSource* m_source; - const Transformer* m_trans; + Transformer* m_trans; }; diff --git a/agg2/include/agg_conv_unclose_polygon.h b/agg/include/agg_conv_unclose_polygon.h similarity index 73% rename from agg2/include/agg_conv_unclose_polygon.h rename to agg/include/agg_conv_unclose_polygon.h index a0619dc..fe5c263 100644 --- a/agg2/include/agg_conv_unclose_polygon.h +++ b/agg/include/agg_conv_unclose_polygon.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -17,7 +17,6 @@ #define AGG_CONV_UNCLOSE_POLYGON_INCLUDED #include "agg_basics.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -25,9 +24,8 @@ namespace agg template class conv_unclose_polygon { public: - conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {} - - void set_source(VertexSource& source) { m_source = &source; } + explicit conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {} + void attach(VertexSource& source) { m_source = &source; } void rewind(unsigned path_id) { @@ -41,11 +39,6 @@ namespace agg return cmd; } - typedef conv_unclose_polygon source_type; - typedef vertex_iterator iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: conv_unclose_polygon(const conv_unclose_polygon&); const conv_unclose_polygon& diff --git a/agg/include/agg_curves.h b/agg/include/agg_curves.h new file mode 100644 index 0000000..1ef02e8 --- /dev/null +++ b/agg/include/agg_curves.h @@ -0,0 +1,693 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.4 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// Copyright (C) 2005 Tony Juricic (tonygeek@yahoo.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_CURVES_INCLUDED +#define AGG_CURVES_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + + // See Implementation agg_curves.cpp + + //--------------------------------------------curve_approximation_method_e + enum curve_approximation_method_e + { + curve_inc, + curve_div + }; + + //--------------------------------------------------------------curve3_inc + class curve3_inc + { + public: + curve3_inc() : + m_num_steps(0), m_step(0), m_scale(1.0) { } + + curve3_inc(double x1, double y1, + double x2, double y2, + double x3, double y3) : + m_num_steps(0), m_step(0), m_scale(1.0) + { + init(x1, y1, x2, y2, x3, y3); + } + + void reset() { m_num_steps = 0; m_step = -1; } + void init(double x1, double y1, + double x2, double y2, + double x3, double y3); + + void approximation_method(curve_approximation_method_e) {} + curve_approximation_method_e approximation_method() const { return curve_inc; } + + void approximation_scale(double s); + double approximation_scale() const; + + void angle_tolerance(double) {} + double angle_tolerance() const { return 0.0; } + + void cusp_limit(double) {} + double cusp_limit() const { return 0.0; } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + int m_num_steps; + int m_step; + double m_scale; + double m_start_x; + double m_start_y; + double m_end_x; + double m_end_y; + double m_fx; + double m_fy; + double m_dfx; + double m_dfy; + double m_ddfx; + double m_ddfy; + double m_saved_fx; + double m_saved_fy; + double m_saved_dfx; + double m_saved_dfy; + }; + + + + + + //-------------------------------------------------------------curve3_div + class curve3_div + { + public: + curve3_div() : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_count(0) + {} + + curve3_div(double x1, double y1, + double x2, double y2, + double x3, double y3) : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_count(0) + { + init(x1, y1, x2, y2, x3, y3); + } + + void reset() { m_points.remove_all(); m_count = 0; } + void init(double x1, double y1, + double x2, double y2, + double x3, double y3); + + void approximation_method(curve_approximation_method_e) {} + curve_approximation_method_e approximation_method() const { return curve_div; } + + void approximation_scale(double s) { m_approximation_scale = s; } + double approximation_scale() const { return m_approximation_scale; } + + void angle_tolerance(double a) { m_angle_tolerance = a; } + double angle_tolerance() const { return m_angle_tolerance; } + + void cusp_limit(double) {} + double cusp_limit() const { return 0.0; } + + void rewind(unsigned) + { + m_count = 0; + } + + unsigned vertex(double* x, double* y) + { + if(m_count >= m_points.size()) return path_cmd_stop; + const point_d& p = m_points[m_count++]; + *x = p.x; + *y = p.y; + return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to; + } + + private: + void bezier(double x1, double y1, + double x2, double y2, + double x3, double y3); + void recursive_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + unsigned level); + + double m_approximation_scale; + double m_distance_tolerance_square; + double m_angle_tolerance; + unsigned m_count; + pod_bvector m_points; + }; + + + + + + + + //-------------------------------------------------------------curve4_points + struct curve4_points + { + double cp[8]; + curve4_points() {} + curve4_points(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2; + cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4; + } + void init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2; + cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4; + } + double operator [] (unsigned i) const { return cp[i]; } + double& operator [] (unsigned i) { return cp[i]; } + }; + + + + //-------------------------------------------------------------curve4_inc + class curve4_inc + { + public: + curve4_inc() : + m_num_steps(0), m_step(0), m_scale(1.0) { } + + curve4_inc(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) : + m_num_steps(0), m_step(0), m_scale(1.0) + { + init(x1, y1, x2, y2, x3, y3, x4, y4); + } + + curve4_inc(const curve4_points& cp) : + m_num_steps(0), m_step(0), m_scale(1.0) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void reset() { m_num_steps = 0; m_step = -1; } + void init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4); + + void init(const curve4_points& cp) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void approximation_method(curve_approximation_method_e) {} + curve_approximation_method_e approximation_method() const { return curve_inc; } + + void approximation_scale(double s); + double approximation_scale() const; + + void angle_tolerance(double) {} + double angle_tolerance() const { return 0.0; } + + void cusp_limit(double) {} + double cusp_limit() const { return 0.0; } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + int m_num_steps; + int m_step; + double m_scale; + double m_start_x; + double m_start_y; + double m_end_x; + double m_end_y; + double m_fx; + double m_fy; + double m_dfx; + double m_dfy; + double m_ddfx; + double m_ddfy; + double m_dddfx; + double m_dddfy; + double m_saved_fx; + double m_saved_fy; + double m_saved_dfx; + double m_saved_dfy; + double m_saved_ddfx; + double m_saved_ddfy; + }; + + + + //-------------------------------------------------------catrom_to_bezier + inline curve4_points catrom_to_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + // Trans. matrix Catmull-Rom to Bezier + // + // 0 1 0 0 + // -1/6 1 1/6 0 + // 0 1/6 1 -1/6 + // 0 0 1 0 + // + return curve4_points( + x2, + y2, + (-x1 + 6*x2 + x3) / 6, + (-y1 + 6*y2 + y3) / 6, + ( x2 + 6*x3 - x4) / 6, + ( y2 + 6*y3 - y4) / 6, + x3, + y3); + } + + + //----------------------------------------------------------------------- + inline curve4_points + catrom_to_bezier(const curve4_points& cp) + { + return catrom_to_bezier(cp[0], cp[1], cp[2], cp[3], + cp[4], cp[5], cp[6], cp[7]); + } + + + + //-----------------------------------------------------ubspline_to_bezier + inline curve4_points ubspline_to_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + // Trans. matrix Uniform BSpline to Bezier + // + // 1/6 4/6 1/6 0 + // 0 4/6 2/6 0 + // 0 2/6 4/6 0 + // 0 1/6 4/6 1/6 + // + return curve4_points( + (x1 + 4*x2 + x3) / 6, + (y1 + 4*y2 + y3) / 6, + (4*x2 + 2*x3) / 6, + (4*y2 + 2*y3) / 6, + (2*x2 + 4*x3) / 6, + (2*y2 + 4*y3) / 6, + (x2 + 4*x3 + x4) / 6, + (y2 + 4*y3 + y4) / 6); + } + + + //----------------------------------------------------------------------- + inline curve4_points + ubspline_to_bezier(const curve4_points& cp) + { + return ubspline_to_bezier(cp[0], cp[1], cp[2], cp[3], + cp[4], cp[5], cp[6], cp[7]); + } + + + + + //------------------------------------------------------hermite_to_bezier + inline curve4_points hermite_to_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + // Trans. matrix Hermite to Bezier + // + // 1 0 0 0 + // 1 0 1/3 0 + // 0 1 0 -1/3 + // 0 1 0 0 + // + return curve4_points( + x1, + y1, + (3*x1 + x3) / 3, + (3*y1 + y3) / 3, + (3*x2 - x4) / 3, + (3*y2 - y4) / 3, + x2, + y2); + } + + + + //----------------------------------------------------------------------- + inline curve4_points + hermite_to_bezier(const curve4_points& cp) + { + return hermite_to_bezier(cp[0], cp[1], cp[2], cp[3], + cp[4], cp[5], cp[6], cp[7]); + } + + + //-------------------------------------------------------------curve4_div + class curve4_div + { + public: + curve4_div() : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_cusp_limit(0.0), + m_count(0) + {} + + curve4_div(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_cusp_limit(0.0), + m_count(0) + { + init(x1, y1, x2, y2, x3, y3, x4, y4); + } + + curve4_div(const curve4_points& cp) : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_count(0) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void reset() { m_points.remove_all(); m_count = 0; } + void init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4); + + void init(const curve4_points& cp) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void approximation_method(curve_approximation_method_e) {} + + curve_approximation_method_e approximation_method() const + { + return curve_div; + } + + void approximation_scale(double s) { m_approximation_scale = s; } + double approximation_scale() const { return m_approximation_scale; } + + void angle_tolerance(double a) { m_angle_tolerance = a; } + double angle_tolerance() const { return m_angle_tolerance; } + + void cusp_limit(double v) + { + m_cusp_limit = (v == 0.0) ? 0.0 : pi - v; + } + + double cusp_limit() const + { + return (m_cusp_limit == 0.0) ? 0.0 : pi - m_cusp_limit; + } + + void rewind(unsigned) + { + m_count = 0; + } + + unsigned vertex(double* x, double* y) + { + if(m_count >= m_points.size()) return path_cmd_stop; + const point_d& p = m_points[m_count++]; + *x = p.x; + *y = p.y; + return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to; + } + + private: + void bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4); + + void recursive_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4, + unsigned level); + + double m_approximation_scale; + double m_distance_tolerance_square; + double m_angle_tolerance; + double m_cusp_limit; + unsigned m_count; + pod_bvector m_points; + }; + + + //-----------------------------------------------------------------curve3 + class curve3 + { + public: + curve3() : m_approximation_method(curve_div) {} + curve3(double x1, double y1, + double x2, double y2, + double x3, double y3) : + m_approximation_method(curve_div) + { + init(x1, y1, x2, y2, x3, y3); + } + + void reset() + { + m_curve_inc.reset(); + m_curve_div.reset(); + } + + void init(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + if(m_approximation_method == curve_inc) + { + m_curve_inc.init(x1, y1, x2, y2, x3, y3); + } + else + { + m_curve_div.init(x1, y1, x2, y2, x3, y3); + } + } + + void approximation_method(curve_approximation_method_e v) + { + m_approximation_method = v; + } + + curve_approximation_method_e approximation_method() const + { + return m_approximation_method; + } + + void approximation_scale(double s) + { + m_curve_inc.approximation_scale(s); + m_curve_div.approximation_scale(s); + } + + double approximation_scale() const + { + return m_curve_inc.approximation_scale(); + } + + void angle_tolerance(double a) + { + m_curve_div.angle_tolerance(a); + } + + double angle_tolerance() const + { + return m_curve_div.angle_tolerance(); + } + + void cusp_limit(double v) + { + m_curve_div.cusp_limit(v); + } + + double cusp_limit() const + { + return m_curve_div.cusp_limit(); + } + + void rewind(unsigned path_id) + { + if(m_approximation_method == curve_inc) + { + m_curve_inc.rewind(path_id); + } + else + { + m_curve_div.rewind(path_id); + } + } + + unsigned vertex(double* x, double* y) + { + if(m_approximation_method == curve_inc) + { + return m_curve_inc.vertex(x, y); + } + return m_curve_div.vertex(x, y); + } + + private: + curve3_inc m_curve_inc; + curve3_div m_curve_div; + curve_approximation_method_e m_approximation_method; + }; + + + + + + //-----------------------------------------------------------------curve4 + class curve4 + { + public: + curve4() : m_approximation_method(curve_div) {} + curve4(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) : + m_approximation_method(curve_div) + { + init(x1, y1, x2, y2, x3, y3, x4, y4); + } + + curve4(const curve4_points& cp) : + m_approximation_method(curve_div) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void reset() + { + m_curve_inc.reset(); + m_curve_div.reset(); + } + + void init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + if(m_approximation_method == curve_inc) + { + m_curve_inc.init(x1, y1, x2, y2, x3, y3, x4, y4); + } + else + { + m_curve_div.init(x1, y1, x2, y2, x3, y3, x4, y4); + } + } + + void init(const curve4_points& cp) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void approximation_method(curve_approximation_method_e v) + { + m_approximation_method = v; + } + + curve_approximation_method_e approximation_method() const + { + return m_approximation_method; + } + + void approximation_scale(double s) + { + m_curve_inc.approximation_scale(s); + m_curve_div.approximation_scale(s); + } + double approximation_scale() const { return m_curve_inc.approximation_scale(); } + + void angle_tolerance(double v) + { + m_curve_div.angle_tolerance(v); + } + + double angle_tolerance() const + { + return m_curve_div.angle_tolerance(); + } + + void cusp_limit(double v) + { + m_curve_div.cusp_limit(v); + } + + double cusp_limit() const + { + return m_curve_div.cusp_limit(); + } + + void rewind(unsigned path_id) + { + if(m_approximation_method == curve_inc) + { + m_curve_inc.rewind(path_id); + } + else + { + m_curve_div.rewind(path_id); + } + } + + unsigned vertex(double* x, double* y) + { + if(m_approximation_method == curve_inc) + { + return m_curve_inc.vertex(x, y); + } + return m_curve_div.vertex(x, y); + } + + private: + curve4_inc m_curve_inc; + curve4_div m_curve_div; + curve_approximation_method_e m_approximation_method; + }; + + + + +} + +#endif diff --git a/agg2/include/agg_dda_line.h b/agg/include/agg_dda_line.h similarity index 94% rename from agg2/include/agg_dda_line.h rename to agg/include/agg_dda_line.h index ead31c9..c535816 100644 --- a/agg2/include/agg_dda_line.h +++ b/agg/include/agg_dda_line.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -20,7 +20,7 @@ #ifndef AGG_DDA_LINE_INCLUDED #define AGG_DDA_LINE_INCLUDED -#include +#include #include "agg_basics.h" namespace agg @@ -86,7 +86,7 @@ namespace agg { public: typedef int save_data_type; - enum { save_size = 2 }; + enum save_size_e { save_size = 2 }; //-------------------------------------------------------------------- dda2_line_interpolator() {} @@ -217,11 +217,11 @@ namespace agg class line_bresenham_interpolator { public: - enum + enum subpixel_scale_e { subpixel_shift = 8, - subpixel_size = 1 << subpixel_shift, - subpixel_mask = subpixel_size - 1 + subpixel_scale = 1 << subpixel_shift, + subpixel_mask = subpixel_scale - 1 }; //-------------------------------------------------------------------- @@ -233,9 +233,9 @@ namespace agg m_y1_lr(line_lr(y1)), m_x2_lr(line_lr(x2)), m_y2_lr(line_lr(y2)), - m_ver(abs(m_x2_lr - m_x1_lr) < abs(m_y2_lr - m_y1_lr)), - m_len(m_ver ? abs(m_y2_lr - m_y1_lr) : - abs(m_x2_lr - m_x1_lr)), + m_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, diff --git a/agg2/include/agg_ellipse.h b/agg/include/agg_ellipse.h similarity index 62% rename from agg2/include/agg_ellipse.h rename to agg/include/agg_ellipse.h index fcd0d11..b046b1c 100644 --- a/agg2/include/agg_ellipse.h +++ b/agg/include/agg_ellipse.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -21,7 +21,7 @@ #define AGG_ELLIPSE_INCLUDED #include "agg_basics.h" -#include +#include namespace agg { @@ -30,27 +30,41 @@ namespace agg class ellipse { public: - ellipse() : m_x(0.0), m_y(0.0), m_rx(1.0), m_ry(1.0), m_num(4), m_step(0) {} - ellipse(double x, double y, double rx, double ry, unsigned num_steps) - : m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_num(num_steps), m_step(0) {} + 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 init(double x, double y, double rx, double ry, unsigned num_steps); void approximation_scale(double scale); - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: + void calc_num_steps(); + double m_x; double m_y; double m_rx; double m_ry; + double m_scale; unsigned m_num; unsigned m_step; + bool m_cw; }; - //------------------------------------------------------------------------ - inline void ellipse::init(double x, double y, double rx, double ry, unsigned num_steps) + inline void ellipse::init(double x, double y, double rx, double ry, + unsigned num_steps, bool cw) { m_x = x; m_y = y; @@ -58,13 +72,23 @@ namespace agg m_ry = ry; m_num = num_steps; m_step = 0; + m_cw = cw; + if(m_num == 0) calc_num_steps(); } //------------------------------------------------------------------------ inline void ellipse::approximation_scale(double scale) { - m_num = unsigned((fabs(m_rx) + fabs(m_ry) + 6.0) * scale); - if(m_num < 6) m_num = 6; + 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); } //------------------------------------------------------------------------ @@ -83,8 +107,9 @@ namespace agg } if(m_step > m_num) return path_cmd_stop; double angle = double(m_step) / double(m_num) * 2.0 * pi; - *x = m_x + cos(angle) * m_rx; - *y = m_y + sin(angle) * m_ry; + 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); } diff --git a/agg2/include/agg_ellipse_bresenham.h b/agg/include/agg_ellipse_bresenham.h similarity index 96% rename from agg2/include/agg_ellipse_bresenham.h rename to agg/include/agg_ellipse_bresenham.h index 7ce425b..ee3b9c4 100644 --- a/agg2/include/agg_ellipse_bresenham.h +++ b/agg/include/agg_ellipse_bresenham.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. diff --git a/agg2/include/agg_embedded_raster_fonts.h b/agg/include/agg_embedded_raster_fonts.h similarity index 95% rename from agg2/include/agg_embedded_raster_fonts.h rename to agg/include/agg_embedded_raster_fonts.h index 8068de2..9d522d6 100644 --- a/agg2/include/agg_embedded_raster_fonts.h +++ b/agg/include/agg_embedded_raster_fonts.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. diff --git a/agg2/include/agg_font_cache_manager.h b/agg/include/agg_font_cache_manager.h similarity index 83% rename from agg2/include/agg_font_cache_manager.h rename to agg/include/agg_font_cache_manager.h index a2a9694..4f362d1 100644 --- a/agg2/include/agg_font_cache_manager.h +++ b/agg/include/agg_font_cache_manager.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -16,7 +16,7 @@ #ifndef AGG_FONT_CACHE_MANAGER_INCLUDED #define AGG_FONT_CACHE_MANAGER_INCLUDED -#include +#include #include "agg_array.h" namespace agg @@ -39,7 +39,7 @@ namespace agg int8u* data; unsigned data_size; glyph_data_type data_type; - rect bounds; + rect_i bounds; double advance_x; double advance_y; }; @@ -49,22 +49,26 @@ namespace agg class font_cache { public: - enum { block_size = 16384-16 }; + enum block_size_e { block_size = 16384-16 }; //-------------------------------------------------------------------- - font_cache(const char* font_signature) : + font_cache() : m_allocator(block_size), m_font_signature(0) + {} + + //-------------------------------------------------------------------- + void signature(const char* font_signature) { - m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1); - strcpy(m_font_signature, font_signature); - memset(m_glyphs, 0, sizeof(m_glyphs)); + m_font_signature = (char*)m_allocator.allocate(std::strlen(font_signature) + 1); + std::strcpy(m_font_signature, font_signature); + std::memset(m_glyphs, 0, sizeof(m_glyphs)); } //-------------------------------------------------------------------- bool font_is(const char* font_signature) const { - return strcmp(font_signature, m_font_signature) == 0; + return std::strcmp(font_signature, m_font_signature) == 0; } //-------------------------------------------------------------------- @@ -83,7 +87,7 @@ namespace agg unsigned glyph_index, unsigned data_size, glyph_data_type data_type, - const rect& bounds, + const rect_i& bounds, double advance_x, double advance_y) { @@ -93,7 +97,7 @@ namespace agg m_glyphs[msb] = (glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256, sizeof(glyph_cache*)); - memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256); + std::memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256); } unsigned lsb = glyph_code & 0xFF; @@ -101,20 +105,20 @@ namespace agg glyph_cache* glyph = (glyph_cache*)m_allocator.allocate(sizeof(glyph_cache), - sizeof(int8u*)); - - 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; + 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: - pod_allocator m_allocator; + block_allocator m_allocator; glyph_cache** m_glyphs[256]; char* m_font_signature; }; @@ -135,14 +139,14 @@ namespace agg unsigned i; for(i = 0; i < m_num_fonts; ++i) { - delete m_fonts[i]; + obj_allocator::deallocate(m_fonts[i]); } - delete [] m_fonts; + pod_allocator::deallocate(m_fonts, m_max_fonts); } //-------------------------------------------------------------------- font_cache_pool(unsigned max_fonts=32) : - m_fonts(new font_cache* [max_fonts]), + m_fonts(pod_allocator::allocate(max_fonts)), m_max_fonts(max_fonts), m_num_fonts(0), m_cur_font(0) @@ -157,8 +161,9 @@ namespace agg { if(reset_cache) { - delete m_fonts[idx]; - m_fonts[idx] = new font_cache(font_signature); + obj_allocator::deallocate(m_fonts[idx]); + m_fonts[idx] = obj_allocator::allocate(); + m_fonts[idx]->signature(font_signature); } m_cur_font = m_fonts[idx]; } @@ -166,13 +171,14 @@ namespace agg { if(m_num_fonts >= m_max_fonts) { - delete m_fonts[0]; - memcpy(m_fonts, + obj_allocator::deallocate(m_fonts[0]); + std::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] = new font_cache(font_signature); + m_fonts[m_num_fonts] = obj_allocator::allocate(); + m_fonts[m_num_fonts]->signature(font_signature); m_cur_font = m_fonts[m_num_fonts]; ++m_num_fonts; } @@ -196,7 +202,7 @@ namespace agg unsigned glyph_index, unsigned data_size, glyph_data_type data_type, - const rect& bounds, + const rect_i& bounds, double advance_x, double advance_y) { @@ -269,6 +275,12 @@ namespace agg m_last_glyph(0) {} + //-------------------------------------------------------------------- + void reset_last_glyph() + { + m_prev_glyph = m_last_glyph = 0; + } + //-------------------------------------------------------------------- const glyph_cache* glyph(unsigned glyph_code) { @@ -299,12 +311,15 @@ namespace agg } //-------------------------------------------------------------------- - void init_embedded_adaptors(const glyph_cache* gl, double x, double y) + void init_embedded_adaptors(const glyph_cache* gl, + double x, double y, + double scale=1.0) { if(gl) { switch(gl->data_type) { + default: return; case glyph_data_mono: m_mono_adaptor.init(gl->data, gl->data_size, x, y); break; @@ -314,7 +329,7 @@ namespace agg break; case glyph_data_outline: - m_path_adaptor.init(gl->data, gl->data_size, x, y); + m_path_adaptor.init(gl->data, gl->data_size, x, y, scale); break; } } diff --git a/agg/include/agg_font_cache_manager2.h b/agg/include/agg_font_cache_manager2.h new file mode 100644 index 0000000..f6b06d1 --- /dev/null +++ b/agg/include/agg_font_cache_manager2.h @@ -0,0 +1,311 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_FONT_CACHE_MANAGER2_INCLUDED +#define AGG_FONT_CACHE_MANAGER2_INCLUDED + +#include +#include +#include +#include "agg_array.h" + +namespace agg { + +namespace fman { + //---------------------------------------------------------glyph_data_type + enum glyph_data_type + { + glyph_data_invalid = 0, + glyph_data_mono = 1, + glyph_data_gray8 = 2, + glyph_data_outline = 3 + }; + + + //-------------------------------------------------------------cached_glyph + struct cached_glyph + { + void * cached_font; + unsigned glyph_code; + unsigned glyph_index; + int8u* data; + unsigned data_size; + glyph_data_type data_type; + rect_i bounds; + double advance_x; + double advance_y; + }; + + + //--------------------------------------------------------------cached_glyphs + class cached_glyphs + { + public: + enum block_size_e { block_size = 16384-16 }; + + //-------------------------------------------------------------------- + cached_glyphs() + : m_allocator(block_size) + { std::memset(m_glyphs, 0, sizeof(m_glyphs)); } + + //-------------------------------------------------------------------- + const cached_glyph* 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; + } + + //-------------------------------------------------------------------- + cached_glyph* cache_glyph( + void * cached_font, + 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] = + (cached_glyph**)m_allocator.allocate(sizeof(cached_glyph*) * 256, + sizeof(cached_glyph*)); + std::memset(m_glyphs[msb], 0, sizeof(cached_glyph*) * 256); + } + + unsigned lsb = glyph_code & 0xFF; + if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite + + cached_glyph* glyph = + (cached_glyph*)m_allocator.allocate(sizeof(cached_glyph), + sizeof(double)); + + glyph->cached_font = cached_font; + glyph->glyph_code = glyph_code; + 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; + cached_glyph** m_glyphs[256]; + }; + + + + //------------------------------------------------------------------------ + 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 font_cache_manager + { + public: + typedef FontEngine font_engine_type; + typedef font_cache_manager 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; + + struct cached_font + { + cached_font( + font_engine_type& engine, + typename FontEngine::loaded_face *face, + double height, + double width, + bool hinting, + glyph_rendering rendering ) + : m_engine( engine ) + , m_face( face ) + , m_height( height ) + , m_width( width ) + , m_hinting( hinting ) + , m_rendering( rendering ) + { + select_face(); + m_face_height=m_face->height(); + m_face_width=m_face->width(); + m_face_ascent=m_face->ascent(); + m_face_descent=m_face->descent(); + m_face_ascent_b=m_face->ascent_b(); + m_face_descent_b=m_face->descent_b(); + } + + double height() const + { + return m_face_height; + } + + double width() const + { + return m_face_width; + } + + double ascent() const + { + return m_face_ascent; + } + + double descent() const + { + return m_face_descent; + } + + double ascent_b() const + { + return m_face_ascent_b; + } + + double descent_b() const + { + return m_face_descent_b; + } + + bool add_kerning( const cached_glyph *first, const cached_glyph *second, double* x, double* y) + { + if( !first || !second ) + return false; + select_face(); + return m_face->add_kerning( + first->glyph_index, second->glyph_index, x, y ); + } + + void select_face() + { + m_face->select_instance( m_height, m_width, m_hinting, m_rendering ); + } + + const cached_glyph *get_glyph(unsigned cp) + { + const cached_glyph *glyph=m_glyphs.find_glyph(cp); + if( glyph==0 ) + { + typename FontEngine::prepared_glyph prepared; + select_face(); + bool success=m_face->prepare_glyph(cp, &prepared); + if( success ) + { + glyph=m_glyphs.cache_glyph( + this, + prepared.glyph_code, + prepared.glyph_index, + prepared.data_size, + prepared.data_type, + prepared.bounds, + prepared.advance_x, + prepared.advance_y ); + assert( glyph!=0 ); + m_face->write_glyph_to(&prepared,glyph->data); + } + } + return glyph; + } + + font_engine_type& m_engine; + typename FontEngine::loaded_face *m_face; + double m_height; + double m_width; + bool m_hinting; + glyph_rendering m_rendering; + double m_face_height; + double m_face_width; + double m_face_ascent; + double m_face_descent; + double m_face_ascent_b; + double m_face_descent_b; + cached_glyphs m_glyphs; + }; + + //-------------------------------------------------------------------- + font_cache_manager(font_engine_type& engine, unsigned max_fonts=32) + :m_engine(engine) + { } + + //-------------------------------------------------------------------- + void init_embedded_adaptors(const cached_glyph* gl, + double x, double y, + double scale=1.0) + { + if(gl) + { + switch(gl->data_type) + { + default: return; + case glyph_data_mono: + m_mono_adaptor.init(gl->data, gl->data_size, x, y); + break; + + case glyph_data_gray8: + m_gray8_adaptor.init(gl->data, gl->data_size, x, y); + break; + + case glyph_data_outline: + m_path_adaptor.init(gl->data, gl->data_size, x, y, scale); + break; + } + } + } + + + //-------------------------------------------------------------------- + path_adaptor_type& path_adaptor() { return m_path_adaptor; } + gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; } + gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; } + mono_adaptor_type& mono_adaptor() { return m_mono_adaptor; } + mono_scanline_type& mono_scanline() { return m_mono_scanline; } + + + private: + //-------------------------------------------------------------------- + font_cache_manager(const self_type&); + const self_type& operator = (const self_type&); + + font_engine_type& m_engine; + path_adaptor_type m_path_adaptor; + gray8_adaptor_type m_gray8_adaptor; + gray8_scanline_type m_gray8_scanline; + mono_adaptor_type m_mono_adaptor; + mono_scanline_type m_mono_scanline; + }; + +} +} + +#endif + diff --git a/agg2/include/agg_gamma_functions.h b/agg/include/agg_gamma_functions.h similarity index 89% rename from agg2/include/agg_gamma_functions.h rename to agg/include/agg_gamma_functions.h index 527cfd6..a29081d 100644 --- a/agg2/include/agg_gamma_functions.h +++ b/agg/include/agg_gamma_functions.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -16,7 +16,6 @@ #ifndef AGG_GAMMA_FUNCTIONS_INCLUDED #define AGG_GAMMA_FUNCTIONS_INCLUDED -#include #include "agg_basics.h" namespace agg @@ -115,6 +114,15 @@ namespace agg 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); + } } #endif diff --git a/agg/include/agg_gamma_lut.h b/agg/include/agg_gamma_lut.h new file mode 100644 index 0000000..52e6140 --- /dev/null +++ b/agg/include/agg_gamma_lut.h @@ -0,0 +1,307 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_GAMMA_LUT_INCLUDED +#define AGG_GAMMA_LUT_INCLUDED + +#include +#include "agg_basics.h" +#include "agg_gamma_functions.h" + +namespace agg +{ + template class gamma_lut + { + public: + typedef gamma_lut self_type; + + enum gamma_scale_e + { + gamma_shift = GammaShift, + gamma_size = 1 << gamma_shift, + gamma_mask = gamma_size - 1 + }; + + enum hi_res_scale_e + { + hi_res_shift = HiResShift, + hi_res_size = 1 << hi_res_shift, + hi_res_mask = hi_res_size - 1 + }; + + ~gamma_lut() + { + pod_allocator::deallocate(m_inv_gamma, hi_res_size); + pod_allocator::deallocate(m_dir_gamma, gamma_size); + } + + gamma_lut() : + m_gamma(1.0), + m_dir_gamma(pod_allocator::allocate(gamma_size)), + m_inv_gamma(pod_allocator::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::allocate(gamma_size)), + m_inv_gamma(pod_allocator::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(std::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(std::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 sRGB_lut_base + { + public: + LinearType dir(int8u v) const + { + return m_dir_table[v]; + } + + int8u inv(LinearType v) const + { + // 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; + } + + 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 sRGB_lut; + + template<> + class sRGB_lut : public sRGB_lut_base + { + 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)); + } + } + }; + + template<> + class sRGB_lut : public sRGB_lut_base + { + public: + sRGB_lut() + { + // Generate lookup tables. + m_dir_table[0] = 0; + m_inv_table[0] = 0; + for (int 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)); + } + } + }; + + template<> + class sRGB_lut : public sRGB_lut_base + { + public: + sRGB_lut() + { + // Generate lookup tables. + m_dir_table[0] = 0; + m_inv_table[0] = 0; + for (int 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)); + } + } + + int8u inv(int8u v) const + { + // In this case, the inverse transform is a simple lookup. + return m_inv_table[v]; + } + }; + + // Common base class for sRGB_conv objects. Defines an internal + // sRGB_lut object so that users don't have to. + template + 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 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 + sRGB_lut sRGB_conv_base::lut; + + // Wrapper for sRGB-linear conversion. + // Base template is undefined, specializations are provided below. + template + class sRGB_conv; + + template<> + class sRGB_conv : public sRGB_conv_base + { + public: + static float alpha_from_sRGB(int8u x) + { + static const double y = 1 / 255.0; + return float(x * y); + } + + static int8u alpha_to_sRGB(float x) + { + if (x < 0) return 0; + if (x > 1) return 255; + return int8u(0.5 + x * 255); + } + }; + + template<> + class sRGB_conv : public sRGB_conv_base + { + 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 : public sRGB_conv_base + { + public: + static int8u alpha_from_sRGB(int8u x) + { + return x; + } + + static int8u alpha_to_sRGB(int8u x) + { + return x; + } + }; +} + +#endif diff --git a/agg2/include/agg_glyph_raster_bin.h b/agg/include/agg_glyph_raster_bin.h similarity index 96% rename from agg2/include/agg_glyph_raster_bin.h rename to agg/include/agg_glyph_raster_bin.h index cd28183..57d5b98 100644 --- a/agg2/include/agg_glyph_raster_bin.h +++ b/agg/include/agg_glyph_raster_bin.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -16,7 +16,7 @@ #ifndef AGG_GLYPH_RASTER_BIN_INCLUDED #define AGG_GLYPH_RASTER_BIN_INCLUDED -#include +#include #include "agg_basics.h" namespace agg @@ -42,7 +42,7 @@ namespace agg { int t = 1; if(*(char*)&t == 0) m_big_endian = true; - memset(m_span, 0, sizeof(m_span)); + std::memset(m_span, 0, sizeof(m_span)); } //-------------------------------------------------------------------- diff --git a/agg/include/agg_gradient_lut.h b/agg/include/agg_gradient_lut.h new file mode 100644 index 0000000..9aaa426 --- /dev/null +++ b/agg/include/agg_gradient_lut.h @@ -0,0 +1,244 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_GRADIENT_LUT_INCLUDED +#define AGG_GRADIENT_LUT_INCLUDED + +#include "agg_array.h" +#include "agg_dda_line.h" +#include "agg_color_rgba.h" +#include "agg_color_gray.h" + +namespace agg +{ + + //======================================================color_interpolator + template struct color_interpolator + { + public: + typedef ColorT color_type; + + color_interpolator(const color_type& c1, + const color_type& c2, + unsigned len) : + m_c1(c1), + m_c2(c2), + m_len(len), + m_count(0) + {} + + void operator ++ () + { + ++m_count; + } + + color_type color() const + { + return m_c1.gradient(m_c2, double(m_count) / m_len); + } + + private: + color_type m_c1; + color_type m_c2; + unsigned m_len; + unsigned m_count; + }; + + //======================================================================== + // Fast specialization for rgba8 + template<> struct color_interpolator + { + 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 + { + 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 gradient_lut + { + public: + typedef ColorInterpolator interpolator_type; + typedef typename interpolator_type::color_type color_type; + enum { color_lut_size = ColorLutSize }; + + //-------------------------------------------------------------------- + gradient_lut() : m_color_lut(color_lut_size) {} + + // Build Gradient Lut + // First, call remove_all(), then add_color() at least twice, + // then build_lut(). Argument "offset" in add_color must be + // in range [0...1] and defines a color stop as it is described + // in SVG specification, section Gradients and Patterns. + // The simplest linear gradient is: + // gradient_lut.add_color(0.0, start_color); + // gradient_lut.add_color(1.0, end_color); + //-------------------------------------------------------------------- + void remove_all(); + void add_color(double offset, const color_type& color); + void build_lut(); + + // Size-index Interface. This class can be used directly as the + // ColorF in span_gradient. All it needs is two access methods + // size() and operator []. + //-------------------------------------------------------------------- + static unsigned size() + { + return color_lut_size; + } + const color_type& operator [] (unsigned i) const + { + return m_color_lut[i]; + } + + private: + //-------------------------------------------------------------------- + struct color_point + { + double offset; + color_type color; + + color_point() {} + color_point(double off, const color_type& c) : + offset(off), color(c) + { + if(offset < 0.0) offset = 0.0; + if(offset > 1.0) offset = 1.0; + } + }; + typedef agg::pod_bvector color_profile_type; + typedef agg::pod_array 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 + void gradient_lut::remove_all() + { + m_color_profile.remove_all(); + } + + //------------------------------------------------------------------------ + template + void gradient_lut::add_color(double offset, const color_type& color) + { + m_color_profile.add(color_point(offset, color)); + } + + //------------------------------------------------------------------------ + template + void gradient_lut::build_lut() + { + quick_sort(m_color_profile, offset_less); + m_color_profile.cut_at(remove_duplicates(m_color_profile, offset_equal)); + if(m_color_profile.size() >= 2) + { + unsigned i; + unsigned start = uround(m_color_profile[0].offset * color_lut_size); + unsigned end; + color_type c = m_color_profile[0].color; + for(i = 0; i < start; i++) + { + m_color_lut[i] = c; + } + for(i = 1; i < m_color_profile.size(); i++) + { + end = uround(m_color_profile[i].offset * color_lut_size); + interpolator_type ci(m_color_profile[i-1].color, + m_color_profile[i ].color, + end - start + 1); + while(start < end) + { + m_color_lut[start] = ci.color(); + ++ci; + ++start; + } + } + c = m_color_profile.last().color; + for(; end < m_color_lut.size(); end++) + { + m_color_lut[end] = c; + } + } + } +} + + + + +#endif diff --git a/agg2/include/agg_gsv_text.h b/agg/include/agg_gsv_text.h similarity index 70% rename from agg2/include/agg_gsv_text.h rename to agg/include/agg_gsv_text.h index cb9b50b..16b3aeb 100644 --- a/agg2/include/agg_gsv_text.h +++ b/agg/include/agg_gsv_text.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -20,7 +20,7 @@ #ifndef AGG_GSV_TEXT_INCLUDED #define AGG_GSV_TEXT_INCLUDED -#include "agg_basics.h" +#include "agg_array.h" #include "agg_conv_stroke.h" #include "agg_conv_transform.h" @@ -43,7 +43,6 @@ namespace agg }; public: - ~gsv_text(); gsv_text(); void font(const void* font); @@ -54,8 +53,10 @@ namespace agg void line_space(double line_space); void start_point(double x, double y); void text(const char* text); + + double text_width(); - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: @@ -80,30 +81,28 @@ namespace agg } 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; - char* m_text_buf; - unsigned m_buf_size; - char* m_cur_chr; - const void* m_font; - 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; + 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 m_text_buf; + char* m_cur_chr; + const void* m_font; + pod_array 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; }; @@ -113,7 +112,7 @@ namespace agg template class gsv_text_outline { public: - gsv_text_outline(gsv_text& text, const Transformer& trans) : + gsv_text_outline(gsv_text& text, Transformer& trans) : m_polyline(text), m_trans(m_polyline, trans) { @@ -129,11 +128,11 @@ namespace agg m_trans->transformer(trans); } - void rewind(unsigned id) + void rewind(unsigned path_id) { - m_trans.rewind(id); - m_polyline.line_join(vcgen_stroke::round_join); - m_polyline.line_cap(vcgen_stroke::round_cap); + m_trans.rewind(path_id); + m_polyline.line_join(round_join); + m_polyline.line_cap(round_cap); } unsigned vertex(double* x, double* y) diff --git a/agg/include/agg_image_accessors.h b/agg/include/agg_image_accessors.h new file mode 100644 index 0000000..c651d6d --- /dev/null +++ b/agg/include/agg_image_accessors.h @@ -0,0 +1,481 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_IMAGE_ACCESSORS_INCLUDED +#define AGG_IMAGE_ACCESSORS_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //-----------------------------------------------------image_accessor_clip + template class image_accessor_clip + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::order_type order_type; + typedef typename pixfmt_type::value_type value_type; + enum pix_width_e { pix_width = pixfmt_type::pix_width }; + + image_accessor_clip() {} + explicit image_accessor_clip(pixfmt_type& pixf, + const color_type& bk) : + m_pixf(&pixf) + { + pixfmt_type::make_pix(m_bk_buf, bk); + } + + void attach(pixfmt_type& pixf) + { + m_pixf = &pixf; + } + + void background_color(const color_type& bk) + { + pixfmt_type::make_pix(m_bk_buf, bk); + } + + private: + AGG_INLINE const int8u* pixel() const + { + if(m_y >= 0 && m_y < (int)m_pixf->height() && + m_x >= 0 && m_x < (int)m_pixf->width()) + { + return m_pixf->pix_ptr(m_x, m_y); + } + return m_bk_buf; + } + + public: + AGG_INLINE const int8u* span(int x, int y, unsigned len) + { + m_x = m_x0 = x; + m_y = y; + if(y >= 0 && y < (int)m_pixf->height() && + x >= 0 && x+(int)len <= (int)m_pixf->width()) + { + return m_pix_ptr = m_pixf->pix_ptr(x, y); + } + m_pix_ptr = 0; + return pixel(); + } + + AGG_INLINE const int8u* next_x() + { + if(m_pix_ptr) return m_pix_ptr += pix_width; + ++m_x; + return pixel(); + } + + AGG_INLINE const int8u* next_y() + { + ++m_y; + m_x = m_x0; + if(m_pix_ptr && + m_y >= 0 && m_y < (int)m_pixf->height()) + { + return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y); + } + m_pix_ptr = 0; + return pixel(); + } + + private: + const pixfmt_type* m_pixf; + int8u m_bk_buf[pix_width]; + int m_x, m_x0, m_y; + const int8u* m_pix_ptr; + }; + + + + + //--------------------------------------------------image_accessor_no_clip + template 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(pixfmt_type& pixf) : + m_pixf(&pixf) + {} + + void attach(pixfmt_type& pixf) + { + m_pixf = &pixf; + } + + AGG_INLINE const int8u* span(int x, int y, unsigned) + { + m_x = x; + m_y = y; + return m_pix_ptr = m_pixf->pix_ptr(x, y); + } + + AGG_INLINE const int8u* next_x() + { + return m_pix_ptr += pix_width; + } + + AGG_INLINE const int8u* next_y() + { + ++m_y; + return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y); + } + + private: + const pixfmt_type* m_pixf; + int m_x, m_y; + const int8u* m_pix_ptr; + }; + + + + + //----------------------------------------------------image_accessor_clone + template class image_accessor_clone + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::order_type order_type; + typedef typename pixfmt_type::value_type value_type; + enum pix_width_e { pix_width = pixfmt_type::pix_width }; + + image_accessor_clone() {} + explicit image_accessor_clone(pixfmt_type& pixf) : + m_pixf(&pixf) + {} + + void attach(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+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 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(pixfmt_type& pixf) : + m_pixf(&pixf), + m_wrap_x(pixf.width()), + m_wrap_y(pixf.height()) + {} + + void attach(pixfmt_type& pixf) + { + m_pixf = &pixf; + } + + AGG_INLINE const int8u* span(int x, int y, unsigned) + { + m_x = x; + m_row_ptr = m_pixf->pix_ptr(0, 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->pix_ptr(0, ++m_wrap_y); + return m_row_ptr + m_wrap_x(m_x) * pix_width; + } + + private: + const pixfmt_type* m_pixf; + const int8u* m_row_ptr; + int m_x; + WrapX m_wrap_x; + WrapY m_wrap_y; + }; + + + + + //--------------------------------------------------------wrap_mode_repeat + class wrap_mode_repeat + { + public: + wrap_mode_repeat() {} + wrap_mode_repeat(unsigned size) : + m_size(size), + m_add(size * (0x3FFFFFFF / size)), + m_value(0) + {} + + AGG_INLINE unsigned operator() (int v) + { + return m_value = (unsigned(v) + m_add) % m_size; + } + + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value >= m_size) m_value = 0; + return m_value; + } + private: + unsigned m_size; + unsigned m_add; + unsigned m_value; + }; + + + //---------------------------------------------------wrap_mode_repeat_pow2 + class wrap_mode_repeat_pow2 + { + public: + wrap_mode_repeat_pow2() {} + wrap_mode_repeat_pow2(unsigned size) : m_value(0) + { + m_mask = 1; + while(m_mask < size) m_mask = (m_mask << 1) | 1; + m_mask >>= 1; + } + AGG_INLINE unsigned operator() (int v) + { + return m_value = unsigned(v) & m_mask; + } + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value > m_mask) m_value = 0; + return m_value; + } + private: + unsigned m_mask; + unsigned m_value; + }; + + + //----------------------------------------------wrap_mode_repeat_auto_pow2 + class wrap_mode_repeat_auto_pow2 + { + public: + wrap_mode_repeat_auto_pow2() {} + wrap_mode_repeat_auto_pow2(unsigned size) : + m_size(size), + m_add(size * (0x3FFFFFFF / size)), + m_mask((m_size & (m_size-1)) ? 0 : m_size-1), + m_value(0) + {} + + AGG_INLINE unsigned operator() (int v) + { + if(m_mask) return m_value = unsigned(v) & m_mask; + return m_value = (unsigned(v) + m_add) % m_size; + } + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value >= m_size) m_value = 0; + return m_value; + } + + private: + unsigned m_size; + unsigned m_add; + unsigned m_mask; + unsigned m_value; + }; + + + //-------------------------------------------------------wrap_mode_reflect + class wrap_mode_reflect + { + public: + wrap_mode_reflect() {} + wrap_mode_reflect(unsigned size) : + m_size(size), + m_size2(size * 2), + m_add(m_size2 * (0x3FFFFFFF / m_size2)), + m_value(0) + {} + + AGG_INLINE unsigned operator() (int v) + { + m_value = (unsigned(v) + m_add) % m_size2; + if(m_value >= m_size) return m_size2 - m_value - 1; + return m_value; + } + + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value >= m_size2) m_value = 0; + if(m_value >= m_size) return m_size2 - m_value - 1; + return m_value; + } + private: + unsigned m_size; + unsigned m_size2; + unsigned m_add; + unsigned m_value; + }; + + + + //--------------------------------------------------wrap_mode_reflect_pow2 + class wrap_mode_reflect_pow2 + { + public: + wrap_mode_reflect_pow2() {} + wrap_mode_reflect_pow2(unsigned size) : m_value(0) + { + m_mask = 1; + m_size = 1; + while(m_mask < size) + { + m_mask = (m_mask << 1) | 1; + m_size <<= 1; + } + } + AGG_INLINE unsigned operator() (int v) + { + m_value = unsigned(v) & m_mask; + if(m_value >= m_size) return m_mask - m_value; + return m_value; + } + AGG_INLINE unsigned operator++ () + { + ++m_value; + m_value &= m_mask; + if(m_value >= m_size) return m_mask - m_value; + return m_value; + } + private: + unsigned m_size; + unsigned m_mask; + unsigned m_value; + }; + + + + //---------------------------------------------wrap_mode_reflect_auto_pow2 + class wrap_mode_reflect_auto_pow2 + { + public: + wrap_mode_reflect_auto_pow2() {} + wrap_mode_reflect_auto_pow2(unsigned size) : + m_size(size), + m_size2(size * 2), + m_add(m_size2 * (0x3FFFFFFF / m_size2)), + m_mask((m_size2 & (m_size2-1)) ? 0 : m_size2-1), + m_value(0) + {} + + AGG_INLINE unsigned operator() (int v) + { + m_value = m_mask ? unsigned(v) & m_mask : + (unsigned(v) + m_add) % m_size2; + if(m_value >= m_size) return m_size2 - m_value - 1; + return m_value; + } + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value >= m_size2) m_value = 0; + if(m_value >= m_size) return m_size2 - m_value - 1; + return m_value; + } + + private: + unsigned m_size; + unsigned m_size2; + unsigned m_add; + unsigned m_mask; + unsigned m_value; + }; + + +} + + +#endif diff --git a/agg/include/agg_image_filters.h b/agg/include/agg_image_filters.h new file mode 100644 index 0000000..5199f51 --- /dev/null +++ b/agg/include/agg_image_filters.h @@ -0,0 +1,449 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Image transformation filters, +// Filtering classes (image_filter_lut, image_filter), +// Basic filter shape classes +//---------------------------------------------------------------------------- +#ifndef AGG_IMAGE_FILTERS_INCLUDED +#define AGG_IMAGE_FILTERS_INCLUDED + +#include "agg_array.h" +#include "agg_math.h" + +namespace agg +{ + + // See Implementation agg_image_filters.cpp + + enum image_filter_scale_e + { + image_filter_shift = 14, //----image_filter_shift + image_filter_scale = 1 << image_filter_shift, //----image_filter_scale + image_filter_mask = image_filter_scale - 1 //----image_filter_mask + }; + + enum image_subpixel_scale_e + { + image_subpixel_shift = 8, //----image_subpixel_shift + image_subpixel_scale = 1 << image_subpixel_shift, //----image_subpixel_scale + image_subpixel_mask = image_subpixel_scale - 1 //----image_subpixel_mask + }; + + + //-----------------------------------------------------image_filter_lut + class image_filter_lut + { + public: + template void calculate(const FilterF& filter, + bool normalization=true) + { + filter; // prevent erroneous C4100 in MSVC + double r = filter.radius(); + realloc_lut(r); + unsigned i; + unsigned pivot = diameter() << (image_subpixel_shift - 1); + for(i = 0; i < pivot; i++) + { + double x = double(i) / double(image_subpixel_scale); + double y = filter.calc_weight(x); + m_weight_array[pivot + i] = + m_weight_array[pivot - i] = (int16)iround(y * image_filter_scale); + } + unsigned end = (diameter() << image_subpixel_shift) - 1; + m_weight_array[0] = m_weight_array[end]; + if(normalization) + { + normalize(); + } + } + + image_filter_lut() : m_radius(0), m_diameter(0), m_start(0) {} + + template image_filter_lut(const FilterF& filter, + bool normalization=true) + { + calculate(filter, normalization); + } + + double radius() const { return m_radius; } + unsigned diameter() const { return m_diameter; } + int start() const { return m_start; } + const int16* weight_array() const { return &m_weight_array[0]; } + void normalize(); + + private: + void realloc_lut(double radius); + image_filter_lut(const image_filter_lut&); + const image_filter_lut& operator = (const image_filter_lut&); + + double m_radius; + unsigned m_diameter; + int m_start; + pod_array m_weight_array; + }; + + + + //--------------------------------------------------------image_filter + template 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) {t = x - 1.5; return 0.5 * t * t;} + return 0.0; + } + }; + + //------------------------------------------------image_filter_bicubic + class image_filter_bicubic + { + static double pow3(double x) + { + return (x <= 0.0) ? 0.0 : x * x * x; + } + + public: + static double radius() { return 2.0; } + static double calc_weight(double x) + { + return + (1.0/6.0) * + (pow3(x + 2) - 4 * pow3(x + 1) + 6 * pow3(x) - 4 * pow3(x - 1)); + } + }; + + //-------------------------------------------------image_filter_kaiser + class image_filter_kaiser + { + double a; + double i0a; + double epsilon; + + public: + image_filter_kaiser(double b = 6.33) : + a(b), epsilon(1e-12) + { + i0a = 1.0 / bessel_i0(b); + } + + static double radius() { return 1.0; } + double calc_weight(double x) const + { + return bessel_i0(a * std::sqrt(1. - x * x)) * i0a; + } + + private: + double bessel_i0(double x) const + { + int i; + double sum, y, t; + + sum = 1.; + y = x * x / 4.; + t = y; + + for(i = 2; t > epsilon; i++) + { + sum += t; + t *= (double)y / (i * i); + } + return sum; + } + }; + + //----------------------------------------------image_filter_catrom + struct image_filter_catrom + { + static double radius() { return 2.0; } + static double calc_weight(double x) + { + if(x < 1.0) return 0.5 * (2.0 + x * x * (-5.0 + x * 3.0)); + if(x < 2.0) return 0.5 * (4.0 + x * (-8.0 + x * (5.0 - x))); + return 0.; + } + }; + + //---------------------------------------------image_filter_mitchell + class image_filter_mitchell + { + double p0, p2, p3; + double q0, q1, q2, q3; + + public: + image_filter_mitchell(double b = 1.0/3.0, double c = 1.0/3.0) : + p0((6.0 - 2.0 * b) / 6.0), + p2((-18.0 + 12.0 * b + 6.0 * c) / 6.0), + p3((12.0 - 9.0 * b - 6.0 * c) / 6.0), + q0((8.0 * b + 24.0 * c) / 6.0), + q1((-12.0 * b - 48.0 * c) / 6.0), + q2((6.0 * b + 30.0 * c) / 6.0), + q3((-b - 6.0 * c) / 6.0) + {} + + static double radius() { return 2.0; } + double calc_weight(double x) const + { + if(x < 1.0) return p0 + x * x * (p2 + x * p3); + if(x < 2.0) return q0 + x * (q1 + x * (q2 + x * q3)); + return 0.0; + } + }; + + + //----------------------------------------------image_filter_spline16 + struct image_filter_spline16 + { + static double radius() { return 2.0; } + static double calc_weight(double x) + { + if(x < 1.0) + { + return ((x - 9.0/5.0 ) * x - 1.0/5.0 ) * x + 1.0; + } + return ((-1.0/3.0 * (x-1) + 4.0/5.0) * (x-1) - 7.0/15.0 ) * (x-1); + } + }; + + + //---------------------------------------------image_filter_spline36 + struct image_filter_spline36 + { + static double radius() { return 3.0; } + static double calc_weight(double x) + { + if(x < 1.0) + { + return ((13.0/11.0 * x - 453.0/209.0) * x - 3.0/209.0) * x + 1.0; + } + if(x < 2.0) + { + return ((-6.0/11.0 * (x-1) + 270.0/209.0) * (x-1) - 156.0/ 209.0) * (x-1); + } + return ((1.0/11.0 * (x-2) - 45.0/209.0) * (x-2) + 26.0/209.0) * (x-2); + } + }; + + + //----------------------------------------------image_filter_gaussian + struct image_filter_gaussian + { + static double radius() { return 2.0; } + static double calc_weight(double x) + { + return std::exp(-2.0 * x * x) * std::sqrt(2.0 / pi); + } + }; + + + //------------------------------------------------image_filter_bessel + struct image_filter_bessel + { + static double radius() { return 3.2383; } + static double calc_weight(double x) + { + return (x == 0.0) ? pi / 4.0 : besj(pi * x, 1) / (2.0 * x); + } + }; + + + //-------------------------------------------------image_filter_sinc + class image_filter_sinc + { + public: + image_filter_sinc(double r) : m_radius(r < 2.0 ? 2.0 : r) {} + double radius() const { return m_radius; } + double calc_weight(double x) const + { + if(x == 0.0) return 1.0; + x *= pi; + return 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); + } + private: + double m_radius; + }; + + + //----------------------------------------------image_filter_blackman + class image_filter_blackman + { + public: + image_filter_blackman(double r) : m_radius(r < 2.0 ? 2.0 : r) {} + double radius() const { return m_radius; } + double calc_weight(double x) const + { + if(x == 0.0) return 1.0; + if(x > m_radius) return 0.0; + x *= pi; + double xr = x / m_radius; + return (std::sin(x) / x) * (0.42 + 0.5*std::cos(xr) + 0.08*std::cos(2*xr)); + } + private: + double m_radius; + }; + + //------------------------------------------------image_filter_sinc36 + class image_filter_sinc36 : public image_filter_sinc + { public: image_filter_sinc36() : image_filter_sinc(3.0){} }; + + //------------------------------------------------image_filter_sinc64 + class image_filter_sinc64 : public image_filter_sinc + { public: image_filter_sinc64() : image_filter_sinc(4.0){} }; + + //-----------------------------------------------image_filter_sinc100 + class image_filter_sinc100 : public image_filter_sinc + { public: image_filter_sinc100() : image_filter_sinc(5.0){} }; + + //-----------------------------------------------image_filter_sinc144 + class image_filter_sinc144 : public image_filter_sinc + { public: image_filter_sinc144() : image_filter_sinc(6.0){} }; + + //-----------------------------------------------image_filter_sinc196 + class image_filter_sinc196 : public image_filter_sinc + { public: image_filter_sinc196() : image_filter_sinc(7.0){} }; + + //-----------------------------------------------image_filter_sinc256 + class image_filter_sinc256 : public image_filter_sinc + { public: image_filter_sinc256() : image_filter_sinc(8.0){} }; + + //---------------------------------------------image_filter_lanczos36 + class image_filter_lanczos36 : public image_filter_lanczos + { public: image_filter_lanczos36() : image_filter_lanczos(3.0){} }; + + //---------------------------------------------image_filter_lanczos64 + class image_filter_lanczos64 : public image_filter_lanczos + { public: image_filter_lanczos64() : image_filter_lanczos(4.0){} }; + + //--------------------------------------------image_filter_lanczos100 + class image_filter_lanczos100 : public image_filter_lanczos + { public: image_filter_lanczos100() : image_filter_lanczos(5.0){} }; + + //--------------------------------------------image_filter_lanczos144 + class image_filter_lanczos144 : public image_filter_lanczos + { public: image_filter_lanczos144() : image_filter_lanczos(6.0){} }; + + //--------------------------------------------image_filter_lanczos196 + class image_filter_lanczos196 : public image_filter_lanczos + { public: image_filter_lanczos196() : image_filter_lanczos(7.0){} }; + + //--------------------------------------------image_filter_lanczos256 + class image_filter_lanczos256 : public image_filter_lanczos + { public: image_filter_lanczos256() : image_filter_lanczos(8.0){} }; + + //--------------------------------------------image_filter_blackman36 + class image_filter_blackman36 : public image_filter_blackman + { public: image_filter_blackman36() : image_filter_blackman(3.0){} }; + + //--------------------------------------------image_filter_blackman64 + class image_filter_blackman64 : public image_filter_blackman + { public: image_filter_blackman64() : image_filter_blackman(4.0){} }; + + //-------------------------------------------image_filter_blackman100 + class image_filter_blackman100 : public image_filter_blackman + { public: image_filter_blackman100() : image_filter_blackman(5.0){} }; + + //-------------------------------------------image_filter_blackman144 + class image_filter_blackman144 : public image_filter_blackman + { public: image_filter_blackman144() : image_filter_blackman(6.0){} }; + + //-------------------------------------------image_filter_blackman196 + class image_filter_blackman196 : public image_filter_blackman + { public: image_filter_blackman196() : image_filter_blackman(7.0){} }; + + //-------------------------------------------image_filter_blackman256 + class image_filter_blackman256 : public image_filter_blackman + { public: image_filter_blackman256() : image_filter_blackman(8.0){} }; + + +} + +#endif diff --git a/agg2/include/agg_line_aa_basics.h b/agg/include/agg_line_aa_basics.h similarity index 52% rename from agg2/include/agg_line_aa_basics.h rename to agg/include/agg_line_aa_basics.h index 7ae650c..6726b9d 100644 --- a/agg2/include/agg_line_aa_basics.h +++ b/agg/include/agg_line_aa_basics.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -15,7 +15,7 @@ #ifndef AGG_LINE_AA_BASICS_INCLUDED #define AGG_LINE_AA_BASICS_INCLUDED -#include +#include #include "agg_basics.h" namespace agg @@ -24,44 +24,58 @@ namespace agg // See Implementation agg_line_aa_basics.cpp //------------------------------------------------------------------------- - enum + enum line_subpixel_scale_e { - line_subpixel_shift = 8, //----line_subpixel_shift - line_subpixel_size = 1 << line_subpixel_shift, //----line_subpixel_size - line_subpixel_mask = line_subpixel_size - 1 //----line_subpixel_mask + 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 + enum line_mr_subpixel_scale_e { line_mr_subpixel_shift = 4, //----line_mr_subpixel_shift - line_mr_subpixel_size = 1 << line_mr_subpixel_shift, //----line_mr_subpixel_size - line_mr_subpixel_mask = line_mr_subpixel_size - 1 //----line_mr_subpixel_mask + 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 - inline int line_mr(int x) + AGG_INLINE int line_mr(int x) { return x >> (line_subpixel_shift - line_mr_subpixel_shift); } //-------------------------------------------------------------------line_hr - inline int line_hr(int x) + AGG_INLINE int line_hr(int x) { return x << (line_subpixel_shift - line_mr_subpixel_shift); } //---------------------------------------------------------------line_dbl_hr - inline int line_dbl_hr(int x) + AGG_INLINE int line_dbl_hr(int x) { return x << line_subpixel_shift; } //---------------------------------------------------------------line_coord - inline int line_coord(double x) + struct line_coord { - return int(x * line_subpixel_size); - } + 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::iround(x * line_subpixel_scale); + } + }; //==========================================================line_parameters struct line_parameters @@ -70,8 +84,8 @@ namespace agg line_parameters() {} line_parameters(int x1_, int y1_, int x2_, int y2_, int len_) : x1(x1_), y1(y1_), x2(x2_), y2(y2_), - dx(abs(x2_ - x1_)), - dy(abs(y2_ - y1_)), + dx(std::abs(x2_ - x1_)), + dy(std::abs(y2_ - y1_)), sx((x2_ > x1_) ? 1 : -1), sy((y2_ > y1_) ? 1 : -1), vertical(dy >= dx), @@ -96,6 +110,29 @@ namespace agg { 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; @@ -105,8 +142,8 @@ namespace agg int octant; //--------------------------------------------------------------------- - static int8u s_orthogonal_quadrant[8]; - static int8u s_diagonal_quadrant[8]; + static const int8u s_orthogonal_quadrant[8]; + static const int8u s_diagonal_quadrant[8]; }; @@ -118,6 +155,35 @@ namespace agg const line_parameters& l2, int* x, int* y); + + //-------------------------------------------fix_degenerate_bisectrix_start + void inline fix_degenerate_bisectrix_start(const line_parameters& lp, + int* x, int* y) + { + int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) - + double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len); + if(d < line_subpixel_scale/2) + { + *x = lp.x1 + (lp.y2 - lp.y1); + *y = lp.y1 - (lp.x2 - lp.x1); + } + } + + + //---------------------------------------------fix_degenerate_bisectrix_end + void inline fix_degenerate_bisectrix_end(const line_parameters& lp, + int* x, int* y) + { + int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) - + double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len); + if(d < line_subpixel_scale/2) + { + *x = lp.x2 + (lp.y2 - lp.y1); + *y = lp.y2 - (lp.x2 - lp.x1); + } + } + + } #endif diff --git a/agg/include/agg_math.h b/agg/include/agg_math.h new file mode 100644 index 0000000..b3051bc --- /dev/null +++ b/agg/include/agg_math.h @@ -0,0 +1,437 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// Bessel function (besj) was adapted for use in AGG library by Andy Wilk +// Contact: castor.vulgaris@gmail.com +//---------------------------------------------------------------------------- + +#ifndef AGG_MATH_INCLUDED +#define AGG_MATH_INCLUDED + +#include +#include "agg_basics.h" + +namespace agg +{ + + //------------------------------------------------------vertex_dist_epsilon + // Coinciding points maximal distance (Epsilon) + const double vertex_dist_epsilon = 1e-14; + + //-----------------------------------------------------intersection_epsilon + // See calc_intersection + const double intersection_epsilon = 1.0e-30; + + //------------------------------------------------------------cross_product + AGG_INLINE double cross_product(double x1, double y1, + double x2, double y2, + double x, double y) + { + return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1); + } + + //--------------------------------------------------------point_in_triangle + AGG_INLINE bool point_in_triangle(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x, double y) + { + bool cp1 = cross_product(x1, y1, x2, y2, x, y) < 0.0; + bool cp2 = cross_product(x2, y2, x3, y3, x, y) < 0.0; + bool cp3 = cross_product(x3, y3, x1, y1, x, y) < 0.0; + return cp1 == cp2 && cp2 == cp3 && cp3 == cp1; + } + + //-----------------------------------------------------------calc_distance + AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2) + { + double dx = x2-x1; + double dy = y2-y1; + return std::sqrt(dx * dx + dy * dy); + } + + //--------------------------------------------------------calc_sq_distance + AGG_INLINE double calc_sq_distance(double x1, double y1, double x2, double y2) + { + double dx = x2-x1; + double dy = y2-y1; + return dx * dx + dy * dy; + } + + //------------------------------------------------calc_line_point_distance + AGG_INLINE double calc_line_point_distance(double x1, double y1, + double x2, double y2, + double x, double y) + { + double dx = x2-x1; + double dy = y2-y1; + double d = std::sqrt(dx * dx + dy * dy); + if(d < vertex_dist_epsilon) + { + return calc_distance(x1, y1, x, y); + } + return ((x - x2) * dy - (y - y2) * dx) / d; + } + + //-------------------------------------------------------calc_line_point_u + AGG_INLINE double calc_segment_point_u(double x1, double y1, + double x2, double y2, + double x, double y) + { + double dx = x2 - x1; + double dy = y2 - y1; + + if(dx == 0 && dy == 0) + { + return 0; + } + + double pdx = x - x1; + double pdy = y - y1; + + return (pdx * dx + pdy * dy) / (dx * dx + dy * dy); + } + + //---------------------------------------------calc_line_point_sq_distance + AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1, + double x2, double y2, + double x, double y, + double u) + { + if(u <= 0) + { + return calc_sq_distance(x, y, x1, y1); + } + else + if(u >= 1) + { + return calc_sq_distance(x, y, x2, y2); + } + return calc_sq_distance(x, y, x1 + u * (x2 - x1), y1 + u * (y2 - y1)); + } + + //---------------------------------------------calc_line_point_sq_distance + AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1, + double x2, double y2, + double x, double y) + { + return + calc_segment_point_sq_distance( + x1, y1, x2, y2, x, y, + calc_segment_point_u(x1, y1, x2, y2, x, y)); + } + + //-------------------------------------------------------calc_intersection + AGG_INLINE bool calc_intersection(double ax, double ay, double bx, double by, + double cx, double cy, double dx, double dy, + double* x, double* y) + { + double num = (ay-cy) * (dx-cx) - (ax-cx) * (dy-cy); + double den = (bx-ax) * (dy-cy) - (by-ay) * (dx-cx); + if(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(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 = std::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 double calc_polygon_area(const Storage& st) + { + unsigned i; + double sum = 0.0; + double x = st[0].x; + double y = st[0].y; + double xs = x; + double ys = y; + + for(i = 1; i < st.size(); i++) + { + const typename Storage::value_type& v = st[i]; + sum += x * v.y - y * v.x; + x = v.x; + y = v.y; + } + return (sum + x * ys - y * xs) * 0.5; + } + + //------------------------------------------------------------------------ + // Tables for fast sqrt + extern int16u g_sqrt_table[1024]; + extern int8 g_elder_bit_table[256]; + + + //---------------------------------------------------------------fast_sqrt + //Fast integer Sqrt - really fast: no cycles, divisions or multiplications + #if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 4035) //Disable warning "no return value" + #endif + AGG_INLINE unsigned fast_sqrt(unsigned val) + { + #if defined(_M_IX86) && defined(_MSC_VER) && !defined(AGG_NO_ASM) + //For Ix86 family processors this assembler code is used. + //The key command here is bsr - determination the number of the most + //significant bit of the value. For other processors + //(and maybe compilers) the pure C "#else" section is used. + __asm + { + mov ebx, val + mov edx, 11 + bsr ecx, ebx + sub ecx, 9 + jle less_than_9_bits + shr ecx, 1 + adc ecx, 0 + sub edx, ecx + shl ecx, 1 + shr ebx, cl + less_than_9_bits: + xor eax, eax + mov ax, g_sqrt_table[ebx*2] + mov ecx, edx + shr eax, cl + } + #else + + //This code is actually pure C and portable to most + //arcitectures including 64bit ones. + unsigned t = val; + int bit=0; + unsigned shift = 11; + + //The following piece of code is just an emulation of the + //Ix86 assembler command "bsr" (see above). However on old + //Intels (like Intel MMX 233MHz) this code is about twice + //faster (sic!) then just one "bsr". On PIII and PIV the + //bsr is optimized quite well. + bit = t >> 24; + if(bit) + { + bit = g_elder_bit_table[bit] + 24; + } + else + { + bit = (t >> 16) & 0xFF; + if(bit) + { + bit = g_elder_bit_table[bit] + 16; + } + else + { + bit = (t >> 8) & 0xFF; + if(bit) + { + bit = g_elder_bit_table[bit] + 8; + } + else + { + bit = g_elder_bit_table[t]; + } + } + } + + //This code calculates the sqrt. + bit -= 9; + if(bit > 0) + { + bit = (bit >> 1) + (bit & 1); + shift -= bit; + val >>= (bit << 1); + } + return g_sqrt_table[val] >> shift; + #endif + } + #if defined(_MSC_VER) + #pragma warning(pop) + #endif + + + + + //--------------------------------------------------------------------besj + // Function BESJ calculates Bessel function of first kind of order n + // Arguments: + // n - an integer (>=0), the order + // x - value at which the Bessel function is required + //-------------------- + // C++ Mathematical Library + // Convereted from equivalent FORTRAN library + // Converetd by Gareth Walker for use by course 392 computational project + // All functions tested and yield the same results as the corresponding + // FORTRAN versions. + // + // If you have any problems using these functions please report them to + // M.Muldoon@UMIST.ac.uk + // + // Documentation available on the web + // http://www.ma.umist.ac.uk/mrm/Teaching/392/libs/392.html + // Version 1.0 8/98 + // 29 October, 1999 + //-------------------- + // Adapted for use in AGG library by Andy Wilk (castor.vulgaris@gmail.com) + //------------------------------------------------------------------------ + inline double besj(double x, int n) + { + if(n < 0) + { + return 0; + } + double d = 1E-6; + double b = 0; + if(std::fabs(x) <= d) + { + if(n != 0) return 0; + return 1; + } + double b1 = 0; // b1 is the value from the previous iteration + // Set up a starting order for recurrence + int m1 = (int)std::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) + { + m8 = -1; + } + int imax = m2 - 2; + for (int i = 1; i <= imax; i++) + { + double c6 = 2 * (m2 - i) * c2 / x - c3; + c3 = c2; + c2 = c6; + if(m2 - i - 1 == n) + { + b = c6; + } + m8 = -1 * m8; + if (m8 > 0) + { + c4 = c4 + 2 * c6; + } + } + double c6 = 2 * c2 / x - c3; + if(n == 0) + { + b = c6; + } + c4 += c6; + b /= c4; + if(std::fabs(b - b1) < d) + { + return b; + } + b1 = b; + m2 += 3; + } + } + +} + + +#endif diff --git a/agg/include/agg_math_stroke.h b/agg/include/agg_math_stroke.h new file mode 100644 index 0000000..6a9d604 --- /dev/null +++ b/agg/include/agg_math_stroke.h @@ -0,0 +1,526 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Stroke math +// +//---------------------------------------------------------------------------- + +#ifndef AGG_STROKE_MATH_INCLUDED +#define AGG_STROKE_MATH_INCLUDED + +#include "agg_math.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + //-------------------------------------------------------------line_cap_e + enum line_cap_e + { + butt_cap, + square_cap, + round_cap + }; + + //------------------------------------------------------------line_join_e + enum line_join_e + { + miter_join = 0, + miter_join_revert = 1, + round_join = 2, + bevel_join = 3, + miter_join_round = 4 + }; + + + //-----------------------------------------------------------inner_join_e + enum inner_join_e + { + inner_bevel, + inner_miter, + inner_jag, + inner_round + }; + + //------------------------------------------------------------math_stroke + template class 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 math_stroke::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 void math_stroke::width(double w) + { + m_width = w * 0.5; + if(m_width < 0) + { + m_width_abs = -m_width; + m_width_sign = -1; + } + else + { + m_width_abs = m_width; + m_width_sign = 1; + } + m_width_eps = m_width / 1024.0; + } + + //----------------------------------------------------------------------- + template void math_stroke::miter_limit_theta(double t) + { + m_miter_limit = 1.0 / std::sin(t * 0.5) ; + } + + //----------------------------------------------------------------------- + template + void math_stroke::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++) + { + add_vertex(vc, x + std::cos(a1) * m_width, y + std::sin(a1) * m_width); + a1 += da; + } + } + else + { + if(a1 < a2) a2 -= 2 * pi; + n = int((a1 - a2) / da); + da = (a1 - a2) / (n + 1); + a1 -= da; + for(i = 0; i < n; i++) + { + add_vertex(vc, x + std::cos(a1) * m_width, y + std::sin(a1) * m_width); + a1 -= da; + } + } + add_vertex(vc, x + dx2, y + dy2); + } + + //----------------------------------------------------------------------- + template + void math_stroke::calc_miter(VC& vc, + const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + double dx1, double dy1, + double dx2, double dy2, + line_join_e lj, + double mlimit, + double dbevel) + { + double xi = v1.x; + double yi = v1.y; + double di = 1; + double lim = m_width_abs * mlimit; + bool miter_limit_exceeded = true; // Assume the worst + bool intersection_failed = true; // Assume the worst + + if(calc_intersection(v0.x + dx1, v0.y - dy1, + v1.x + dx1, v1.y - dy1, + v1.x + dx2, v1.y - dy2, + v2.x + dx2, v2.y - dy2, + &xi, &yi)) + { + // Calculation of the intersection succeeded + //--------------------- + di = calc_distance(v1.x, v1.y, xi, yi); + if(di <= lim) + { + // Inside the miter limit + //--------------------- + add_vertex(vc, xi, yi); + miter_limit_exceeded = false; + } + intersection_failed = false; + } + else + { + // Calculation of the intersection failed, most probably + // the three points lie one straight line. + // First check if v0 and v2 lie on the opposite sides of vector: + // (v1.x, v1.y) -> (v1.x+dx1, v1.y-dy1), that is, the perpendicular + // to the line determined by vertices v0 and v1. + // This condition determines whether the next line segments continues + // the previous one or goes back. + //---------------- + double x2 = v1.x + dx1; + double y2 = v1.y - dy1; + if((cross_product(v0.x, v0.y, v1.x, v1.y, x2, y2) < 0.0) == + (cross_product(v1.x, v1.y, v2.x, v2.y, x2, y2) < 0.0)) + { + // This case means that the next segment continues + // the previous one (straight line) + //----------------- + add_vertex(vc, v1.x + dx1, v1.y - dy1); + miter_limit_exceeded = false; + } + } + + if(miter_limit_exceeded) + { + // Miter limit exceeded + //------------------------ + switch(lj) + { + case miter_join_revert: + // For the compatibility with SVG, PDF, etc, + // we use a simple bevel join instead of + // "smart" bevel + //------------------- + add_vertex(vc, v1.x + dx1, v1.y - dy1); + add_vertex(vc, v1.x + dx2, v1.y - dy2); + break; + + case miter_join_round: + calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2); + break; + + default: + // If no miter-revert, calculate new dx1, dy1, dx2, dy2 + //---------------- + if(intersection_failed) + { + mlimit *= m_width_sign; + add_vertex(vc, v1.x + dx1 + dy1 * mlimit, + v1.y - dy1 + dx1 * mlimit); + add_vertex(vc, v1.x + dx2 - dy2 * mlimit, + v1.y - dy2 - dx2 * mlimit); + } + else + { + double x1 = v1.x + dx1; + double y1 = v1.y - dy1; + double x2 = v1.x + dx2; + double y2 = v1.y - dy2; + di = (lim - dbevel) / (di - dbevel); + add_vertex(vc, x1 + (xi - x1) * di, + y1 + (yi - y1) * di); + add_vertex(vc, x2 + (xi - x2) * di, + y2 + (yi - y2) * di); + } + break; + } + } + } + + //--------------------------------------------------------stroke_calc_cap + template + void math_stroke::calc_cap(VC& vc, + const vertex_dist& v0, + const vertex_dist& v1, + double len) + { + vc.remove_all(); + + double dx1 = (v1.y - v0.y) / len; + double dy1 = (v1.x - v0.x) / len; + double dx2 = 0; + double dy2 = 0; + + dx1 *= m_width; + dy1 *= m_width; + + if(m_line_cap != round_cap) + { + if(m_line_cap == square_cap) + { + dx2 = dy1 * m_width_sign; + dy2 = dx1 * m_width_sign; + } + add_vertex(vc, v0.x - dx1 - dx2, v0.y + dy1 - dy2); + add_vertex(vc, v0.x + dx1 - dx2, v0.y - dy1 - dy2); + } + else + { + double da = 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++) + { + 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); + 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); + } + } + + //----------------------------------------------------------------------- + template + void math_stroke::calc_join(VC& vc, + const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + double len1, + double len2) + { + double dx1 = m_width * (v1.y - v0.y) / len1; + double dy1 = m_width * (v1.x - v0.x) / len1; + double dx2 = m_width * (v2.y - v1.y) / len2; + double dy2 = m_width * (v2.x - v1.x) / len2; + + vc.remove_all(); + + double cp = cross_product(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y); + if(cp != 0 && (cp > 0) == (m_width > 0)) + { + // Inner join + //--------------- + double limit = ((len1 < len2) ? len1 : len2) / m_width_abs; + if(limit < m_inner_miter_limit) + { + limit = m_inner_miter_limit; + } + + switch(m_inner_join) + { + default: // inner_bevel + add_vertex(vc, v1.x + dx1, v1.y - dy1); + add_vertex(vc, v1.x + dx2, v1.y - dy2); + break; + + case inner_miter: + calc_miter(vc, + v0, v1, v2, dx1, dy1, dx2, dy2, + miter_join_revert, + limit, 0); + break; + + case inner_jag: + case inner_round: + cp = (dx1-dx2) * (dx1-dx2) + (dy1-dy2) * (dy1-dy2); + if(cp < len1 * len1 && cp < len2 * len2) + { + calc_miter(vc, + v0, v1, v2, dx1, dy1, dx2, dy2, + miter_join_revert, + limit, 0); + } + else + { + if(m_inner_join == inner_jag) + { + add_vertex(vc, v1.x + dx1, v1.y - dy1); + add_vertex(vc, v1.x, v1.y ); + add_vertex(vc, v1.x + dx2, v1.y - dy2); + } + else + { + add_vertex(vc, v1.x + dx1, v1.y - dy1); + add_vertex(vc, v1.x, v1.y ); + calc_arc(vc, v1.x, v1.y, dx2, -dy2, dx1, -dy1); + add_vertex(vc, v1.x, v1.y ); + add_vertex(vc, v1.x + dx2, v1.y - dy2); + } + } + break; + } + } + else + { + // Outer join + //--------------- + + // Calculate the distance between v1 and + // the central point of the bevel line segment + //--------------- + double dx = (dx1 + dx2) / 2; + double dy = (dy1 + dy2) / 2; + double dbevel = std::sqrt(dx * dx + dy * dy); + + if(m_line_join == round_join || m_line_join == bevel_join) + { + // This is an optimization that reduces the number of points + // in cases of almost collinear segments. If there's no + // visible difference between bevel and miter joins we'd rather + // use miter join because it adds only one point instead of two. + // + // Here we calculate the middle point between the bevel points + // and then, the distance between v1 and this middle point. + // At outer joins this distance always less than stroke width, + // because it's actually the height of an isosceles triangle of + // v1 and its two bevel points. If the difference between this + // width and this value is small (no visible bevel) we can + // add just one point. + // + // The constant in the expression makes the result approximately + // the same as in round joins and caps. You can safely comment + // out this entire "if". + //------------------- + if(m_approx_scale * (m_width_abs - dbevel) < m_width_eps) + { + if(calc_intersection(v0.x + dx1, v0.y - dy1, + v1.x + dx1, v1.y - dy1, + v1.x + dx2, v1.y - dy2, + v2.x + dx2, v2.y - dy2, + &dx, &dy)) + { + add_vertex(vc, dx, dy); + } + else + { + add_vertex(vc, v1.x + dx1, v1.y - dy1); + } + return; + } + } + + switch(m_line_join) + { + case miter_join: + case miter_join_revert: + case miter_join_round: + calc_miter(vc, + v0, v1, v2, dx1, dy1, dx2, dy2, + m_line_join, + m_miter_limit, + dbevel); + break; + + case round_join: + calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2); + break; + + default: // Bevel join + add_vertex(vc, v1.x + dx1, v1.y - dy1); + add_vertex(vc, v1.x + dx2, v1.y - dy2); + break; + } + } + } + + + + +} + +#endif diff --git a/agg/include/agg_path_length.h b/agg/include/agg_path_length.h new file mode 100644 index 0000000..740ba31 --- /dev/null +++ b/agg/include/agg_path_length.h @@ -0,0 +1,65 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +#ifndef AGG_PATH_LENGTH_INCLUDED +#define AGG_PATH_LENGTH_INCLUDED + +#include "agg_math.h" + +namespace agg +{ + template + double path_length(VertexSource& vs, unsigned path_id = 0) + { + double len = 0.0; + double start_x = 0.0; + double start_y = 0.0; + double x1 = 0.0; + double y1 = 0.0; + double x2 = 0.0; + double y2 = 0.0; + bool first = true; + + unsigned cmd; + vs.rewind(path_id); + while(!is_stop(cmd = vs.vertex(&x2, &y2))) + { + if(is_vertex(cmd)) + { + if(first || is_move_to(cmd)) + { + start_x = x2; + start_y = y2; + } + else + { + len += calc_distance(x1, y1, x2, y2); + } + x1 = x2; + y1 = y2; + first = false; + } + else + { + if(is_close(cmd) && !first) + { + len += calc_distance(x1, y1, start_x, start_y); + } + } + } + return len; + } +} + +#endif diff --git a/agg/include/agg_path_storage.h b/agg/include/agg_path_storage.h new file mode 100644 index 0000000..3a62f71 --- /dev/null +++ b/agg/include/agg_path_storage.h @@ -0,0 +1,1581 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_PATH_STORAGE_INCLUDED +#define AGG_PATH_STORAGE_INCLUDED + +#include +#include "agg_math.h" +#include "agg_array.h" +#include "agg_bezier_arc.h" + +namespace agg +{ + + + //----------------------------------------------------vertex_block_storage + template + class vertex_block_storage + { + public: + // Allocation parameters + enum block_scale_e + { + block_shift = BlockShift, + block_size = 1 << block_shift, + block_mask = block_size - 1, + block_pool = BlockPool + }; + + typedef T value_type; + typedef vertex_block_storage self_type; + + ~vertex_block_storage(); + vertex_block_storage(); + vertex_block_storage(const self_type& v); + const self_type& operator = (const self_type& ps); + + void remove_all(); + void free_all(); + + void add_vertex(double x, double y, unsigned cmd); + void modify_vertex(unsigned idx, double x, double y); + void modify_vertex(unsigned idx, double x, double y, unsigned cmd); + void modify_command(unsigned idx, unsigned cmd); + void swap_vertices(unsigned v1, unsigned v2); + + unsigned last_command() const; + unsigned last_vertex(double* x, double* y) const; + unsigned prev_vertex(double* x, double* y) const; + + double last_x() const; + double last_y() const; + + unsigned total_vertices() const; + unsigned vertex(unsigned idx, double* x, double* y) const; + unsigned command(unsigned idx) const; + + private: + void allocate_block(unsigned nb); + int8u* storage_ptrs(T** xy_ptr); + + private: + unsigned m_total_vertices; + unsigned m_total_blocks; + unsigned m_max_blocks; + T** m_coord_blocks; + int8u** m_cmd_blocks; + }; + + + //------------------------------------------------------------------------ + template + void vertex_block_storage::free_all() + { + if(m_total_blocks) + { + T** coord_blk = m_coord_blocks + m_total_blocks - 1; + while(m_total_blocks--) + { + pod_allocator::deallocate( + *coord_blk, + block_size * 2 + + block_size / (sizeof(T) / sizeof(unsigned char))); + --coord_blk; + } + pod_allocator::deallocate(m_coord_blocks, m_max_blocks * 2); + m_total_blocks = 0; + m_max_blocks = 0; + m_coord_blocks = 0; + m_cmd_blocks = 0; + m_total_vertices = 0; + } + } + + //------------------------------------------------------------------------ + template + vertex_block_storage::~vertex_block_storage() + { + free_all(); + } + + //------------------------------------------------------------------------ + template + vertex_block_storage::vertex_block_storage() : + m_total_vertices(0), + m_total_blocks(0), + m_max_blocks(0), + m_coord_blocks(0), + m_cmd_blocks(0) + { + } + + //------------------------------------------------------------------------ + template + vertex_block_storage::vertex_block_storage(const vertex_block_storage& v) : + m_total_vertices(0), + m_total_blocks(0), + m_max_blocks(0), + m_coord_blocks(0), + m_cmd_blocks(0) + { + *this = v; + } + + //------------------------------------------------------------------------ + template + const vertex_block_storage& + vertex_block_storage::operator = (const vertex_block_storage& v) + { + remove_all(); + unsigned i; + for(i = 0; i < v.total_vertices(); i++) + { + double x, y; + unsigned cmd = v.vertex(i, &x, &y); + add_vertex(x, y, cmd); + } + return *this; + } + + //------------------------------------------------------------------------ + template + inline void vertex_block_storage::remove_all() + { + m_total_vertices = 0; + } + + //------------------------------------------------------------------------ + template + inline void vertex_block_storage::add_vertex(double x, double y, + unsigned cmd) + { + T* coord_ptr = 0; + *storage_ptrs(&coord_ptr) = (int8u)cmd; + coord_ptr[0] = T(x); + coord_ptr[1] = T(y); + m_total_vertices++; + } + + //------------------------------------------------------------------------ + template + inline void vertex_block_storage::modify_vertex(unsigned idx, + double x, double y) + { + T* pv = m_coord_blocks[idx >> block_shift] + ((idx & block_mask) << 1); + pv[0] = T(x); + pv[1] = T(y); + } + + //------------------------------------------------------------------------ + template + inline void vertex_block_storage::modify_vertex(unsigned idx, + double x, double y, + unsigned cmd) + { + unsigned block = idx >> block_shift; + unsigned offset = idx & block_mask; + T* pv = m_coord_blocks[block] + (offset << 1); + pv[0] = T(x); + pv[1] = T(y); + m_cmd_blocks[block][offset] = (int8u)cmd; + } + + //------------------------------------------------------------------------ + template + inline void vertex_block_storage::modify_command(unsigned idx, + unsigned cmd) + { + m_cmd_blocks[idx >> block_shift][idx & block_mask] = (int8u)cmd; + } + + //------------------------------------------------------------------------ + template + inline void vertex_block_storage::swap_vertices(unsigned v1, unsigned v2) + { + unsigned b1 = v1 >> block_shift; + unsigned b2 = v2 >> block_shift; + unsigned o1 = v1 & block_mask; + unsigned o2 = v2 & block_mask; + T* pv1 = m_coord_blocks[b1] + (o1 << 1); + T* pv2 = m_coord_blocks[b2] + (o2 << 1); + T val; + val = pv1[0]; pv1[0] = pv2[0]; pv2[0] = val; + val = pv1[1]; pv1[1] = pv2[1]; pv2[1] = val; + int8u cmd = m_cmd_blocks[b1][o1]; + m_cmd_blocks[b1][o1] = m_cmd_blocks[b2][o2]; + m_cmd_blocks[b2][o2] = cmd; + } + + //------------------------------------------------------------------------ + template + inline unsigned vertex_block_storage::last_command() const + { + if(m_total_vertices) return command(m_total_vertices - 1); + return path_cmd_stop; + } + + //------------------------------------------------------------------------ + template + inline unsigned vertex_block_storage::last_vertex(double* x, double* y) const + { + if(m_total_vertices) return vertex(m_total_vertices - 1, x, y); + return path_cmd_stop; + } + + //------------------------------------------------------------------------ + template + inline unsigned vertex_block_storage::prev_vertex(double* x, double* y) const + { + if(m_total_vertices > 1) return vertex(m_total_vertices - 2, x, y); + return path_cmd_stop; + } + + //------------------------------------------------------------------------ + template + inline double vertex_block_storage::last_x() const + { + if(m_total_vertices) + { + unsigned idx = m_total_vertices - 1; + return m_coord_blocks[idx >> block_shift][(idx & block_mask) << 1]; + } + return 0.0; + } + + //------------------------------------------------------------------------ + template + inline double vertex_block_storage::last_y() const + { + if(m_total_vertices) + { + unsigned idx = m_total_vertices - 1; + return m_coord_blocks[idx >> block_shift][((idx & block_mask) << 1) + 1]; + } + return 0.0; + } + + //------------------------------------------------------------------------ + template + inline unsigned vertex_block_storage::total_vertices() const + { + return m_total_vertices; + } + + //------------------------------------------------------------------------ + template + inline unsigned vertex_block_storage::vertex(unsigned idx, + double* x, double* y) const + { + unsigned nb = idx >> block_shift; + const T* pv = m_coord_blocks[nb] + ((idx & block_mask) << 1); + *x = pv[0]; + *y = pv[1]; + return m_cmd_blocks[nb][idx & block_mask]; + } + + //------------------------------------------------------------------------ + template + inline unsigned vertex_block_storage::command(unsigned idx) const + { + return m_cmd_blocks[idx >> block_shift][idx & block_mask]; + } + + //------------------------------------------------------------------------ + template + void vertex_block_storage::allocate_block(unsigned nb) + { + if(nb >= m_max_blocks) + { + T** new_coords = + pod_allocator::allocate((m_max_blocks + block_pool) * 2); + + unsigned char** new_cmds = + (unsigned char**)(new_coords + m_max_blocks + block_pool); + + if(m_coord_blocks) + { + std::memcpy(new_coords, + m_coord_blocks, + m_max_blocks * sizeof(T*)); + + std::memcpy(new_cmds, + m_cmd_blocks, + m_max_blocks * sizeof(unsigned char*)); + + pod_allocator::deallocate(m_coord_blocks, m_max_blocks * 2); + } + m_coord_blocks = new_coords; + m_cmd_blocks = new_cmds; + m_max_blocks += block_pool; + } + m_coord_blocks[nb] = + pod_allocator::allocate(block_size * 2 + + block_size / (sizeof(T) / sizeof(unsigned char))); + + m_cmd_blocks[nb] = + (unsigned char*)(m_coord_blocks[nb] + block_size * 2); + + m_total_blocks++; + } + + //------------------------------------------------------------------------ + template + int8u* vertex_block_storage::storage_ptrs(T** xy_ptr) + { + unsigned nb = m_total_vertices >> block_shift; + if(nb >= m_total_blocks) + { + allocate_block(nb); + } + *xy_ptr = m_coord_blocks[nb] + ((m_total_vertices & block_mask) << 1); + return m_cmd_blocks[nb] + (m_total_vertices & block_mask); + } + + + + + //-----------------------------------------------------poly_plain_adaptor + template class poly_plain_adaptor + { + public: + typedef T value_type; + + poly_plain_adaptor() : + m_data(0), + m_ptr(0), + m_end(0), + m_closed(false), + m_stop(false) + {} + + poly_plain_adaptor(const T* data, unsigned num_points, bool closed) : + m_data(data), + m_ptr(data), + m_end(data + num_points * 2), + m_closed(closed), + m_stop(false) + {} + + void init(const T* data, unsigned num_points, bool closed) + { + m_data = data; + m_ptr = data; + m_end = data + num_points * 2; + m_closed = closed; + m_stop = false; + } + + void rewind(unsigned) + { + m_ptr = m_data; + m_stop = false; + } + + unsigned vertex(double* x, double* y) + { + if(m_ptr < m_end) + { + bool first = m_ptr == m_data; + *x = *m_ptr++; + *y = *m_ptr++; + return first ? path_cmd_move_to : path_cmd_line_to; + } + *x = *y = 0.0; + if(m_closed && !m_stop) + { + m_stop = true; + return path_cmd_end_poly | path_flags_close; + } + return path_cmd_stop; + } + + private: + const T* m_data; + const T* m_ptr; + const T* m_end; + bool m_closed; + bool m_stop; + }; + + + + + + //-------------------------------------------------poly_container_adaptor + template class poly_container_adaptor + { + public: + typedef typename Container::value_type vertex_type; + + poly_container_adaptor() : + m_container(0), + m_index(0), + m_closed(false), + m_stop(false) + {} + + poly_container_adaptor(const Container& data, bool closed) : + m_container(&data), + m_index(0), + m_closed(closed), + m_stop(false) + {} + + void init(const Container& data, bool closed) + { + m_container = &data; + m_index = 0; + m_closed = closed; + m_stop = false; + } + + void rewind(unsigned) + { + m_index = 0; + m_stop = false; + } + + unsigned vertex(double* x, double* y) + { + if(m_index < m_container->size()) + { + bool first = m_index == 0; + const vertex_type& v = (*m_container)[m_index++]; + *x = v.x; + *y = v.y; + return first ? path_cmd_move_to : path_cmd_line_to; + } + *x = *y = 0.0; + if(m_closed && !m_stop) + { + m_stop = true; + return path_cmd_end_poly | path_flags_close; + } + return path_cmd_stop; + } + + private: + const Container* m_container; + unsigned m_index; + bool m_closed; + bool m_stop; + }; + + + + //-----------------------------------------poly_container_reverse_adaptor + template class poly_container_reverse_adaptor + { + public: + typedef typename Container::value_type vertex_type; + + poly_container_reverse_adaptor() : + m_container(0), + m_index(-1), + m_closed(false), + m_stop(false) + {} + + poly_container_reverse_adaptor(Container& data, bool closed) : + m_container(&data), + m_index(-1), + m_closed(closed), + m_stop(false) + {} + + void init(Container& data, bool closed) + { + m_container = &data; + m_index = m_container->size() - 1; + m_closed = closed; + m_stop = false; + } + + void rewind(unsigned) + { + m_index = m_container->size() - 1; + m_stop = false; + } + + unsigned vertex(double* x, double* y) + { + if(m_index >= 0) + { + bool first = m_index == int(m_container->size() - 1); + const vertex_type& v = (*m_container)[m_index--]; + *x = v.x; + *y = v.y; + return first ? path_cmd_move_to : path_cmd_line_to; + } + *x = *y = 0.0; + if(m_closed && !m_stop) + { + m_stop = true; + return path_cmd_end_poly | path_flags_close; + } + return path_cmd_stop; + } + + private: + Container* m_container; + int m_index; + bool m_closed; + bool m_stop; + }; + + + + + + //--------------------------------------------------------line_adaptor + class line_adaptor + { + public: + typedef double value_type; + + line_adaptor() : m_line(m_coord, 2, false) {} + line_adaptor(double x1, double y1, double x2, double y2) : + m_line(m_coord, 2, false) + { + m_coord[0] = x1; + m_coord[1] = y1; + m_coord[2] = x2; + m_coord[3] = y2; + } + + void init(double x1, double y1, double x2, double y2) + { + m_coord[0] = x1; + m_coord[1] = y1; + m_coord[2] = x2; + m_coord[3] = y2; + m_line.rewind(0); + } + + void rewind(unsigned) + { + m_line.rewind(0); + } + + unsigned vertex(double* x, double* y) + { + return m_line.vertex(x, y); + } + + private: + double m_coord[4]; + poly_plain_adaptor m_line; + }; + + + + + + + + + + + + + + //---------------------------------------------------------------path_base + // A container to store vertices with their flags. + // A path consists of a number of contours separated with "move_to" + // commands. The path storage can keep and maintain more than one + // path. + // To navigate to the beginning of a particular path, use rewind(path_id); + // Where path_id is what start_new_path() returns. So, when you call + // start_new_path() you need to store its return value somewhere else + // to navigate to the path afterwards. + // + // See also: vertex_source concept + //------------------------------------------------------------------------ + template class path_base + { + public: + typedef VertexContainer container_type; + typedef path_base self_type; + + //-------------------------------------------------------------------- + path_base() : m_vertices(), m_iterator(0) {} + void remove_all() { m_vertices.remove_all(); m_iterator = 0; } + void free_all() { m_vertices.free_all(); m_iterator = 0; } + + // Make path functions + //-------------------------------------------------------------------- + unsigned start_new_path(); + + void move_to(double x, double y); + void move_rel(double dx, double dy); + + void line_to(double x, double y); + void line_rel(double dx, double dy); + + void hline_to(double x); + void hline_rel(double dx); + + void vline_to(double y); + void vline_rel(double dy); + + void arc_to(double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double x, double y); + + void arc_rel(double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double dx, double dy); + + void curve3(double x_ctrl, double y_ctrl, + double x_to, double y_to); + + void curve3_rel(double dx_ctrl, double dy_ctrl, + double dx_to, double dy_to); + + void curve3(double x_to, double y_to); + + void curve3_rel(double dx_to, double dy_to); + + void curve4(double x_ctrl1, double y_ctrl1, + double x_ctrl2, double y_ctrl2, + double x_to, double y_to); + + void curve4_rel(double dx_ctrl1, double dy_ctrl1, + double dx_ctrl2, double dy_ctrl2, + double dx_to, double dy_to); + + void curve4(double x_ctrl2, double y_ctrl2, + double x_to, double y_to); + + void curve4_rel(double x_ctrl2, double y_ctrl2, + double x_to, double y_to); + + + void end_poly(unsigned flags = path_flags_close); + void close_polygon(unsigned flags = path_flags_none); + + // Accessors + //-------------------------------------------------------------------- + const container_type& vertices() const { return m_vertices; } + container_type& vertices() { return m_vertices; } + + unsigned total_vertices() const; + + void rel_to_abs(double* x, double* y) const; + + unsigned last_vertex(double* x, double* y) const; + unsigned prev_vertex(double* x, double* y) const; + + double last_x() const; + double last_y() const; + + unsigned vertex(unsigned idx, double* x, double* y) const; + unsigned command(unsigned idx) const; + + void modify_vertex(unsigned idx, double x, double y); + void modify_vertex(unsigned idx, double x, double y, unsigned cmd); + void modify_command(unsigned idx, unsigned cmd); + + // VertexSource interface + //-------------------------------------------------------------------- + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + // Arrange the orientation of a polygon, all polygons in a path, + // or in all paths. After calling arrange_orientations() or + // arrange_orientations_all_paths(), all the polygons will have + // the same orientation, i.e. path_flags_cw or path_flags_ccw + //-------------------------------------------------------------------- + unsigned arrange_polygon_orientation(unsigned start, path_flags_e orientation); + unsigned arrange_orientations(unsigned path_id, path_flags_e orientation); + void arrange_orientations_all_paths(path_flags_e orientation); + void invert_polygon(unsigned start); + + // Flip all vertices horizontally or vertically, + // between x1 and x2, or between y1 and y2 respectively + //-------------------------------------------------------------------- + void flip_x(double x1, double x2); + void flip_y(double y1, double y2); + + // Concatenate path. The path is added as is. + //-------------------------------------------------------------------- + template + void concat_path(VertexSource& vs, unsigned path_id = 0) + { + double x, y; + unsigned cmd; + vs.rewind(path_id); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + m_vertices.add_vertex(x, y, cmd); + } + } + + //-------------------------------------------------------------------- + // Join path. The path is joined with the existing one, that is, + // it behaves as if the pen of a plotter was always down (drawing) + template + void join_path(VertexSource& vs, unsigned path_id = 0) + { + double x, y; + unsigned cmd; + vs.rewind(path_id); + cmd = vs.vertex(&x, &y); + if(!is_stop(cmd)) + { + if(is_vertex(cmd)) + { + double x0, y0; + unsigned cmd0 = last_vertex(&x0, &y0); + if(is_vertex(cmd0)) + { + if(calc_distance(x, y, x0, y0) > vertex_dist_epsilon) + { + if(is_move_to(cmd)) cmd = path_cmd_line_to; + m_vertices.add_vertex(x, y, cmd); + } + } + else + { + if(is_stop(cmd0)) + { + cmd = path_cmd_move_to; + } + else + { + if(is_move_to(cmd)) cmd = path_cmd_line_to; + } + m_vertices.add_vertex(x, y, cmd); + } + } + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + m_vertices.add_vertex(x, y, is_move_to(cmd) ? + unsigned(path_cmd_line_to) : + cmd); + } + } + } + + // Concatenate polygon/polyline. + //-------------------------------------------------------------------- + template void concat_poly(const T* data, + unsigned num_points, + bool closed) + { + poly_plain_adaptor poly(data, num_points, closed); + concat_path(poly); + } + + // Join polygon/polyline continuously. + //-------------------------------------------------------------------- + template void join_poly(const T* data, + unsigned num_points, + bool closed) + { + poly_plain_adaptor poly(data, num_points, closed); + join_path(poly); + } + + //-------------------------------------------------------------------- + void translate(double dx, double dy, unsigned path_id=0); + void translate_all_paths(double dx, double dy); + + //-------------------------------------------------------------------- + template + void transform(const Trans& trans, unsigned path_id=0) + { + unsigned num_ver = m_vertices.total_vertices(); + for(; path_id < num_ver; path_id++) + { + double x, y; + unsigned cmd = m_vertices.vertex(path_id, &x, &y); + if(is_stop(cmd)) break; + if(is_vertex(cmd)) + { + trans.transform(&x, &y); + m_vertices.modify_vertex(path_id, x, y); + } + } + } + + //-------------------------------------------------------------------- + template + void transform_all_paths(const Trans& trans) + { + unsigned idx; + unsigned num_ver = m_vertices.total_vertices(); + for(idx = 0; idx < num_ver; idx++) + { + double x, y; + if(is_vertex(m_vertices.vertex(idx, &x, &y))) + { + trans.transform(&x, &y); + m_vertices.modify_vertex(idx, x, y); + } + } + } + + + //-------------------------------------------------------------------- + // If the end points of a path are very, very close then make them + // exactly equal so that the stroke converter is not confused. + //-------------------------------------------------------------------- + unsigned align_path(unsigned idx = 0) + { + if (idx >= total_vertices() || !is_move_to(command(idx))) + { + return total_vertices(); + } + + double start_x, start_y; + for (; idx < total_vertices() && is_move_to(command(idx)); ++idx) + { + vertex(idx, &start_x, &start_y); + } + while (idx < total_vertices() && is_drawing(command(idx))) + ++idx; + + double x, y; + if (is_drawing(vertex(idx - 1, &x, &y)) && + is_equal_eps(x, start_x, 1e-8) && + is_equal_eps(y, start_y, 1e-8)) + { + modify_vertex(idx - 1, start_x, start_y); + } + + while (idx < total_vertices() && !is_move_to(command(idx))) + ++idx; + return idx; + } + + void align_all_paths() + { + for (unsigned i = 0; i < total_vertices(); i = align_path(i)); + } + + + private: + unsigned perceive_polygon_orientation(unsigned start, unsigned end); + void invert_polygon(unsigned start, unsigned end); + + VertexContainer m_vertices; + unsigned m_iterator; + }; + + //------------------------------------------------------------------------ + template + unsigned path_base::start_new_path() + { + if(!is_stop(m_vertices.last_command())) + { + m_vertices.add_vertex(0.0, 0.0, path_cmd_stop); + } + return m_vertices.total_vertices(); + } + + + //------------------------------------------------------------------------ + template + inline void path_base::rel_to_abs(double* x, double* y) const + { + if(m_vertices.total_vertices()) + { + double x2; + double y2; + if(is_vertex(m_vertices.last_vertex(&x2, &y2))) + { + *x += x2; + *y += y2; + } + } + } + + //------------------------------------------------------------------------ + template + inline void path_base::move_to(double x, double y) + { + m_vertices.add_vertex(x, y, path_cmd_move_to); + } + + //------------------------------------------------------------------------ + template + inline void path_base::move_rel(double dx, double dy) + { + rel_to_abs(&dx, &dy); + m_vertices.add_vertex(dx, dy, path_cmd_move_to); + } + + //------------------------------------------------------------------------ + template + inline void path_base::line_to(double x, double y) + { + m_vertices.add_vertex(x, y, path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template + inline void path_base::line_rel(double dx, double dy) + { + rel_to_abs(&dx, &dy); + m_vertices.add_vertex(dx, dy, path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template + inline void path_base::hline_to(double x) + { + m_vertices.add_vertex(x, last_y(), path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template + inline void path_base::hline_rel(double dx) + { + double dy = 0; + rel_to_abs(&dx, &dy); + m_vertices.add_vertex(dx, dy, path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template + inline void path_base::vline_to(double y) + { + m_vertices.add_vertex(last_x(), y, path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template + inline void path_base::vline_rel(double dy) + { + double dx = 0; + rel_to_abs(&dx, &dy); + m_vertices.add_vertex(dx, dy, path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template + void path_base::arc_to(double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double x, double y) + { + if(m_vertices.total_vertices() && is_vertex(m_vertices.last_command())) + { + const double epsilon = 1e-30; + double x0 = 0.0; + double y0 = 0.0; + m_vertices.last_vertex(&x0, &y0); + + rx = std::fabs(rx); + ry = std::fabs(ry); + + // Ensure radii are valid + //------------------------- + if(rx < epsilon || ry < epsilon) + { + line_to(x, y); + return; + } + + if(calc_distance(x0, y0, x, y) < epsilon) + { + // If the endpoints (x, y) and (x0, y0) are identical, then this + // is equivalent to omitting the elliptical arc segment entirely. + return; + } + bezier_arc_svg a(x0, y0, rx, ry, angle, large_arc_flag, sweep_flag, x, y); + if(a.radii_ok()) + { + join_path(a); + } + else + { + line_to(x, y); + } + } + else + { + move_to(x, y); + } + } + + //------------------------------------------------------------------------ + template + void path_base::arc_rel(double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double dx, double dy) + { + rel_to_abs(&dx, &dy); + arc_to(rx, ry, angle, large_arc_flag, sweep_flag, dx, dy); + } + + //------------------------------------------------------------------------ + template + void path_base::curve3(double x_ctrl, double y_ctrl, + double x_to, double y_to) + { + m_vertices.add_vertex(x_ctrl, y_ctrl, path_cmd_curve3); + m_vertices.add_vertex(x_to, y_to, path_cmd_curve3); + } + + //------------------------------------------------------------------------ + template + void path_base::curve3_rel(double dx_ctrl, double dy_ctrl, + double dx_to, double dy_to) + { + rel_to_abs(&dx_ctrl, &dy_ctrl); + rel_to_abs(&dx_to, &dy_to); + m_vertices.add_vertex(dx_ctrl, dy_ctrl, path_cmd_curve3); + m_vertices.add_vertex(dx_to, dy_to, path_cmd_curve3); + } + + //------------------------------------------------------------------------ + template + void path_base::curve3(double x_to, double y_to) + { + double x0; + double y0; + if(is_vertex(m_vertices.last_vertex(&x0, &y0))) + { + double x_ctrl; + double y_ctrl; + unsigned cmd = m_vertices.prev_vertex(&x_ctrl, &y_ctrl); + if(is_curve(cmd)) + { + x_ctrl = x0 + x0 - x_ctrl; + y_ctrl = y0 + y0 - y_ctrl; + } + else + { + x_ctrl = x0; + y_ctrl = y0; + } + curve3(x_ctrl, y_ctrl, x_to, y_to); + } + } + + //------------------------------------------------------------------------ + template + void path_base::curve3_rel(double dx_to, double dy_to) + { + rel_to_abs(&dx_to, &dy_to); + curve3(dx_to, dy_to); + } + + //------------------------------------------------------------------------ + template + void path_base::curve4(double x_ctrl1, double y_ctrl1, + double x_ctrl2, double y_ctrl2, + double x_to, double y_to) + { + m_vertices.add_vertex(x_ctrl1, y_ctrl1, path_cmd_curve4); + m_vertices.add_vertex(x_ctrl2, y_ctrl2, path_cmd_curve4); + m_vertices.add_vertex(x_to, y_to, path_cmd_curve4); + } + + //------------------------------------------------------------------------ + template + void path_base::curve4_rel(double dx_ctrl1, double dy_ctrl1, + double dx_ctrl2, double dy_ctrl2, + double dx_to, double dy_to) + { + rel_to_abs(&dx_ctrl1, &dy_ctrl1); + rel_to_abs(&dx_ctrl2, &dy_ctrl2); + rel_to_abs(&dx_to, &dy_to); + m_vertices.add_vertex(dx_ctrl1, dy_ctrl1, path_cmd_curve4); + m_vertices.add_vertex(dx_ctrl2, dy_ctrl2, path_cmd_curve4); + m_vertices.add_vertex(dx_to, dy_to, path_cmd_curve4); + } + + //------------------------------------------------------------------------ + template + void path_base::curve4(double x_ctrl2, double y_ctrl2, + double x_to, double y_to) + { + double x0; + double y0; + if(is_vertex(last_vertex(&x0, &y0))) + { + double x_ctrl1; + double y_ctrl1; + unsigned cmd = prev_vertex(&x_ctrl1, &y_ctrl1); + if(is_curve(cmd)) + { + x_ctrl1 = x0 + x0 - x_ctrl1; + y_ctrl1 = y0 + y0 - y_ctrl1; + } + else + { + x_ctrl1 = x0; + y_ctrl1 = y0; + } + curve4(x_ctrl1, y_ctrl1, x_ctrl2, y_ctrl2, x_to, y_to); + } + } + + //------------------------------------------------------------------------ + template + void path_base::curve4_rel(double dx_ctrl2, double dy_ctrl2, + double dx_to, double dy_to) + { + rel_to_abs(&dx_ctrl2, &dy_ctrl2); + rel_to_abs(&dx_to, &dy_to); + curve4(dx_ctrl2, dy_ctrl2, dx_to, dy_to); + } + + //------------------------------------------------------------------------ + template + inline void path_base::end_poly(unsigned flags) + { + if(is_vertex(m_vertices.last_command())) + { + m_vertices.add_vertex(0.0, 0.0, path_cmd_end_poly | flags); + } + } + + //------------------------------------------------------------------------ + template + inline void path_base::close_polygon(unsigned flags) + { + end_poly(path_flags_close | flags); + } + + //------------------------------------------------------------------------ + template + inline unsigned path_base::total_vertices() const + { + return m_vertices.total_vertices(); + } + + //------------------------------------------------------------------------ + template + inline unsigned path_base::last_vertex(double* x, double* y) const + { + return m_vertices.last_vertex(x, y); + } + + //------------------------------------------------------------------------ + template + inline unsigned path_base::prev_vertex(double* x, double* y) const + { + return m_vertices.prev_vertex(x, y); + } + + //------------------------------------------------------------------------ + template + inline double path_base::last_x() const + { + return m_vertices.last_x(); + } + + //------------------------------------------------------------------------ + template + inline double path_base::last_y() const + { + return m_vertices.last_y(); + } + + //------------------------------------------------------------------------ + template + inline unsigned path_base::vertex(unsigned idx, double* x, double* y) const + { + return m_vertices.vertex(idx, x, y); + } + + //------------------------------------------------------------------------ + template + inline unsigned path_base::command(unsigned idx) const + { + return m_vertices.command(idx); + } + + //------------------------------------------------------------------------ + template + void path_base::modify_vertex(unsigned idx, double x, double y) + { + m_vertices.modify_vertex(idx, x, y); + } + + //------------------------------------------------------------------------ + template + void path_base::modify_vertex(unsigned idx, double x, double y, unsigned cmd) + { + m_vertices.modify_vertex(idx, x, y, cmd); + } + + //------------------------------------------------------------------------ + template + void path_base::modify_command(unsigned idx, unsigned cmd) + { + m_vertices.modify_command(idx, cmd); + } + + //------------------------------------------------------------------------ + template + inline void path_base::rewind(unsigned path_id) + { + m_iterator = path_id; + } + + //------------------------------------------------------------------------ + template + inline unsigned path_base::vertex(double* x, double* y) + { + if(m_iterator >= m_vertices.total_vertices()) return path_cmd_stop; + return m_vertices.vertex(m_iterator++, x, y); + } + + //------------------------------------------------------------------------ + template + unsigned path_base::perceive_polygon_orientation(unsigned start, + unsigned end) + { + // Calculate signed area (double area to be exact) + //--------------------- + unsigned np = end - start; + double area = 0.0; + unsigned i; + for(i = 0; i < np; i++) + { + double x1, y1, x2, y2; + m_vertices.vertex(start + i, &x1, &y1); + m_vertices.vertex(start + (i + 1) % np, &x2, &y2); + area += x1 * y2 - y1 * x2; + } + return (area < 0.0) ? path_flags_cw : path_flags_ccw; + } + + //------------------------------------------------------------------------ + template + void path_base::invert_polygon(unsigned start, unsigned end) + { + unsigned i; + unsigned tmp_cmd = m_vertices.command(start); + + --end; // Make "end" inclusive + + // Shift all commands to one position + for(i = start; i < end; i++) + { + m_vertices.modify_command(i, m_vertices.command(i + 1)); + } + + // Assign starting command to the ending command + m_vertices.modify_command(end, tmp_cmd); + + // Reverse the polygon + while(end > start) + { + m_vertices.swap_vertices(start++, end--); + } + } + + //------------------------------------------------------------------------ + template + void path_base::invert_polygon(unsigned start) + { + // Skip all non-vertices at the beginning + while(start < m_vertices.total_vertices() && + !is_vertex(m_vertices.command(start))) ++start; + + // Skip all insignificant move_to + while(start+1 < m_vertices.total_vertices() && + is_move_to(m_vertices.command(start)) && + is_move_to(m_vertices.command(start+1))) ++start; + + // Find the last vertex + unsigned end = start + 1; + while(end < m_vertices.total_vertices() && + !is_next_poly(m_vertices.command(end))) ++end; + + invert_polygon(start, end); + } + + //------------------------------------------------------------------------ + template + unsigned path_base::arrange_polygon_orientation(unsigned start, + path_flags_e orientation) + { + if(orientation == path_flags_none) return start; + + // Skip all non-vertices at the beginning + while(start < m_vertices.total_vertices() && + !is_vertex(m_vertices.command(start))) ++start; + + // Skip all insignificant move_to + while(start+1 < m_vertices.total_vertices() && + is_move_to(m_vertices.command(start)) && + is_move_to(m_vertices.command(start+1))) ++start; + + // Find the last vertex + unsigned end = start + 1; + while(end < m_vertices.total_vertices() && + !is_next_poly(m_vertices.command(end))) ++end; + + if(end - start > 2) + { + if(perceive_polygon_orientation(start, end) != unsigned(orientation)) + { + // Invert polygon, set orientation flag, and skip all end_poly + invert_polygon(start, end); + unsigned cmd; + while(end < m_vertices.total_vertices() && + is_end_poly(cmd = m_vertices.command(end))) + { + m_vertices.modify_command(end++, set_orientation(cmd, orientation)); + } + } + } + return end; + } + + //------------------------------------------------------------------------ + template + unsigned path_base::arrange_orientations(unsigned start, + path_flags_e orientation) + { + if(orientation != path_flags_none) + { + while(start < m_vertices.total_vertices()) + { + start = arrange_polygon_orientation(start, orientation); + if(is_stop(m_vertices.command(start))) + { + ++start; + break; + } + } + } + return start; + } + + //------------------------------------------------------------------------ + template + void path_base::arrange_orientations_all_paths(path_flags_e orientation) + { + if(orientation != path_flags_none) + { + unsigned start = 0; + while(start < m_vertices.total_vertices()) + { + start = arrange_orientations(start, orientation); + } + } + } + + //------------------------------------------------------------------------ + template + void path_base::flip_x(double x1, double x2) + { + unsigned i; + double x, y; + for(i = 0; i < m_vertices.total_vertices(); i++) + { + unsigned cmd = m_vertices.vertex(i, &x, &y); + if(is_vertex(cmd)) + { + m_vertices.modify_vertex(i, x2 - x + x1, y); + } + } + } + + //------------------------------------------------------------------------ + template + void path_base::flip_y(double y1, double y2) + { + unsigned i; + double x, y; + for(i = 0; i < m_vertices.total_vertices(); i++) + { + unsigned cmd = m_vertices.vertex(i, &x, &y); + if(is_vertex(cmd)) + { + m_vertices.modify_vertex(i, x, y2 - y + y1); + } + } + } + + //------------------------------------------------------------------------ + template + void path_base::translate(double dx, double dy, unsigned path_id) + { + unsigned num_ver = m_vertices.total_vertices(); + for(; path_id < num_ver; path_id++) + { + double x, y; + unsigned cmd = m_vertices.vertex(path_id, &x, &y); + if(is_stop(cmd)) break; + if(is_vertex(cmd)) + { + x += dx; + y += dy; + m_vertices.modify_vertex(path_id, x, y); + } + } + } + + //------------------------------------------------------------------------ + template + void path_base::translate_all_paths(double dx, double dy) + { + unsigned idx; + unsigned num_ver = m_vertices.total_vertices(); + for(idx = 0; idx < num_ver; idx++) + { + double x, y; + if(is_vertex(m_vertices.vertex(idx, &x, &y))) + { + x += dx; + y += dy; + m_vertices.modify_vertex(idx, x, y); + } + } + } + + //-----------------------------------------------------vertex_stl_storage + template class vertex_stl_storage + { + public: + typedef typename Container::value_type vertex_type; + typedef typename vertex_type::value_type value_type; + + void remove_all() { m_vertices.clear(); } + void free_all() { m_vertices.clear(); } + + void add_vertex(double x, double y, unsigned cmd) + { + m_vertices.push_back(vertex_type(value_type(x), + value_type(y), + int8u(cmd))); + } + + void modify_vertex(unsigned idx, double x, double y) + { + vertex_type& v = m_vertices[idx]; + v.x = value_type(x); + v.y = value_type(y); + } + + void modify_vertex(unsigned idx, double x, double y, unsigned cmd) + { + vertex_type& v = m_vertices[idx]; + v.x = value_type(x); + v.y = value_type(y); + v.cmd = int8u(cmd); + } + + void modify_command(unsigned idx, unsigned cmd) + { + m_vertices[idx].cmd = int8u(cmd); + } + + void swap_vertices(unsigned v1, unsigned v2) + { + vertex_type t = m_vertices[v1]; + m_vertices[v1] = m_vertices[v2]; + m_vertices[v2] = t; + } + + unsigned last_command() const + { + return m_vertices.size() ? + m_vertices[m_vertices.size() - 1].cmd : + path_cmd_stop; + } + + unsigned last_vertex(double* x, double* y) const + { + if(m_vertices.size() == 0) + { + *x = *y = 0.0; + return path_cmd_stop; + } + return vertex(m_vertices.size() - 1, x, y); + } + + unsigned prev_vertex(double* x, double* y) const + { + if(m_vertices.size() < 2) + { + *x = *y = 0.0; + return path_cmd_stop; + } + return vertex(m_vertices.size() - 2, x, y); + } + + double last_x() const + { + return m_vertices.size() ? m_vertices[m_vertices.size() - 1].x : 0.0; + } + + double last_y() const + { + return m_vertices.size() ? m_vertices[m_vertices.size() - 1].y : 0.0; + } + + unsigned total_vertices() const + { + return m_vertices.size(); + } + + unsigned vertex(unsigned idx, double* x, double* y) const + { + const vertex_type& v = m_vertices[idx]; + *x = v.x; + *y = v.y; + return v.cmd; + } + + unsigned command(unsigned idx) const + { + return m_vertices[idx].cmd; + } + + private: + Container m_vertices; + }; + + //-----------------------------------------------------------path_storage + typedef path_base > path_storage; + + // Example of declarations path_storage with pod_bvector as a container + //----------------------------------------------------------------------- + //typedef path_base > > path_storage; + +} + + + +// Example of declarations path_storage with std::vector as a container +//--------------------------------------------------------------------------- +//#include +//namespace agg +//{ +// typedef path_base > > stl_path_storage; +//} + + + + +#endif diff --git a/agg2/include/agg_path_storage_integer.h b/agg/include/agg_path_storage_integer.h similarity index 82% rename from agg2/include/agg_path_storage_integer.h rename to agg/include/agg_path_storage_integer.h index f140bbc..1026bde 100644 --- a/agg2/include/agg_path_storage_integer.h +++ b/agg/include/agg_path_storage_integer.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -16,12 +16,11 @@ #ifndef AGG_PATH_STORAGE_INTEGER_INCLUDED #define AGG_PATH_STORAGE_INTEGER_INCLUDED -#include +#include #include "agg_array.h" namespace agg { - //---------------------------------------------------------vertex_integer template struct vertex_integer { @@ -33,10 +32,10 @@ namespace agg cmd_curve4 = 3 }; - enum + enum coord_scale_e { coord_shift = CoordShift, - coord_mult = 1 << coord_shift + coord_scale = 1 << coord_shift }; T x,y; @@ -45,10 +44,12 @@ namespace agg x(((x_ << 1) & ~1) | (flag & 1)), y(((y_ << 1) & ~1) | (flag >> 1)) {} - unsigned vertex(double* x_, double* y_, double dx=0, double dy=0) const + unsigned vertex(double* x_, double* y_, + double dx=0, double dy=0, + double scale=1.0) const { - *x_ = dx + (double(x >> 1) / coord_mult); - *y_ = dy + (double(y >> 1) / coord_mult); + *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; @@ -65,6 +66,7 @@ namespace agg template class path_storage_integer { public: + typedef T value_type; typedef vertex_integer vertex_integer_type; //-------------------------------------------------------------------- @@ -108,12 +110,9 @@ namespace agg //-------------------------------------------------------------------- unsigned size() const { return m_storage.size(); } - unsigned vertex(unsigned idx, T* x, T* y) const + unsigned vertex(unsigned idx, double* x, double* y) const { - const vertex_integer_type& v = m_storage[idx]; - *x = v.x >> 1; - *y = v.y >> 1; - return ((v.y & 1) << 1) | (v.x & 1); + return m_storage[idx].vertex(x, y); } //-------------------------------------------------------------------- @@ -123,12 +122,11 @@ namespace agg unsigned i; for(i = 0; i < m_storage.size(); i++) { - memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type)); + std::memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type)); ptr += sizeof(vertex_integer_type); } } - //-------------------------------------------------------------------- void rewind(unsigned) { @@ -171,7 +169,7 @@ namespace agg rect_d bounds(1e100, 1e100, -1e100, -1e100); if(m_storage.size() == 0) { - bounds.x1 = bounds.x1 = bounds.x2 = bounds.y2 = 0.0; + bounds.x1 = bounds.y1 = bounds.x2 = bounds.y2 = 0.0; } else { @@ -189,11 +187,10 @@ namespace agg return bounds; } - private: - pod_deque m_storage; - unsigned m_vertex_idx; - bool m_closed; + pod_bvector m_storage; + unsigned m_vertex_idx; + bool m_closed; }; @@ -212,7 +209,8 @@ namespace agg m_ptr(0), m_dx(0.0), m_dy(0.0), - m_closed(true) + m_scale(1.0), + m_vertices(0) {} //-------------------------------------------------------------------- @@ -223,26 +221,28 @@ namespace agg m_ptr(data), m_dx(dx), m_dy(dy), - m_closed(true) + m_vertices(0) {} //-------------------------------------------------------------------- - void init(const int8u* data, unsigned size, double dx, double dy) + void init(const int8u* data, unsigned size, + double dx, double dy, double scale=1.0) { - m_data = data; - m_end = data + size; - m_ptr = data; - m_dx = dx; - m_dy = dy; - m_closed = true; + m_data = data; + m_end = data + size; + m_ptr = data; + m_dx = dx; + m_dy = dy; + m_scale = scale; + m_vertices = 0; } //-------------------------------------------------------------------- void rewind(unsigned) { - m_ptr = m_data; - m_closed = true; + m_ptr = m_data; + m_vertices = 0; } //-------------------------------------------------------------------- @@ -254,6 +254,7 @@ namespace agg *y = 0; return path_cmd_stop; } + if(m_ptr == m_end) { *x = 0; @@ -263,16 +264,16 @@ namespace agg } vertex_integer_type v; - memcpy(&v, m_ptr, sizeof(vertex_integer_type)); - unsigned cmd = v.vertex(x, y, m_dx, m_dy); - if(is_move_to(cmd) && !m_closed) + std::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_closed = true; + m_vertices = 0; return path_cmd_end_poly | path_flags_close; } - m_closed = false; + ++m_vertices; m_ptr += sizeof(vertex_integer_type); return cmd; } @@ -283,7 +284,8 @@ namespace agg const int8u* m_ptr; double m_dx; double m_dy; - bool m_closed; + double m_scale; + unsigned m_vertices; }; } diff --git a/agg2/include/agg_pattern_filters_rgba8.h b/agg/include/agg_pattern_filters_rgba.h similarity index 53% rename from agg2/include/agg_pattern_filters_rgba8.h rename to agg/include/agg_pattern_filters_rgba.h index 51f49f1..c1d174c 100644 --- a/agg2/include/agg_pattern_filters_rgba8.h +++ b/agg/include/agg_pattern_filters_rgba.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -17,7 +17,7 @@ #include "agg_basics.h" #include "agg_line_aa_basics.h" -#include "agg_color_rgba8.h" +#include "agg_color_rgba.h" namespace agg @@ -29,43 +29,47 @@ namespace agg typedef ColorT color_type; static unsigned dilation() { return 0; } - static void pixel_low_res(color_type const* const* buf, - color_type* p, int x, int y) + 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 pixel_high_res(color_type const* const* buf, - color_type* p, int x, int y) + static void AGG_INLINE pixel_high_res(color_type const* const* buf, + color_type* p, int x, int y) { *p = buf[y >> line_subpixel_shift] [x >> line_subpixel_shift]; } }; - typedef pattern_filter_nn pattern_filter_nn_rgba8; + typedef pattern_filter_nn pattern_filter_nn_rgba8; + typedef pattern_filter_nn pattern_filter_nn_rgba16; - - //===========================================pattern_filter_bilinear_rgba8 - struct pattern_filter_bilinear_rgba8 + //===========================================pattern_filter_bilinear_rgba + template struct pattern_filter_bilinear_rgba { - typedef rgba8 color_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + + static unsigned dilation() { return 1; } - static void pixel_low_res(color_type const* const* buf, - color_type* p, int x, int y) + static AGG_INLINE void pixel_low_res(color_type const* const* buf, + color_type* p, int x, int y) { *p = buf[y][x]; } - static void pixel_high_res(color_type const* const* buf, - color_type* p, int x, int y) + static AGG_INLINE void pixel_high_res(color_type const* const* buf, + color_type* p, int x, int y) { - int r, g, b, a; - r = g = b = a = line_subpixel_size * line_subpixel_size / 2; + calc_type r, g, b, a; + r = g = b = a = 0; - int weight; + calc_type weight; int x_lr = x >> line_subpixel_shift; int y_lr = y >> line_subpixel_shift; @@ -73,8 +77,8 @@ namespace agg y &= line_subpixel_mask; const color_type* ptr = buf[y_lr] + x_lr; - weight = (line_subpixel_size - x) * - (line_subpixel_size - y); + weight = (line_subpixel_scale - x) * + (line_subpixel_scale - y); r += weight * ptr->r; g += weight * ptr->g; b += weight * ptr->b; @@ -82,7 +86,7 @@ namespace agg ++ptr; - weight = x * (line_subpixel_size - y); + weight = x * (line_subpixel_scale - y); r += weight * ptr->r; g += weight * ptr->g; b += weight * ptr->b; @@ -90,7 +94,7 @@ namespace agg ptr = buf[y_lr + 1] + x_lr; - weight = (line_subpixel_size - x) * y; + weight = (line_subpixel_scale - x) * y; r += weight * ptr->r; g += weight * ptr->g; b += weight * ptr->b; @@ -104,14 +108,16 @@ namespace agg b += weight * ptr->b; a += weight * ptr->a; - p->r = (int8u)(r >> line_subpixel_shift * 2); - p->g = (int8u)(g >> line_subpixel_shift * 2); - p->b = (int8u)(b >> line_subpixel_shift * 2); - p->a = (int8u)(a >> line_subpixel_shift * 2); - + p->r = (value_type)color_type::downshift(r, line_subpixel_shift * 2); + p->g = (value_type)color_type::downshift(g, line_subpixel_shift * 2); + p->b = (value_type)color_type::downshift(b, line_subpixel_shift * 2); + p->a = (value_type)color_type::downshift(a, line_subpixel_shift * 2); } }; + typedef pattern_filter_bilinear_rgba pattern_filter_bilinear_rgba8; + typedef pattern_filter_bilinear_rgba pattern_filter_bilinear_rgba16; + typedef pattern_filter_bilinear_rgba pattern_filter_bilinear_rgba32; } #endif diff --git a/agg2/include/agg_pixfmt_amask_adaptor.h b/agg/include/agg_pixfmt_amask_adaptor.h similarity index 64% rename from agg2/include/agg_pixfmt_amask_adaptor.h rename to agg/include/agg_pixfmt_amask_adaptor.h index 3848374..fa44598 100644 --- a/agg2/include/agg_pixfmt_amask_adaptor.h +++ b/agg/include/agg_pixfmt_amask_adaptor.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -17,7 +17,8 @@ #define AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED -#include +#include +#include "agg_array.h" #include "agg_rendering_buffer.h" @@ -29,45 +30,48 @@ namespace agg 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 = 256 }; + enum span_extra_tail_e { span_extra_tail = 256 }; void realloc_span(unsigned len) { - if(len > m_max_len) + if(len > m_span.size()) { - delete [] m_span; - m_span = new cover_type[m_max_len = len + span_extra_tail]; + m_span.resize(len + span_extra_tail); } } void init_span(unsigned len) { realloc_span(len); - - // ATTN! May work incorrectly if cover_type is more that one byte - memset(m_span, amask_type::cover_full, len * sizeof(cover_type)); + std::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, covers, len * sizeof(cover_type)); + std::memcpy(&m_span[0], covers, len * sizeof(cover_type)); } public: - ~pixfmt_amask_adaptor() { delete [] m_span; } - - pixfmt_amask_adaptor(pixfmt_type& pixf, const amask_type& mask) : - m_pixf(&pixf), m_mask(&mask), m_span(0), m_max_len(0) + pixfmt_amask_adaptor(pixfmt_type& pixf, 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(amask_type& mask) { m_mask = &mask; } + + //-------------------------------------------------------------------- + template + 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(); } @@ -97,19 +101,19 @@ namespace agg const color_type& c) { realloc_span(len); - m_mask->fill_hspan(x, y, m_span, len); - m_pixf->blend_solid_hspan(x, y, len, c, m_span); + 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) + cover_type) { init_span(len); - m_mask->combine_hspan(x, y, m_span, len); - m_pixf->blend_solid_hspan(x, y, len, c, m_span); + m_mask->combine_hspan(x, y, &m_span[0], len); + m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]); } //-------------------------------------------------------------------- @@ -118,19 +122,19 @@ namespace agg const color_type& c) { realloc_span(len); - m_mask->fill_vspan(x, y, m_span, len); - m_pixf->blend_solid_vspan(x, y, len, c, m_span); + 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) + cover_type) { init_span(len); - m_mask->combine_vspan(x, y, m_span, len); - m_pixf->blend_solid_vspan(x, y, len, c, m_span); + m_mask->combine_vspan(x, y, &m_span[0], len); + m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]); } //-------------------------------------------------------------------- @@ -150,8 +154,8 @@ namespace agg const cover_type* covers) { init_span(len, covers); - m_mask->combine_hspan(x, y, m_span, len); - m_pixf->blend_solid_hspan(x, y, len, c, m_span); + m_mask->combine_hspan(x, y, &m_span[0], len); + m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]); } @@ -162,11 +166,27 @@ namespace agg const cover_type* covers) { init_span(len, covers); - m_mask->combine_vspan(x, y, m_span, len); - m_pixf->blend_solid_vspan(x, y, len, c, m_span); + m_mask->combine_vspan(x, y, &m_span[0], len); + m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]); } + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, unsigned len, const color_type* colors) + { + realloc_span(len); + m_mask->fill_hspan(x, y, &m_span[0], len); + m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover_full); + } + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, unsigned len, const color_type* colors) + { + realloc_span(len); + m_mask->fill_vspan(x, y, &m_span[0], len); + m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover_full); + } + //-------------------------------------------------------------------- void blend_color_hspan(int x, int y, unsigned len, @@ -177,14 +197,14 @@ namespace agg if(covers) { init_span(len, covers); - m_mask->combine_hspan(x, y, m_span, len); + m_mask->combine_hspan(x, y, &m_span[0], len); } else { realloc_span(len); - m_mask->fill_hspan(x, y, m_span, len); + m_mask->fill_hspan(x, y, &m_span[0], len); } - m_pixf->blend_color_hspan(x, y, len, colors, m_span, cover); + m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover); } @@ -198,22 +218,20 @@ namespace agg if(covers) { init_span(len, covers); - m_mask->combine_vspan(x, y, m_span, len); + m_mask->combine_vspan(x, y, &m_span[0], len); } else { realloc_span(len); - m_mask->fill_vspan(x, y, m_span, len); + m_mask->fill_vspan(x, y, &m_span[0], len); } - m_pixf->blend_color_vspan(x, y, len, colors, m_span, cover); + m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover); } private: - pixfmt_type* m_pixf; - const amask_type* m_mask; - - cover_type* m_span; - unsigned m_max_len; + pixfmt_type* m_pixf; + const amask_type* m_mask; + pod_array m_span; }; } diff --git a/agg/include/agg_pixfmt_base.h b/agg/include/agg_pixfmt_base.h new file mode 100644 index 0000000..57ae19c --- /dev/null +++ b/agg/include/agg_pixfmt_base.h @@ -0,0 +1,97 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_PIXFMT_BASE_INCLUDED +#define AGG_PIXFMT_BASE_INCLUDED + +#include "agg_basics.h" +#include "agg_color_gray.h" +#include "agg_color_rgba.h" + +namespace agg +{ + struct pixfmt_gray_tag + { + }; + + struct pixfmt_rgb_tag + { + }; + + struct pixfmt_rgba_tag + { + }; + + //--------------------------------------------------------------blender_base + template + 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) + { + 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; + } + 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); + } + + 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); + } + }; +} + +#endif diff --git a/agg/include/agg_pixfmt_gray.h b/agg/include/agg_pixfmt_gray.h new file mode 100644 index 0000000..3f99087 --- /dev/null +++ b/agg/include/agg_pixfmt_gray.h @@ -0,0 +1,738 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_PIXFMT_GRAY_INCLUDED +#define AGG_PIXFMT_GRAY_INCLUDED + +#include +#include "agg_pixfmt_base.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + + //============================================================blender_gray + template struct blender_gray + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + // Blend pixels using the non-premultiplied form of Alvy-Ray Smith's + // compositing function. Since the render buffer is opaque we skip the + // initial premultiply and final demultiply. + + static AGG_INLINE void blend_pix(value_type* p, + value_type cv, value_type alpha, cover_type cover) + { + blend_pix(p, cv, color_type::mult_cover(alpha, cover)); + } + + static AGG_INLINE void blend_pix(value_type* p, + value_type cv, value_type alpha) + { + *p = color_type::lerp(*p, cv, alpha); + } + }; + + + //======================================================blender_gray_pre + template struct blender_gray_pre + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + // Blend pixels using the premultiplied form of Alvy-Ray Smith's + // compositing function. + + static AGG_INLINE void blend_pix(value_type* p, + value_type cv, value_type alpha, cover_type cover) + { + blend_pix(p, color_type::mult_cover(cv, cover), color_type::mult_cover(alpha, cover)); + } + + static AGG_INLINE void blend_pix(value_type* p, + value_type cv, value_type alpha) + { + *p = color_type::prelerp(*p, cv, alpha); + } + }; + + + + //=====================================================apply_gamma_dir_gray + template class apply_gamma_dir_gray + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_dir_gray(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + *p = m_gamma.dir(*p); + } + + private: + const GammaLut& m_gamma; + }; + + + + //=====================================================apply_gamma_inv_gray + template class apply_gamma_inv_gray + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_inv_gray(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + *p = m_gamma.inv(*p); + } + + private: + const GammaLut& m_gamma; + }; + + + + //=================================================pixfmt_alpha_blend_gray + template + class pixfmt_alpha_blend_gray + { + public: + typedef pixfmt_gray_tag pixfmt_category; + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef int order_type; // A fake one + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum + { + num_components = 1, + pix_width = sizeof(value_type) * Step, + pix_step = Step, + pix_offset = Offset, + }; + struct pixel_type + { + value_type c[num_components]; + + void set(value_type v) + { + c[0] = v; + } + + void set(const color_type& color) + { + set(color.v); + } + + void get(value_type& v) const + { + v = c[0]; + } + + color_type get() const + { + return color_type(c[0]); + } + + pixel_type* next() + { + return (pixel_type*)(c + pix_step); + } + + const pixel_type* next() const + { + return (const pixel_type*)(c + pix_step); + } + + pixel_type* advance(int n) + { + return (pixel_type*)(c + n * pix_step); + } + + const pixel_type* advance(int n) const + { + return (const pixel_type*)(c + n * pix_step); + } + }; + + private: + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, + value_type v, value_type a, + unsigned cover) + { + blender_type::blend_pix(p->c, v, a, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, value_type v, value_type a) + { + blender_type::blend_pix(p->c, v, a); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover) + { + blender_type::blend_pix(p->c, c.v, c.a, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, const color_type& c) + { + blender_type::blend_pix(p->c, c.v, c.a); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover) + { + if (!c.is_transparent()) + { + if (c.is_opaque() && cover == cover_mask) + { + p->set(c); + } + else + { + blend_pix(p, c, cover); + } + } + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c) + { + if (!c.is_transparent()) + { + if (c.is_opaque()) + { + p->set(c); + } + else + { + blend_pix(p, c); + } + } + } + + public: + //-------------------------------------------------------------------- + explicit pixfmt_alpha_blend_gray(rbuf_type& rb) : + m_rbuf(&rb) + {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + //-------------------------------------------------------------------- + + template + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) + { + rect_i r(x1, y1, x2, y2); + if (r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + { + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; + } + return false; + } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- + int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset); + } + + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset); + } + + // Return pointer to pixel value, forcing row to be allocated. + AGG_INLINE pixel_type* pix_value_ptr(int x, int y, unsigned len) + { + return (pixel_type*)(m_rbuf->row_ptr(x, y, len) + sizeof(value_type) * (x * pix_step + pix_offset)); + } + + // Return pointer to pixel value, or null if row not allocated. + AGG_INLINE const pixel_type* pix_value_ptr(int x, int y) const + { + int8u* p = m_rbuf->row_ptr(y); + return p ? (pixel_type*)(p + sizeof(value_type) * (x * pix_step + pix_offset)) : 0; + } + + // Get pixel pointer from raw buffer pointer. + AGG_INLINE static pixel_type* pix_value_ptr(void* p) + { + return (pixel_type*)((value_type*)p + pix_offset); + } + + // Get pixel pointer from raw buffer pointer. + AGG_INLINE static const pixel_type* pix_value_ptr(const void* p) + { + return (const pixel_type*)((const value_type*)p + pix_offset); + } + + //-------------------------------------------------------------------- + AGG_INLINE static void write_plain_color(void* p, color_type c) + { + // Grayscale formats are implicitly premultiplied. + c.premultiply(); + pix_value_ptr(p)->set(c); + } + + //-------------------------------------------------------------------- + AGG_INLINE static color_type read_plain_color(const void* p) + { + return pix_value_ptr(p)->get(); + } + + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { + ((pixel_type*)p)->set(c); + } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + if (const pixel_type* p = pix_value_ptr(x, y)) + { + return p->get(); + } + return color_type::no_color(); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_pixel(int x, int y, const color_type& c) + { + pix_value_ptr(x, y, 1)->set(c); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + copy_or_blend_pix(pix_value_ptr(x, y, 1), c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type* p = pix_value_ptr(x, y, len); + do + { + p->set(c); + p = p->next(); + } + while(--len); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + do + { + pix_value_ptr(x, y++, 1)->set(c); + } + while (--len); + } + + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (!c.is_transparent()) + { + pixel_type* p = pix_value_ptr(x, y, len); + + if (c.is_opaque() && cover == cover_mask) + { + do + { + p->set(c); + p = p->next(); + } + while (--len); + } + else + { + do + { + blend_pix(p, c, cover); + p = p->next(); + } + while (--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (!c.is_transparent()) + { + if (c.is_opaque() && cover == cover_mask) + { + do + { + pix_value_ptr(x, y++, 1)->set(c); + } + while (--len); + } + else + { + do + { + blend_pix(pix_value_ptr(x, y++, 1), c, cover); + } + while (--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (!c.is_transparent()) + { + pixel_type* p = pix_value_ptr(x, y, len); + + do + { + if (c.is_opaque() && *covers == cover_mask) + { + p->set(c); + } + else + { + blend_pix(p, c, *covers); + } + p = p->next(); + ++covers; + } + while (--len); + } + } + + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (!c.is_transparent()) + { + do + { + pixel_type* p = pix_value_ptr(x, y++, 1); + + if (c.is_opaque() && *covers == cover_mask) + { + p->set(c); + } + else + { + blend_pix(p, c, *covers); + } + ++covers; + } + while (--len); + } + } + + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + pixel_type* p = pix_value_ptr(x, y, len); + + do + { + p->set(*colors++); + p = p->next(); + } + while (--len); + } + + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + pix_value_ptr(x, y++, 1)->set(*colors++); + } + while (--len); + } + + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + pixel_type* p = pix_value_ptr(x, y, len); + + if (covers) + { + do + { + copy_or_blend_pix(p, *colors++, *covers++); + p = p->next(); + } + while (--len); + } + else + { + if (cover == cover_mask) + { + do + { + copy_or_blend_pix(p, *colors++); + p = p->next(); + } + while (--len); + } + else + { + do + { + copy_or_blend_pix(p, *colors++, cover); + p = p->next(); + } + while (--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + if (covers) + { + do + { + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, *covers++); + } + while (--len); + } + else + { + if (cover == cover_mask) + { + do + { + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++); + } + while (--len); + } + else + { + do + { + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, cover); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + template void for_each_pixel(Function f) + { + unsigned y; + for (y = 0; y < height(); ++y) + { + row_data r = m_rbuf->row(y); + if (r.ptr) + { + unsigned len = r.x2 - r.x1 + 1; + pixel_type* p = pix_value_ptr(r.x1, y, len); + do + { + f(p->c); + p = p->next(); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + template void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_gray(g)); + } + + //-------------------------------------------------------------------- + template void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_gray(g)); + } + + //-------------------------------------------------------------------- + template + void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + if (const int8u* p = from.row_ptr(ysrc)) + { + std::memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } + + //-------------------------------------------------------------------- + // Blend from single color, using grayscale surface as alpha channel. + template + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + typedef typename SrcPixelFormatRenderer::color_type src_color_type; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + do + { + copy_or_blend_pix(pdst, color, src_color_type::scale_cover(cover, psrc->c[0])); + psrc = psrc->next(); + pdst = pdst->next(); + } + while (--len); + } + } + + //-------------------------------------------------------------------- + // Blend from color table, using grayscale surface as indexes into table. + // Obviously, this only works for integer value types. + template + void blend_from_lut(const SrcPixelFormatRenderer& from, + const color_type* color_lut, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + do + { + copy_or_blend_pix(pdst, color_lut[psrc->c[0]], cover); + psrc = psrc->next(); + pdst = pdst->next(); + } + while (--len); + } + } + + private: + rbuf_type* m_rbuf; + }; + + typedef blender_gray blender_gray8; + typedef blender_gray blender_sgray8; + typedef blender_gray blender_gray16; + typedef blender_gray blender_gray32; + + typedef blender_gray_pre blender_gray8_pre; + typedef blender_gray_pre blender_sgray8_pre; + typedef blender_gray_pre blender_gray16_pre; + typedef blender_gray_pre blender_gray32_pre; + + typedef pixfmt_alpha_blend_gray pixfmt_gray8; + typedef pixfmt_alpha_blend_gray pixfmt_sgray8; + typedef pixfmt_alpha_blend_gray pixfmt_gray16; + typedef pixfmt_alpha_blend_gray pixfmt_gray32; + + typedef pixfmt_alpha_blend_gray pixfmt_gray8_pre; + typedef pixfmt_alpha_blend_gray pixfmt_sgray8_pre; + typedef pixfmt_alpha_blend_gray pixfmt_gray16_pre; + typedef pixfmt_alpha_blend_gray pixfmt_gray32_pre; +} + +#endif + diff --git a/agg/include/agg_pixfmt_rgb.h b/agg/include/agg_pixfmt_rgb.h new file mode 100644 index 0000000..044654d --- /dev/null +++ b/agg/include/agg_pixfmt_rgb.h @@ -0,0 +1,995 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_PIXFMT_RGB_INCLUDED +#define AGG_PIXFMT_RGB_INCLUDED + +#include +#include "agg_pixfmt_base.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + + //=====================================================apply_gamma_dir_rgb + template class apply_gamma_dir_rgb + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_dir_rgb(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.dir(p[Order::R]); + p[Order::G] = m_gamma.dir(p[Order::G]); + p[Order::B] = m_gamma.dir(p[Order::B]); + } + + private: + const GammaLut& m_gamma; + }; + + + + //=====================================================apply_gamma_inv_rgb + template class apply_gamma_inv_rgb + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_inv_rgb(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.inv(p[Order::R]); + p[Order::G] = m_gamma.inv(p[Order::G]); + p[Order::B] = m_gamma.inv(p[Order::B]); + } + + private: + const GammaLut& m_gamma; + }; + + + //=========================================================blender_rgb + template + struct blender_rgb + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + // Blend pixels using the non-premultiplied form of Alvy-Ray Smith's + // compositing function. Since the render buffer is opaque we skip the + // initial premultiply and final demultiply. + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover) + { + blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover)); + } + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha) + { + p[Order::R] = color_type::lerp(p[Order::R], cr, alpha); + p[Order::G] = color_type::lerp(p[Order::G], cg, alpha); + p[Order::B] = color_type::lerp(p[Order::B], cb, alpha); + } + }; + + //======================================================blender_rgb_pre + template + struct blender_rgb_pre + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + // Blend pixels using the premultiplied form of Alvy-Ray Smith's + // compositing function. + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover) + { + blend_pix(p, + color_type::mult_cover(cr, cover), + color_type::mult_cover(cg, cover), + color_type::mult_cover(cb, cover), + color_type::mult_cover(alpha, cover)); + } + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha) + { + p[Order::R] = color_type::prelerp(p[Order::R], cr, alpha); + p[Order::G] = color_type::prelerp(p[Order::G], cg, alpha); + p[Order::B] = color_type::prelerp(p[Order::B], cb, alpha); + } + }; + + //===================================================blender_rgb_gamma + template + class blender_rgb_gamma : public blender_base + { + public: + typedef ColorT color_type; + typedef Order order_type; + typedef Gamma gamma_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + blender_rgb_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover) + { + blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover)); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha) + { + calc_type r = m_gamma->dir(p[Order::R]); + calc_type g = m_gamma->dir(p[Order::G]); + calc_type b = m_gamma->dir(p[Order::B]); + p[Order::R] = m_gamma->inv(color_type::downscale((m_gamma->dir(cr) - r) * alpha) + r); + p[Order::G] = m_gamma->inv(color_type::downscale((m_gamma->dir(cg) - g) * alpha) + g); + p[Order::B] = m_gamma->inv(color_type::downscale((m_gamma->dir(cb) - b) * alpha) + b); + } + + private: + const gamma_type* m_gamma; + }; + + + //==================================================pixfmt_alpha_blend_rgb + template + class pixfmt_alpha_blend_rgb + { + public: + typedef pixfmt_rgb_tag pixfmt_category; + typedef RenBuf rbuf_type; + typedef Blender blender_type; + typedef typename rbuf_type::row_data row_data; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum + { + num_components = 3, + pix_step = Step, + pix_offset = Offset, + pix_width = sizeof(value_type) * pix_step + }; + struct pixel_type + { + value_type c[num_components]; + + void set(value_type r, value_type g, value_type b) + { + c[order_type::R] = r; + c[order_type::G] = g; + c[order_type::B] = b; + } + + void set(const color_type& color) + { + set(color.r, color.g, color.b); + } + + void get(value_type& r, value_type& g, value_type& b) const + { + r = c[order_type::R]; + g = c[order_type::G]; + b = c[order_type::B]; + } + + color_type get() const + { + return color_type( + c[order_type::R], + c[order_type::G], + c[order_type::B]); + } + + pixel_type* next() + { + return (pixel_type*)(c + pix_step); + } + + const pixel_type* next() const + { + return (const pixel_type*)(c + pix_step); + } + + pixel_type* advance(int n) + { + return (pixel_type*)(c + n * pix_step); + } + + const pixel_type* advance(int n) const + { + return (const pixel_type*)(c + n * pix_step); + } + }; + + private: + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, + value_type r, value_type g, value_type b, value_type a, + unsigned cover) + { + m_blender.blend_pix(p->c, r, g, b, a, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, + value_type r, value_type g, value_type b, value_type a) + { + m_blender.blend_pix(p->c, r, g, b, a); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover) + { + m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, const color_type& c) + { + m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover) + { + if (!c.is_transparent()) + { + if (c.is_opaque() && cover == cover_mask) + { + p->set(c); + } + else + { + blend_pix(p, c, cover); + } + } + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c) + { + if (!c.is_transparent()) + { + if (c.is_opaque()) + { + p->set(c); + } + else + { + blend_pix(p, c); + } + } + } + + public: + //-------------------------------------------------------------------- + explicit pixfmt_alpha_blend_rgb(rbuf_type& rb) : + m_rbuf(&rb) + {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + + //-------------------------------------------------------------------- + template + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) + { + rect_i r(x1, y1, x2, y2); + if (r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + { + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; + } + return false; + } + + //-------------------------------------------------------------------- + Blender& blender() { return m_blender; } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset); + } + + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset); + } + + // Return pointer to pixel value, forcing row to be allocated. + AGG_INLINE pixel_type* pix_value_ptr(int x, int y, unsigned len) + { + return (pixel_type*)(m_rbuf->row_ptr(x, y, len) + sizeof(value_type) * (x * pix_step + pix_offset)); + } + + // Return pointer to pixel value, or null if row not allocated. + AGG_INLINE const pixel_type* pix_value_ptr(int x, int y) const + { + int8u* p = m_rbuf->row_ptr(y); + return p ? (pixel_type*)(p + sizeof(value_type) * (x * pix_step + pix_offset)) : 0; + } + + // Get pixel pointer from raw buffer pointer. + AGG_INLINE static pixel_type* pix_value_ptr(void* p) + { + return (pixel_type*)((value_type*)p + pix_offset); + } + + // Get pixel pointer from raw buffer pointer. + AGG_INLINE static const pixel_type* pix_value_ptr(const void* p) + { + return (const pixel_type*)((const value_type*)p + pix_offset); + } + + //-------------------------------------------------------------------- + AGG_INLINE static void write_plain_color(void* p, color_type c) + { + // RGB formats are implicitly premultiplied. + c.premultiply(); + pix_value_ptr(p)->set(c); + } + + //-------------------------------------------------------------------- + AGG_INLINE static color_type read_plain_color(const void* p) + { + return pix_value_ptr(p)->get(); + } + + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { + ((pixel_type*)p)->set(c); + } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + if (const pixel_type* p = pix_value_ptr(x, y)) + { + return p->get(); + } + return color_type::no_color(); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_pixel(int x, int y, const color_type& c) + { + pix_value_ptr(x, y, 1)->set(c); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + copy_or_blend_pix(pix_value_ptr(x, y, 1), c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type* p = pix_value_ptr(x, y, len); + do + { + p->set(c); + p = p->next(); + } + while(--len); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + do + { + pix_value_ptr(x, y++, 1)->set(c); + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (!c.is_transparent()) + { + pixel_type* p = pix_value_ptr(x, y, len); + + if (c.is_opaque() && cover == cover_mask) + { + do + { + p->set(c); + p = p->next(); + } + while (--len); + } + else + { + do + { + blend_pix(p, c, cover); + p = p->next(); + } + while (--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (!c.is_transparent()) + { + if (c.is_opaque() && cover == cover_mask) + { + do + { + pix_value_ptr(x, y++, 1)->set(c); + } + while (--len); + } + else + { + do + { + blend_pix(pix_value_ptr(x, y++, 1), c, cover); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (!c.is_transparent()) + { + pixel_type* p = pix_value_ptr(x, y, len); + + do + { + if (c.is_opaque() && *covers == cover_mask) + { + p->set(c); + } + else + { + blend_pix(p, c, *covers); + } + p = p->next(); + ++covers; + } + while (--len); + } + } + + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (!c.is_transparent()) + { + do + { + pixel_type* p = pix_value_ptr(x, y++, 1); + + if (c.is_opaque() && *covers == cover_mask) + { + p->set(c); + } + else + { + blend_pix(p, c, *covers); + } + ++covers; + } + while (--len); + } + } + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + pixel_type* p = pix_value_ptr(x, y, len); + + do + { + p->set(*colors++); + p = p->next(); + } + while (--len); + } + + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + pix_value_ptr(x, y++, 1)->set(*colors++); + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + pixel_type* p = pix_value_ptr(x, y, len); + + if (covers) + { + do + { + copy_or_blend_pix(p, *colors++, *covers++); + p = p->next(); + } + while (--len); + } + else + { + if (cover == cover_mask) + { + do + { + copy_or_blend_pix(p, *colors++); + p = p->next(); + } + while (--len); + } + else + { + do + { + copy_or_blend_pix(p, *colors++, cover); + p = p->next(); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + if (covers) + { + do + { + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, *covers++); + } + while (--len); + } + else + { + if (cover == cover_mask) + { + do + { + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++); + } + while (--len); + } + else + { + do + { + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, cover); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + template void for_each_pixel(Function f) + { + for (unsigned y = 0; y < height(); ++y) + { + row_data r = m_rbuf->row(y); + if (r.ptr) + { + unsigned len = r.x2 - r.x1 + 1; + pixel_type* p = pix_value_ptr(r.x1, y, len); + do + { + f(p->c); + p = p->next(); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + template void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_rgb(g)); + } + + //-------------------------------------------------------------------- + template void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_rgb(g)); + } + + //-------------------------------------------------------------------- + template + void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + if (const int8u* p = from.row_ptr(ysrc)) + { + std::memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } + + //-------------------------------------------------------------------- + // Blend from an RGBA surface. + template + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + typedef typename SrcPixelFormatRenderer::order_type src_order; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + if (cover == cover_mask) + { + do + { + value_type alpha = psrc->c[src_order::A]; + if (alpha <= color_type::empty_value()) + { + if (alpha >= color_type::full_value()) + { + pdst->c[order_type::R] = psrc->c[src_order::R]; + pdst->c[order_type::G] = psrc->c[src_order::G]; + pdst->c[order_type::B] = psrc->c[src_order::B]; + } + else + { + blend_pix(pdst, + psrc->c[src_order::R], + psrc->c[src_order::G], + psrc->c[src_order::B], + alpha); + } + } + psrc = psrc->next(); + pdst = pdst->next(); + } + while(--len); + } + else + { + do + { + copy_or_blend_pix(pdst, psrc->get(), cover); + psrc = psrc->next(); + pdst = pdst->next(); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + // Blend from single color, using grayscale surface as alpha channel. + template + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + typedef typename SrcPixelFormatRenderer::color_type src_color_type; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + do + { + copy_or_blend_pix(pdst, color, src_color_type::scale_cover(cover, psrc->c[0])); + psrc = psrc->next(); + pdst = pdst->next(); + } + while (--len); + } + } + + //-------------------------------------------------------------------- + // Blend from color table, using grayscale surface as indexes into table. + // Obviously, this only works for integer value types. + template + void blend_from_lut(const SrcPixelFormatRenderer& from, + const color_type* color_lut, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + if (cover == cover_mask) + { + do + { + const color_type& color = color_lut[psrc->c[0]]; + blend_pix(pdst, color); + psrc = psrc->next(); + pdst = pdst->next(); + } + while(--len); + } + else + { + do + { + copy_or_blend_pix(pdst, color_lut[psrc->c[0]], cover); + psrc = psrc->next(); + pdst = pdst->next(); + } + while(--len); + } + } + } + + private: + rbuf_type* m_rbuf; + Blender m_blender; + }; + + //----------------------------------------------------------------------- + typedef blender_rgb blender_rgb24; + typedef blender_rgb blender_bgr24; + typedef blender_rgb blender_srgb24; + typedef blender_rgb blender_sbgr24; + typedef blender_rgb blender_rgb48; + typedef blender_rgb blender_bgr48; + typedef blender_rgb blender_rgb96; + typedef blender_rgb blender_bgr96; + + typedef blender_rgb_pre blender_rgb24_pre; + typedef blender_rgb_pre blender_bgr24_pre; + typedef blender_rgb_pre blender_srgb24_pre; + typedef blender_rgb_pre blender_sbgr24_pre; + typedef blender_rgb_pre blender_rgb48_pre; + typedef blender_rgb_pre blender_bgr48_pre; + typedef blender_rgb_pre blender_rgb96_pre; + typedef blender_rgb_pre blender_bgr96_pre; + + typedef pixfmt_alpha_blend_rgb pixfmt_rgb24; + typedef pixfmt_alpha_blend_rgb pixfmt_bgr24; + typedef pixfmt_alpha_blend_rgb pixfmt_srgb24; + typedef pixfmt_alpha_blend_rgb pixfmt_sbgr24; + typedef pixfmt_alpha_blend_rgb pixfmt_rgb48; + typedef pixfmt_alpha_blend_rgb pixfmt_bgr48; + typedef pixfmt_alpha_blend_rgb pixfmt_rgb96; + typedef pixfmt_alpha_blend_rgb pixfmt_bgr96; + + typedef pixfmt_alpha_blend_rgb pixfmt_rgb24_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_bgr24_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_srgb24_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_sbgr24_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_rgb48_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_bgr48_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_rgb96_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_bgr96_pre; + + typedef pixfmt_alpha_blend_rgb pixfmt_rgbx32; + typedef pixfmt_alpha_blend_rgb pixfmt_xrgb32; + typedef pixfmt_alpha_blend_rgb pixfmt_xbgr32; + typedef pixfmt_alpha_blend_rgb pixfmt_bgrx32; + typedef pixfmt_alpha_blend_rgb pixfmt_srgbx32; + typedef pixfmt_alpha_blend_rgb pixfmt_sxrgb32; + typedef pixfmt_alpha_blend_rgb pixfmt_sxbgr32; + typedef pixfmt_alpha_blend_rgb pixfmt_sbgrx32; + typedef pixfmt_alpha_blend_rgb pixfmt_rgbx64; + typedef pixfmt_alpha_blend_rgb pixfmt_xrgb64; + typedef pixfmt_alpha_blend_rgb pixfmt_xbgr64; + typedef pixfmt_alpha_blend_rgb pixfmt_bgrx64; + typedef pixfmt_alpha_blend_rgb pixfmt_rgbx128; + typedef pixfmt_alpha_blend_rgb pixfmt_xrgb128; + typedef pixfmt_alpha_blend_rgb pixfmt_xbgr128; + typedef pixfmt_alpha_blend_rgb pixfmt_bgrx128; + + typedef pixfmt_alpha_blend_rgb pixfmt_rgbx32_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_xrgb32_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_xbgr32_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_bgrx32_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_srgbx32_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_sxrgb32_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_sxbgr32_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_sbgrx32_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_rgbx64_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_xrgb64_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_xbgr64_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_bgrx64_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_rgbx128_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_xrgb128_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_xbgr128_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_bgrx128_pre; + + + //-----------------------------------------------------pixfmt_rgb24_gamma + template class pixfmt_rgb24_gamma : + public pixfmt_alpha_blend_rgb, rendering_buffer, 3> + { + public: + pixfmt_rgb24_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb, rendering_buffer, 3>(rb) + { + this->blender().gamma(g); + } + }; + + //-----------------------------------------------------pixfmt_srgb24_gamma + template class pixfmt_srgb24_gamma : + public pixfmt_alpha_blend_rgb, rendering_buffer, 3> + { + public: + pixfmt_srgb24_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb, rendering_buffer, 3>(rb) + { + this->blender().gamma(g); + } + }; + + //-----------------------------------------------------pixfmt_bgr24_gamma + template class pixfmt_bgr24_gamma : + public pixfmt_alpha_blend_rgb, rendering_buffer, 3> + { + public: + pixfmt_bgr24_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb, rendering_buffer, 3>(rb) + { + this->blender().gamma(g); + } + }; + + //-----------------------------------------------------pixfmt_sbgr24_gamma + template class pixfmt_sbgr24_gamma : + public pixfmt_alpha_blend_rgb, rendering_buffer, 3> + { + public: + pixfmt_sbgr24_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb, rendering_buffer, 3>(rb) + { + this->blender().gamma(g); + } + }; + + //-----------------------------------------------------pixfmt_rgb48_gamma + template class pixfmt_rgb48_gamma : + public pixfmt_alpha_blend_rgb, rendering_buffer, 3> + { + public: + pixfmt_rgb48_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb, rendering_buffer, 3>(rb) + { + this->blender().gamma(g); + } + }; + + //-----------------------------------------------------pixfmt_bgr48_gamma + template class pixfmt_bgr48_gamma : + public pixfmt_alpha_blend_rgb, rendering_buffer, 3> + { + public: + pixfmt_bgr48_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb, rendering_buffer, 3>(rb) + { + this->blender().gamma(g); + } + }; + +} + +#endif + diff --git a/agg/include/agg_pixfmt_rgb_packed.h b/agg/include/agg_pixfmt_rgb_packed.h new file mode 100644 index 0000000..eac6d42 --- /dev/null +++ b/agg/include/agg_pixfmt_rgb_packed.h @@ -0,0 +1,1312 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_PIXFMT_RGB_PACKED_INCLUDED +#define AGG_PIXFMT_RGB_PACKED_INCLUDED + +#include +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + //=========================================================blender_rgb555 + struct blender_rgb555 + { + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = (rgb >> 7) & 0xF8; + calc_type g = (rgb >> 2) & 0xF8; + calc_type b = (rgb << 3) & 0xF8; + *p = (pixel_type) + (((((cr - r) * alpha + (r << 8)) >> 1) & 0x7C00) | + ((((cg - g) * alpha + (g << 8)) >> 6) & 0x03E0) | + (((cb - b) * alpha + (b << 8)) >> 11) | 0x8000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 7) | + ((g & 0xF8) << 2) | + (b >> 3) | 0x8000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 7) & 0xF8, + (p >> 2) & 0xF8, + (p << 3) & 0xF8); + } + }; + + + //=====================================================blender_rgb555_pre + struct blender_rgb555_pre + { + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + pixel_type rgb = *p; + calc_type r = (rgb >> 7) & 0xF8; + calc_type g = (rgb >> 2) & 0xF8; + calc_type b = (rgb << 3) & 0xF8; + *p = (pixel_type) + ((((r * alpha + cr * cover) >> 1) & 0x7C00) | + (((g * alpha + cg * cover) >> 6) & 0x03E0) | + ((b * alpha + cb * cover) >> 11) | 0x8000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 7) | + ((g & 0xF8) << 2) | + (b >> 3) | 0x8000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 7) & 0xF8, + (p >> 2) & 0xF8, + (p << 3) & 0xF8); + } + }; + + + + + //=====================================================blender_rgb555_gamma + template class blender_rgb555_gamma + { + public: + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + typedef Gamma gamma_type; + + blender_rgb555_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = m_gamma->dir((rgb >> 7) & 0xF8); + calc_type g = m_gamma->dir((rgb >> 2) & 0xF8); + calc_type b = m_gamma->dir((rgb << 3) & 0xF8); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 7) & 0x7C00) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 2) & 0x03E0) | + (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3) | 0x8000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 7) | + ((g & 0xF8) << 2) | + (b >> 3) | 0x8000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 7) & 0xF8, + (p >> 2) & 0xF8, + (p << 3) & 0xF8); + } + + private: + const Gamma* m_gamma; + }; + + + + + + //=========================================================blender_rgb565 + struct blender_rgb565 + { + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = (rgb >> 8) & 0xF8; + calc_type g = (rgb >> 3) & 0xFC; + calc_type b = (rgb << 3) & 0xF8; + *p = (pixel_type) + (((((cr - r) * alpha + (r << 8)) ) & 0xF800) | + ((((cg - g) * alpha + (g << 8)) >> 5) & 0x07E0) | + (((cb - b) * alpha + (b << 8)) >> 11)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 8) & 0xF8, + (p >> 3) & 0xFC, + (p << 3) & 0xF8); + } + }; + + + + //=====================================================blender_rgb565_pre + struct blender_rgb565_pre + { + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + pixel_type rgb = *p; + calc_type r = (rgb >> 8) & 0xF8; + calc_type g = (rgb >> 3) & 0xFC; + calc_type b = (rgb << 3) & 0xF8; + *p = (pixel_type) + ((((r * alpha + cr * cover) ) & 0xF800) | + (((g * alpha + cg * cover) >> 5 ) & 0x07E0) | + ((b * alpha + cb * cover) >> 11)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 8) & 0xF8, + (p >> 3) & 0xFC, + (p << 3) & 0xF8); + } + }; + + + + //=====================================================blender_rgb565_gamma + template class blender_rgb565_gamma + { + public: + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + typedef Gamma gamma_type; + + blender_rgb565_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = m_gamma->dir((rgb >> 8) & 0xF8); + calc_type g = m_gamma->dir((rgb >> 3) & 0xFC); + calc_type b = m_gamma->dir((rgb << 3) & 0xF8); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 8) & 0xF800) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 3) & 0x07E0) | + (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 8) & 0xF8, + (p >> 3) & 0xFC, + (p << 3) & 0xF8); + } + + private: + const Gamma* m_gamma; + }; + + + + //=====================================================blender_rgbAAA + struct blender_rgbAAA + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = (rgb >> 14) & 0xFFC0; + calc_type g = (rgb >> 4) & 0xFFC0; + calc_type b = (rgb << 6) & 0xFFC0; + *p = (pixel_type) + (((((cr - r) * alpha + (r << 16)) >> 2) & 0x3FF00000) | + ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) | + (((cb - b) * alpha + (b << 16)) >> 22) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (b >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 14) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p << 6) & 0xFFC0); + } + }; + + + + //==================================================blender_rgbAAA_pre + struct blender_rgbAAA_pre + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (color_type::base_shift - 8); + pixel_type rgb = *p; + calc_type r = (rgb >> 14) & 0xFFC0; + calc_type g = (rgb >> 4) & 0xFFC0; + calc_type b = (rgb << 6) & 0xFFC0; + *p = (pixel_type) + ((((r * alpha + cr * cover) >> 2) & 0x3FF00000) | + (((g * alpha + cg * cover) >> 12) & 0x000FFC00) | + ((b * alpha + cb * cover) >> 22) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (b >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 14) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p << 6) & 0xFFC0); + } + }; + + + + //=================================================blender_rgbAAA_gamma + template class blender_rgbAAA_gamma + { + public: + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + typedef Gamma gamma_type; + + blender_rgbAAA_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = m_gamma->dir((rgb >> 14) & 0xFFC0); + calc_type g = m_gamma->dir((rgb >> 4) & 0xFFC0); + calc_type b = m_gamma->dir((rgb << 6) & 0xFFC0); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 14) & 0x3FF00000) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) | + (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 ) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (b >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 14) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p << 6) & 0xFFC0); + } + private: + const Gamma* m_gamma; + }; + + + //=====================================================blender_bgrAAA + struct blender_bgrAAA + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type bgr = *p; + calc_type b = (bgr >> 14) & 0xFFC0; + calc_type g = (bgr >> 4) & 0xFFC0; + calc_type r = (bgr << 6) & 0xFFC0; + *p = (pixel_type) + (((((cb - b) * alpha + (b << 16)) >> 2) & 0x3FF00000) | + ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) | + (((cr - r) * alpha + (r << 16)) >> 22) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (r >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 6) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p >> 14) & 0xFFC0); + } + }; + + + + //=================================================blender_bgrAAA_pre + struct blender_bgrAAA_pre + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (color_type::base_shift - 8); + pixel_type bgr = *p; + calc_type b = (bgr >> 14) & 0xFFC0; + calc_type g = (bgr >> 4) & 0xFFC0; + calc_type r = (bgr << 6) & 0xFFC0; + *p = (pixel_type) + ((((b * alpha + cb * cover) >> 2) & 0x3FF00000) | + (((g * alpha + cg * cover) >> 12) & 0x000FFC00) | + ((r * alpha + cr * cover) >> 22) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (r >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 6) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p >> 14) & 0xFFC0); + } + }; + + + + //=================================================blender_bgrAAA_gamma + template class blender_bgrAAA_gamma + { + public: + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + typedef Gamma gamma_type; + + blender_bgrAAA_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type bgr = *p; + calc_type b = m_gamma->dir((bgr >> 14) & 0xFFC0); + calc_type g = m_gamma->dir((bgr >> 4) & 0xFFC0); + calc_type r = m_gamma->dir((bgr << 6) & 0xFFC0); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 14) & 0x3FF00000) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) | + (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 6 ) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (r >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 6) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p >> 14) & 0xFFC0); + } + + private: + const Gamma* m_gamma; + }; + + + + //=====================================================blender_rgbBBA + struct blender_rgbBBA + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = (rgb >> 16) & 0xFFE0; + calc_type g = (rgb >> 5) & 0xFFE0; + calc_type b = (rgb << 6) & 0xFFC0; + *p = (pixel_type) + (((((cr - r) * alpha + (r << 16)) ) & 0xFFE00000) | + ((((cg - g) * alpha + (g << 16)) >> 11) & 0x001FFC00) | + (((cb - b) * alpha + (b << 16)) >> 22)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 16) & 0xFFE0, + (p >> 5) & 0xFFE0, + (p << 6) & 0xFFC0); + } + }; + + + //=================================================blender_rgbBBA_pre + struct blender_rgbBBA_pre + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (color_type::base_shift - 8); + pixel_type rgb = *p; + calc_type r = (rgb >> 16) & 0xFFE0; + calc_type g = (rgb >> 5) & 0xFFE0; + calc_type b = (rgb << 6) & 0xFFC0; + *p = (pixel_type) + ((((r * alpha + cr * cover) ) & 0xFFE00000) | + (((g * alpha + cg * cover) >> 11) & 0x001FFC00) | + ((b * alpha + cb * cover) >> 22)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 16) & 0xFFE0, + (p >> 5) & 0xFFE0, + (p << 6) & 0xFFC0); + } + }; + + + + //=================================================blender_rgbBBA_gamma + template class blender_rgbBBA_gamma + { + public: + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + typedef Gamma gamma_type; + + blender_rgbBBA_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = m_gamma->dir((rgb >> 16) & 0xFFE0); + calc_type g = m_gamma->dir((rgb >> 5) & 0xFFE0); + calc_type b = m_gamma->dir((rgb << 6) & 0xFFC0); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 16) & 0xFFE00000) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 5 ) & 0x001FFC00) | + (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 )); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 16) & 0xFFE0, + (p >> 5) & 0xFFE0, + (p << 6) & 0xFFC0); + } + + private: + const Gamma* m_gamma; + }; + + + //=====================================================blender_bgrABB + struct blender_bgrABB + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type bgr = *p; + calc_type b = (bgr >> 16) & 0xFFC0; + calc_type g = (bgr >> 6) & 0xFFE0; + calc_type r = (bgr << 5) & 0xFFE0; + *p = (pixel_type) + (((((cb - b) * alpha + (b << 16)) ) & 0xFFC00000) | + ((((cg - g) * alpha + (g << 16)) >> 10) & 0x003FF800) | + (((cr - r) * alpha + (r << 16)) >> 21)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 5) & 0xFFE0, + (p >> 6) & 0xFFE0, + (p >> 16) & 0xFFC0); + } + }; + + + //=================================================blender_bgrABB_pre + struct blender_bgrABB_pre + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (color_type::base_shift - 8); + pixel_type bgr = *p; + calc_type b = (bgr >> 16) & 0xFFC0; + calc_type g = (bgr >> 6) & 0xFFE0; + calc_type r = (bgr << 5) & 0xFFE0; + *p = (pixel_type) + ((((b * alpha + cb * cover) ) & 0xFFC00000) | + (((g * alpha + cg * cover) >> 10) & 0x003FF800) | + ((r * alpha + cr * cover) >> 21)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 5) & 0xFFE0, + (p >> 6) & 0xFFE0, + (p >> 16) & 0xFFC0); + } + }; + + + + //=================================================blender_bgrABB_gamma + template class blender_bgrABB_gamma + { + public: + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + typedef Gamma gamma_type; + + blender_bgrABB_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type bgr = *p; + calc_type b = m_gamma->dir((bgr >> 16) & 0xFFC0); + calc_type g = m_gamma->dir((bgr >> 6) & 0xFFE0); + calc_type r = m_gamma->dir((bgr << 5) & 0xFFE0); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 16) & 0xFFC00000) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 6 ) & 0x003FF800) | + (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 5 )); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 5) & 0xFFE0, + (p >> 6) & 0xFFE0, + (p >> 16) & 0xFFC0); + } + + private: + const Gamma* m_gamma; + }; + + + + //===========================================pixfmt_alpha_blend_rgb_packed + template class pixfmt_alpha_blend_rgb_packed + { + public: + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::pixel_type pixel_type; + typedef int order_type; // A fake one + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask, + pix_width = sizeof(pixel_type), + }; + + private: + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover) + { + if (c.a) + { + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + *p = m_blender.make_pix(c.r, c.g, c.b); + } + else + { + m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); + } + } + } + + public: + //-------------------------------------------------------------------- + explicit pixfmt_alpha_blend_rgb_packed(rbuf_type& rb) : m_rbuf(&rb) {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + + //-------------------------------------------------------------------- + template + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) + { + rect_i r(x1, y1, x2, y2); + if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + { + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; + } + return false; + } + + Blender& blender() { return m_blender; } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + x * pix_width; + } + + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + return m_rbuf->row_ptr(y) + x * pix_width; + } + + //-------------------------------------------------------------------- + AGG_INLINE void make_pix(int8u* p, const color_type& c) + { + *(pixel_type*)p = m_blender.make_pix(c.r, c.g, c.b); + } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + return m_blender.make_color(((pixel_type*)m_rbuf->row_ptr(y))[x]); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_pixel(int x, int y, const color_type& c) + { + ((pixel_type*) + m_rbuf->row_ptr(x, y, 1))[x] = + m_blender.make_pix(c.r, c.g, c.b); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y, 1) + x, c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; + pixel_type v = m_blender.make_pix(c.r, c.g, c.b); + do + { + *p++ = v; + } + while(--len); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type v = m_blender.make_pix(c.r, c.g, c.b); + do + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x; + *p = v; + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + pixel_type v = m_blender.make_pix(c.r, c.g, c.b); + do + { + *p++ = v; + } + while(--len); + } + else + { + do + { + m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); + ++p; + } + while(--len); + } + } + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) + { + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + pixel_type v = m_blender.make_pix(c.r, c.g, c.b); + do + { + ((pixel_type*)m_rbuf->row_ptr(x, y++, 1))[x] = v; + } + while(--len); + } + else + { + do + { + m_blender.blend_pix( + (pixel_type*)m_rbuf->row_ptr(x, y++, 1), + c.r, c.g, c.b, alpha, cover); + } + while(--len); + } + } + } + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; + do + { + copy_or_blend_pix(p, c, *covers++); + ++p; + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + do + { + copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x, + c, *covers++); + } + while(--len); + } + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; + do + { + *p++ = m_blender.make_pix(colors->r, colors->g, colors->b); + ++colors; + } + while(--len); + } + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x; + *p = m_blender.make_pix(colors->r, colors->g, colors->b); + ++colors; + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; + do + { + copy_or_blend_pix(p++, *colors++, covers ? *covers++ : cover); + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + do + { + copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x, + *colors++, covers ? *covers++ : cover); + } + while(--len); + } + + //-------------------------------------------------------------------- + template + void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + const int8u* p = from.row_ptr(ysrc); + if(p) + { + std::memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } + + //-------------------------------------------------------------------- + template + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::order_type src_order; + + const value_type* psrc = (const value_type*)from.row_ptr(ysrc); + if(psrc) + { + psrc += xsrc * 4; + pixel_type* pdst = + (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; + do + { + value_type alpha = psrc[src_order::A]; + if(alpha) + { + if(alpha == base_mask && cover == 255) + { + *pdst = m_blender.make_pix(psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B]); + } + else + { + m_blender.blend_pix(pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + alpha, + cover); + } + } + psrc += 4; + ++pdst; + } + while(--len); + } + } + + //-------------------------------------------------------------------- + template + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + typedef typename SrcPixelFormatRenderer::color_type src_color_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + psrc += xsrc * SrcPixelFormatRenderer::pix_step + SrcPixelFormatRenderer::pix_offset; + pixel_type* pdst = + (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; + + do + { + m_blender.blend_pix(pdst, + color.r, color.g, color.b, color.a, + cover); + psrc += SrcPixelFormatRenderer::pix_step; + ++pdst; + } + while(--len); + } + } + + //-------------------------------------------------------------------- + template + void blend_from_lut(const SrcPixelFormatRenderer& from, + const color_type* color_lut, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + psrc += xsrc * SrcPixelFormatRenderer::pix_step + SrcPixelFormatRenderer::pix_offset; + pixel_type* pdst = + (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; + + do + { + const color_type& color = color_lut[*psrc]; + m_blender.blend_pix(pdst, + color.r, color.g, color.b, color.a, + cover); + psrc += SrcPixelFormatRenderer::pix_step; + ++pdst; + } + while(--len); + } + } + + + + private: + rbuf_type* m_rbuf; + Blender m_blender; + }; + + typedef pixfmt_alpha_blend_rgb_packed pixfmt_rgb555; //----pixfmt_rgb555 + typedef pixfmt_alpha_blend_rgb_packed pixfmt_rgb565; //----pixfmt_rgb565 + + typedef pixfmt_alpha_blend_rgb_packed pixfmt_rgb555_pre; //----pixfmt_rgb555_pre + typedef pixfmt_alpha_blend_rgb_packed pixfmt_rgb565_pre; //----pixfmt_rgb565_pre + + typedef pixfmt_alpha_blend_rgb_packed pixfmt_rgbAAA; //----pixfmt_rgbAAA + typedef pixfmt_alpha_blend_rgb_packed pixfmt_bgrAAA; //----pixfmt_bgrAAA + typedef pixfmt_alpha_blend_rgb_packed pixfmt_rgbBBA; //----pixfmt_rgbBBA + typedef pixfmt_alpha_blend_rgb_packed pixfmt_bgrABB; //----pixfmt_bgrABB + + typedef pixfmt_alpha_blend_rgb_packed pixfmt_rgbAAA_pre; //----pixfmt_rgbAAA_pre + typedef pixfmt_alpha_blend_rgb_packed pixfmt_bgrAAA_pre; //----pixfmt_bgrAAA_pre + typedef pixfmt_alpha_blend_rgb_packed pixfmt_rgbBBA_pre; //----pixfmt_rgbBBA_pre + typedef pixfmt_alpha_blend_rgb_packed pixfmt_bgrABB_pre; //----pixfmt_bgrABB_pre + + + //-----------------------------------------------------pixfmt_rgb555_gamma + template class pixfmt_rgb555_gamma : + public pixfmt_alpha_blend_rgb_packed, + rendering_buffer> + { + public: + pixfmt_rgb555_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb_packed, + rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_rgb565_gamma + template class pixfmt_rgb565_gamma : + public pixfmt_alpha_blend_rgb_packed, rendering_buffer> + { + public: + pixfmt_rgb565_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb_packed, rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_rgbAAA_gamma + template class pixfmt_rgbAAA_gamma : + public pixfmt_alpha_blend_rgb_packed, + rendering_buffer> + { + public: + pixfmt_rgbAAA_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb_packed, + rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_bgrAAA_gamma + template class pixfmt_bgrAAA_gamma : + public pixfmt_alpha_blend_rgb_packed, + rendering_buffer> + { + public: + pixfmt_bgrAAA_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb_packed, + rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_rgbBBA_gamma + template class pixfmt_rgbBBA_gamma : + public pixfmt_alpha_blend_rgb_packed, + rendering_buffer> + { + public: + pixfmt_rgbBBA_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb_packed, + rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_bgrABB_gamma + template class pixfmt_bgrABB_gamma : + public pixfmt_alpha_blend_rgb_packed, + rendering_buffer> + { + public: + pixfmt_bgrABB_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb_packed, + rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + +} + +#endif + diff --git a/agg/include/agg_pixfmt_rgba.h b/agg/include/agg_pixfmt_rgba.h new file mode 100644 index 0000000..c9172f6 --- /dev/null +++ b/agg/include/agg_pixfmt_rgba.h @@ -0,0 +1,2803 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_PIXFMT_RGBA_INCLUDED +#define AGG_PIXFMT_RGBA_INCLUDED + +#include +#include +#include "agg_pixfmt_base.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + template inline T sd_min(T a, T b) { return (a < b) ? a : b; } + template inline T sd_max(T a, T b) { return (a > b) ? a : b; } + + inline rgba & clip(rgba & c) + { + if (c.a > 1) c.a = 1; else if (c.a < 0) c.a = 0; + if (c.r > c.a) c.r = c.a; else if (c.r < 0) c.r = 0; + if (c.g > c.a) c.g = c.a; else if (c.g < 0) c.g = 0; + if (c.b > c.a) c.b = c.a; else if (c.b < 0) c.b = 0; + return c; + } + + //=========================================================multiplier_rgba + template + struct multiplier_rgba + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + + //-------------------------------------------------------------------- + static AGG_INLINE void premultiply(value_type* p) + { + value_type a = p[Order::A]; + p[Order::R] = color_type::multiply(p[Order::R], a); + p[Order::G] = color_type::multiply(p[Order::G], a); + p[Order::B] = color_type::multiply(p[Order::B], a); + } + + + //-------------------------------------------------------------------- + static AGG_INLINE void demultiply(value_type* p) + { + value_type a = p[Order::A]; + p[Order::R] = color_type::demultiply(p[Order::R], a); + p[Order::G] = color_type::demultiply(p[Order::G], a); + p[Order::B] = color_type::demultiply(p[Order::B], a); + } + }; + + //=====================================================apply_gamma_dir_rgba + template + class apply_gamma_dir_rgba + { + public: + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + + apply_gamma_dir_rgba(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.dir(p[Order::R]); + p[Order::G] = m_gamma.dir(p[Order::G]); + p[Order::B] = m_gamma.dir(p[Order::B]); + } + + private: + const GammaLut& m_gamma; + }; + + //=====================================================apply_gamma_inv_rgba + template class apply_gamma_inv_rgba + { + public: + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + + apply_gamma_inv_rgba(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.inv(p[Order::R]); + p[Order::G] = m_gamma.inv(p[Order::G]); + p[Order::B] = m_gamma.inv(p[Order::B]); + } + + private: + const GammaLut& m_gamma; + }; + + + template + struct conv_rgba_pre + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + + //-------------------------------------------------------------------- + static AGG_INLINE void set_plain_color(value_type* p, color_type c) + { + c.premultiply(); + p[Order::R] = c.r; + p[Order::G] = c.g; + p[Order::B] = c.b; + p[Order::A] = c.a; + } + + //-------------------------------------------------------------------- + static AGG_INLINE color_type get_plain_color(const value_type* p) + { + return color_type( + p[Order::R], + p[Order::G], + p[Order::B], + p[Order::A]).demultiply(); + } + }; + + template + struct conv_rgba_plain + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + + //-------------------------------------------------------------------- + static AGG_INLINE void set_plain_color(value_type* p, color_type c) + { + p[Order::R] = c.r; + p[Order::G] = c.g; + p[Order::B] = c.b; + p[Order::A] = c.a; + } + + //-------------------------------------------------------------------- + static AGG_INLINE color_type get_plain_color(const value_type* p) + { + return color_type( + p[Order::R], + p[Order::G], + p[Order::B], + p[Order::A]); + } + }; + + //=============================================================blender_rgba + // Blends "plain" (i.e. non-premultiplied) colors into a premultiplied buffer. + template + struct blender_rgba : conv_rgba_pre + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + // Blend pixels using the non-premultiplied form of Alvy-Ray Smith's + // compositing function. Since the render buffer is in fact premultiplied + // we omit the initial premultiplication and final demultiplication. + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover) + { + blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover)); + } + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha) + { + p[Order::R] = color_type::lerp(p[Order::R], cr, alpha); + p[Order::G] = color_type::lerp(p[Order::G], cg, alpha); + p[Order::B] = color_type::lerp(p[Order::B], cb, alpha); + p[Order::A] = color_type::prelerp(p[Order::A], alpha, alpha); + } + }; + + + //========================================================blender_rgba_pre + // Blends premultiplied colors into a premultiplied buffer. + template + struct blender_rgba_pre : conv_rgba_pre + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + // Blend pixels using the premultiplied form of Alvy-Ray Smith's + // compositing function. + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover) + { + blend_pix(p, + color_type::mult_cover(cr, cover), + color_type::mult_cover(cg, cover), + color_type::mult_cover(cb, cover), + color_type::mult_cover(alpha, cover)); + } + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha) + { + p[Order::R] = color_type::prelerp(p[Order::R], cr, alpha); + p[Order::G] = color_type::prelerp(p[Order::G], cg, alpha); + p[Order::B] = color_type::prelerp(p[Order::B], cb, alpha); + p[Order::A] = color_type::prelerp(p[Order::A], alpha, alpha); + } + }; + + //======================================================blender_rgba_plain + // Blends "plain" (non-premultiplied) colors into a plain (non-premultiplied) buffer. + template + struct blender_rgba_plain : conv_rgba_plain + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + // Blend pixels using the non-premultiplied form of Alvy-Ray Smith's + // compositing function. + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover) + { + blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover)); + } + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha) + { + if (alpha > color_type::empty_value()) + { + calc_type a = p[Order::A]; + calc_type r = color_type::multiply(p[Order::R], a); + calc_type g = color_type::multiply(p[Order::G], a); + calc_type b = color_type::multiply(p[Order::B], a); + p[Order::R] = color_type::lerp(r, cr, alpha); + p[Order::G] = color_type::lerp(g, cg, alpha); + p[Order::B] = color_type::lerp(b, cb, alpha); + p[Order::A] = color_type::prelerp(a, alpha, alpha); + multiplier_rgba::demultiply(p); + } + } + }; + + // SVG compositing operations. + // For specifications, see http://www.w3.org/TR/SVGCompositing/ + + //=========================================================comp_op_rgba_clear + template + struct comp_op_rgba_clear : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = 0 + // Da' = 0 + static AGG_INLINE void blend_pix(value_type* p, + value_type, value_type, value_type, value_type, cover_type cover) + { + if (cover >= cover_full) + { + p[0] = p[1] = p[2] = p[3] = color_type::empty_value(); + } + else if (cover > cover_none) + { + set(p, get(p, cover_full - cover)); + } + } + }; + + //===========================================================comp_op_rgba_src + template + struct comp_op_rgba_src : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca + // Da' = Sa + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + if (cover >= cover_full) + { + set(p, r, g, b, a); + } + else + { + rgba s = get(r, g, b, a, cover); + rgba d = get(p, cover_full - cover); + d.r += s.r; + d.g += s.g; + d.b += s.b; + d.a += s.a; + set(p, d); + } + } + }; + + //===========================================================comp_op_rgba_dst + template + struct comp_op_rgba_dst : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + + // Dca' = Dca.Sa + Dca.(1 - Sa) = Dca + // Da' = Da.Sa + Da.(1 - Sa) = Da + static AGG_INLINE void blend_pix(value_type*, + value_type, value_type, value_type, value_type, cover_type) + { + // Well, that was easy! + } + }; + + //======================================================comp_op_rgba_src_over + template + struct comp_op_rgba_src_over : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca + Dca.(1 - Sa) = Dca + Sca - Dca.Sa + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { +#if 1 + blender_rgba_pre::blend_pix(p, r, g, b, a, cover); +#else + rgba s = get(r, g, b, a, cover); + rgba d = get(p); + d.r += s.r - d.r * s.a; + d.g += s.g - d.g * s.a; + d.b += s.b - d.b * s.a; + d.a += s.a - d.a * s.a; + set(p, d); +#endif + } + }; + + //======================================================comp_op_rgba_dst_over + template + struct comp_op_rgba_dst_over : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Dca + Sca.(1 - Da) + // Da' = Sa + Da - Sa.Da = Da + Sa.(1 - Da) + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + rgba d = get(p); + double d1a = 1 - d.a; + d.r += s.r * d1a; + d.g += s.g * d1a; + d.b += s.b * d1a; + d.a += s.a * d1a; + set(p, d); + } + }; + + //======================================================comp_op_rgba_src_in + template + struct comp_op_rgba_src_in : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca.Da + // Da' = Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + double da = ColorT::to_double(p[Order::A]); + if (da > 0) + { + rgba s = get(r, g, b, a, cover); + rgba d = get(p, cover_full - cover); + d.r += s.r * da; + d.g += s.g * da; + d.b += s.b * da; + d.a += s.a * da; + set(p, d); + } + } + }; + + //======================================================comp_op_rgba_dst_in + template + struct comp_op_rgba_dst_in : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Dca.Sa + // Da' = Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type, value_type, value_type, value_type a, cover_type cover) + { + double sa = ColorT::to_double(a); + rgba d = get(p, cover_full - cover); + rgba d2 = get(p, cover); + d.r += d2.r * sa; + d.g += d2.g * sa; + d.b += d2.b * sa; + d.a += d2.a * sa; + set(p, d); + } + }; + + //======================================================comp_op_rgba_src_out + template + struct comp_op_rgba_src_out : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca.(1 - Da) + // Da' = Sa.(1 - Da) + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + rgba d = get(p, cover_full - cover); + double d1a = 1 - ColorT::to_double(p[Order::A]); + d.r += s.r * d1a; + d.g += s.g * d1a; + d.b += s.b * d1a; + d.a += s.a * d1a; + set(p, d); + } + }; + + //======================================================comp_op_rgba_dst_out + template + struct comp_op_rgba_dst_out : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Dca.(1 - Sa) + // Da' = Da.(1 - Sa) + static AGG_INLINE void blend_pix(value_type* p, + value_type, value_type, value_type, value_type a, cover_type cover) + { + rgba d = get(p, cover_full - cover); + rgba dc = get(p, cover); + double s1a = 1 - ColorT::to_double(a); + d.r += dc.r * s1a; + d.g += dc.g * s1a; + d.b += dc.b * s1a; + d.a += dc.a * s1a; + set(p, d); + } + }; + + //=====================================================comp_op_rgba_src_atop + template + struct comp_op_rgba_src_atop : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca.Da + Dca.(1 - Sa) + // Da' = Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + rgba d = get(p); + double s1a = 1 - s.a; + d.r = s.r * d.a + d.r * s1a; + d.g = s.g * d.a + d.g * s1a; + d.b = s.b * d.a + d.g * s1a; + set(p, d); + } + }; + + //=====================================================comp_op_rgba_dst_atop + template + struct comp_op_rgba_dst_atop : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Dca.Sa + Sca.(1 - Da) + // Da' = Sa + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba sc = get(r, g, b, a, cover); + rgba dc = get(p, cover); + rgba d = get(p, cover_full - cover); + double sa = ColorT::to_double(a); + double d1a = 1 - ColorT::to_double(p[Order::A]); + d.r += dc.r * sa + sc.r * d1a; + d.g += dc.g * sa + sc.g * d1a; + d.b += dc.b * sa + sc.b * d1a; + d.a += sc.a; + set(p, d); + } + }; + + //=========================================================comp_op_rgba_xor + template + struct comp_op_rgba_xor : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - 2.Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + rgba d = get(p); + double s1a = 1 - s.a; + double d1a = 1 - ColorT::to_double(p[Order::A]); + d.r = s.r * d1a + d.r * s1a; + d.g = s.g * d1a + d.g * s1a; + d.b = s.b * d1a + d.b * s1a; + d.a = s.a + d.a - 2 * s.a * d.a; + set(p, d); + } + }; + + //=========================================================comp_op_rgba_plus + template + struct comp_op_rgba_plus : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca + Dca + // Da' = Sa + Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + d.a = sd_min(d.a + s.a, 1.0); + d.r = sd_min(d.r + s.r, d.a); + d.g = sd_min(d.g + s.g, d.a); + d.b = sd_min(d.b + s.b, d.a); + set(p, clip(d)); + } + } + }; + + //========================================================comp_op_rgba_minus + // Note: not included in SVG spec. + template + struct comp_op_rgba_minus : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Dca - Sca + // Da' = 1 - (1 - Sa).(1 - Da) = Da + Sa - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + d.a += s.a - s.a * d.a; + d.r = sd_max(d.r - s.r, 0.0); + d.g = sd_max(d.g - s.g, 0.0); + d.b = sd_max(d.b - s.b, 0.0); + set(p, clip(d)); + } + } + }; + + //=====================================================comp_op_rgba_multiply + template + struct comp_op_rgba_multiply : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + double s1a = 1 - s.a; + double d1a = 1 - d.a; + d.r = s.r * d.r + s.r * d1a + d.r * s1a; + d.g = s.g * d.g + s.g * d1a + d.g * s1a; + d.b = s.b * d.b + s.b * d1a + d.b * s1a; + d.a += s.a - s.a * d.a; + set(p, clip(d)); + } + } + }; + + //=====================================================comp_op_rgba_screen + template + struct comp_op_rgba_screen : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca + Dca - Sca.Dca + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + d.r += s.r - s.r * d.r; + d.g += s.g - s.g * d.g; + d.b += s.b - s.b * d.b; + d.a += s.a - s.a * d.a; + set(p, clip(d)); + } + } + }; + + //=====================================================comp_op_rgba_overlay + template + struct comp_op_rgba_overlay : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // if 2.Dca <= Da + // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE double calc(double dca, double sca, double da, double sa, double sada, double d1a, double s1a) + { + return (2 * dca <= da) ? + 2 * sca * dca + sca * d1a + dca * s1a : + sada - 2 * (da - dca) * (sa - sca) + sca * d1a + dca * s1a; + } + + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + double d1a = 1 - d.a; + double s1a = 1 - s.a; + double sada = s.a * d.a; + d.r = calc(d.r, s.r, d.a, s.a, sada, d1a, s1a); + d.g = calc(d.g, s.g, d.a, s.a, sada, d1a, s1a); + d.b = calc(d.b, s.b, d.a, s.a, sada, d1a, s1a); + d.a += s.a - s.a * d.a; + set(p, clip(d)); + } + } + }; + + //=====================================================comp_op_rgba_darken + template + struct comp_op_rgba_darken : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + double d1a = 1 - d.a; + double s1a = 1 - s.a; + d.r = sd_min(s.r * d.a, d.r * s.a) + s.r * d1a + d.r * s1a; + d.g = sd_min(s.g * d.a, d.g * s.a) + s.g * d1a + d.g * s1a; + d.b = sd_min(s.b * d.a, d.b * s.a) + s.b * d1a + d.b * s1a; + d.a += s.a - s.a * d.a; + set(p, clip(d)); + } + } + }; + + //=====================================================comp_op_rgba_lighten + template + struct comp_op_rgba_lighten : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + double d1a = 1 - d.a; + double s1a = 1 - s.a; + d.r = sd_max(s.r * d.a, d.r * s.a) + s.r * d1a + d.r * s1a; + d.g = sd_max(s.g * d.a, d.g * s.a) + s.g * d1a + d.g * s1a; + d.b = sd_max(s.b * d.a, d.b * s.a) + s.b * d1a + d.b * s1a; + d.a += s.a - s.a * d.a; + set(p, clip(d)); + } + } + }; + + //=====================================================comp_op_rgba_color_dodge + template + struct comp_op_rgba_color_dodge : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // if Sca == Sa and Dca == 0 + // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) = Sca.(1 - Da) + // otherwise if Sca == Sa + // Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise if Sca < Sa + // Dca' = Sa.Da.min(1, Dca/Da.Sa/(Sa - Sca)) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE double calc(double dca, double sca, double da, double sa, double sada, double d1a, double s1a) + { + if (sca < sa) return sada * sd_min(1.0, (dca / da) * sa / (sa - sca)) + sca * d1a + dca * s1a; + if (dca > 0) return sada + sca * d1a + dca * s1a; + return sca * d1a; + } + + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + if (d.a > 0) + { + double sada = s.a * d.a; + double s1a = 1 - s.a; + double d1a = 1 - d.a; + d.r = calc(d.r, s.r, d.a, s.a, sada, d1a, s1a); + d.g = calc(d.g, s.g, d.a, s.a, sada, d1a, s1a); + d.b = calc(d.b, s.b, d.a, s.a, sada, d1a, s1a); + d.a += s.a - s.a * d.a; + set(p, clip(d)); + } + else set(p, s); + } + } + }; + + //=====================================================comp_op_rgba_color_burn + template + struct comp_op_rgba_color_burn : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // if Sca == 0 and Dca == Da + // Dca' = Sa.Da + Dca.(1 - Sa) + // otherwise if Sca == 0 + // Dca' = Dca.(1 - Sa) + // otherwise if Sca > 0 + // Dca' = Sa.Da.(1 - min(1, (1 - Dca/Da).Sa/Sca)) + Sca.(1 - Da) + Dca.(1 - Sa) + static AGG_INLINE double calc(double dca, double sca, double da, double sa, double sada, double d1a, double s1a) + { + if (sca > 0) return sada * (1 - sd_min(1.0, (1 - dca / da) * sa / sca)) + sca * d1a + dca * s1a; + if (dca > da) return sada + dca * s1a; + return dca * s1a; + } + + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + if (d.a > 0) + { + double sada = s.a * d.a; + double s1a = 1 - s.a; + double d1a = 1 - d.a; + d.r = calc(d.r, s.r, d.a, s.a, sada, d1a, s1a); + d.g = calc(d.g, s.g, d.a, s.a, sada, d1a, s1a); + d.b = calc(d.b, s.b, d.a, s.a, sada, d1a, s1a); + d.a += s.a - sada; + set(p, clip(d)); + } + else set(p, s); + } + } + }; + + //=====================================================comp_op_rgba_hard_light + template + struct comp_op_rgba_hard_light : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // if 2.Sca < Sa + // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE double calc(double dca, double sca, double da, double sa, double sada, double d1a, double s1a) + { + return (2 * sca < sa) ? + 2 * sca * dca + sca * d1a + dca * s1a : + sada - 2 * (da - dca) * (sa - sca) + sca * d1a + dca * s1a; + } + + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + double d1a = 1 - d.a; + double s1a = 1 - s.a; + double sada = s.a * d.a; + d.r = calc(d.r, s.r, d.a, s.a, sada, d1a, s1a); + d.g = calc(d.g, s.g, d.a, s.a, sada, d1a, s1a); + d.b = calc(d.b, s.b, d.a, s.a, sada, d1a, s1a); + d.a += s.a - sada; + set(p, clip(d)); + } + } + }; + + //=====================================================comp_op_rgba_soft_light + template + struct comp_op_rgba_soft_light : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // if 2.Sca <= Sa + // Dca' = Dca.Sa - (Sa.Da - 2.Sca.Da).Dca.Sa.(Sa.Da - Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise if 2.Sca > Sa and 4.Dca <= Da + // Dca' = Dca.Sa + (2.Sca.Da - Sa.Da).((((16.Dsa.Sa - 12).Dsa.Sa + 4).Dsa.Da) - Dsa.Da) + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise if 2.Sca > Sa and 4.Dca > Da + // Dca' = Dca.Sa + (2.Sca.Da - Sa.Da).((Dca.Sa)^0.5 - Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE double calc(double dca, double sca, double da, double sa, double sada, double d1a, double s1a) + { + double dcasa = dca * sa; + if (2 * sca <= sa) return dcasa - (sada - 2 * sca * da) * dcasa * (sada - dcasa) + sca * d1a + dca * s1a; + if (4 * dca <= da) return dcasa + (2 * sca * da - sada) * ((((16 * dcasa - 12) * dcasa + 4) * dca * da) - dca * da) + sca * d1a + dca * s1a; + return dcasa + (2 * sca * da - sada) * (std::sqrt(dcasa) - dcasa) + sca * d1a + dca * s1a; + } + + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + if (d.a > 0) + { + double sada = s.a * d.a; + double s1a = 1 - s.a; + double d1a = 1 - d.a; + d.r = calc(d.r, s.r, d.a, s.a, sada, d1a, s1a); + d.g = calc(d.g, s.g, d.a, s.a, sada, d1a, s1a); + d.b = calc(d.b, s.b, d.a, s.a, sada, d1a, s1a); + d.a += s.a - sada; + set(p, clip(d)); + } + else set(p, s); + } + } + }; + + //=====================================================comp_op_rgba_difference + template + struct comp_op_rgba_difference : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca + Dca - 2.min(Sca.Da, Dca.Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + d.r += s.r - 2 * sd_min(s.r * d.a, d.r * s.a); + d.g += s.g - 2 * sd_min(s.g * d.a, d.g * s.a); + d.b += s.b - 2 * sd_min(s.b * d.a, d.b * s.a); + d.a += s.a - s.a * d.a; + set(p, clip(d)); + } + } + }; + + //=====================================================comp_op_rgba_exclusion + template + struct comp_op_rgba_exclusion : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + double d1a = 1 - d.a; + double s1a = 1 - s.a; + d.r = (s.r * d.a + d.r * s.a - 2 * s.r * d.r) + s.r * d1a + d.r * s1a; + d.g = (s.g * d.a + d.g * s.a - 2 * s.g * d.g) + s.g * d1a + d.g * s1a; + d.b = (s.b * d.a + d.b * s.a - 2 * s.b * d.b) + s.b * d1a + d.b * s1a; + d.a += s.a - s.a * d.a; + set(p, clip(d)); + } + } + }; + +#if 0 + //=====================================================comp_op_rgba_contrast + template struct comp_op_rgba_contrast + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if (cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + long_type dr = p[Order::R]; + long_type dg = p[Order::G]; + long_type db = p[Order::B]; + int da = p[Order::A]; + long_type d2a = da >> 1; + unsigned s2a = sa >> 1; + + int r = (int)((((dr - d2a) * int((sr - s2a)*2 + base_mask)) >> base_shift) + d2a); + int g = (int)((((dg - d2a) * int((sg - s2a)*2 + base_mask)) >> base_shift) + d2a); + int b = (int)((((db - d2a) * int((sb - s2a)*2 + base_mask)) >> base_shift) + d2a); + + r = (r < 0) ? 0 : r; + g = (g < 0) ? 0 : g; + b = (b < 0) ? 0 : b; + + p[Order::R] = (value_type)((r > da) ? da : r); + p[Order::G] = (value_type)((g > da) ? da : g); + p[Order::B] = (value_type)((b > da) ? da : b); + } + }; + + //=====================================================comp_op_rgba_invert + template struct comp_op_rgba_invert + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = (Da - Dca) * Sa + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + sa = (sa * cover + 255) >> 8; + if (sa) + { + calc_type da = p[Order::A]; + calc_type dr = ((da - p[Order::R]) * sa + base_mask) >> base_shift; + calc_type dg = ((da - p[Order::G]) * sa + base_mask) >> base_shift; + calc_type db = ((da - p[Order::B]) * sa + base_mask) >> base_shift; + calc_type s1a = base_mask - sa; + p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + //=================================================comp_op_rgba_invert_rgb + template struct comp_op_rgba_invert_rgb + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = (Da - Dca) * Sca + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if (cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if (sa) + { + calc_type da = p[Order::A]; + calc_type dr = ((da - p[Order::R]) * sr + base_mask) >> base_shift; + calc_type dg = ((da - p[Order::G]) * sg + base_mask) >> base_shift; + calc_type db = ((da - p[Order::B]) * sb + base_mask) >> base_shift; + calc_type s1a = base_mask - sa; + p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; +#endif + + + //======================================================comp_op_table_rgba + template struct comp_op_table_rgba + { + typedef typename ColorT::value_type value_type; + typedef typename ColorT::calc_type calc_type; + typedef void (*comp_op_func_type)(value_type* p, + value_type cr, + value_type cg, + value_type cb, + value_type ca, + cover_type cover); + static comp_op_func_type g_comp_op_func[]; + }; + + //==========================================================g_comp_op_func + template + typename comp_op_table_rgba::comp_op_func_type + comp_op_table_rgba::g_comp_op_func[] = + { + comp_op_rgba_clear ::blend_pix, + comp_op_rgba_src ::blend_pix, + comp_op_rgba_dst ::blend_pix, + comp_op_rgba_src_over ::blend_pix, + comp_op_rgba_dst_over ::blend_pix, + comp_op_rgba_src_in ::blend_pix, + comp_op_rgba_dst_in ::blend_pix, + comp_op_rgba_src_out ::blend_pix, + comp_op_rgba_dst_out ::blend_pix, + comp_op_rgba_src_atop ::blend_pix, + comp_op_rgba_dst_atop ::blend_pix, + comp_op_rgba_xor ::blend_pix, + comp_op_rgba_plus ::blend_pix, + //comp_op_rgba_minus ::blend_pix, + comp_op_rgba_multiply ::blend_pix, + comp_op_rgba_screen ::blend_pix, + comp_op_rgba_overlay ::blend_pix, + comp_op_rgba_darken ::blend_pix, + comp_op_rgba_lighten ::blend_pix, + comp_op_rgba_color_dodge::blend_pix, + comp_op_rgba_color_burn ::blend_pix, + comp_op_rgba_hard_light ::blend_pix, + comp_op_rgba_soft_light ::blend_pix, + comp_op_rgba_difference ::blend_pix, + comp_op_rgba_exclusion ::blend_pix, + //comp_op_rgba_contrast ::blend_pix, + //comp_op_rgba_invert ::blend_pix, + //comp_op_rgba_invert_rgb ::blend_pix, + 0 + }; + + + //==============================================================comp_op_e + enum comp_op_e + { + comp_op_clear, //----comp_op_clear + comp_op_src, //----comp_op_src + comp_op_dst, //----comp_op_dst + comp_op_src_over, //----comp_op_src_over + comp_op_dst_over, //----comp_op_dst_over + comp_op_src_in, //----comp_op_src_in + comp_op_dst_in, //----comp_op_dst_in + comp_op_src_out, //----comp_op_src_out + comp_op_dst_out, //----comp_op_dst_out + comp_op_src_atop, //----comp_op_src_atop + comp_op_dst_atop, //----comp_op_dst_atop + comp_op_xor, //----comp_op_xor + comp_op_plus, //----comp_op_plus + //comp_op_minus, //----comp_op_minus + comp_op_multiply, //----comp_op_multiply + comp_op_screen, //----comp_op_screen + comp_op_overlay, //----comp_op_overlay + comp_op_darken, //----comp_op_darken + comp_op_lighten, //----comp_op_lighten + comp_op_color_dodge, //----comp_op_color_dodge + comp_op_color_burn, //----comp_op_color_burn + comp_op_hard_light, //----comp_op_hard_light + comp_op_soft_light, //----comp_op_soft_light + comp_op_difference, //----comp_op_difference + comp_op_exclusion, //----comp_op_exclusion + //comp_op_contrast, //----comp_op_contrast + //comp_op_invert, //----comp_op_invert + //comp_op_invert_rgb, //----comp_op_invert_rgb + + end_of_comp_op_e + }; + + + + + + + + //====================================================comp_op_adaptor_rgba + template + struct comp_op_adaptor_rgba + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + comp_op_table_rgba::g_comp_op_func[op](p, + color_type::multiply(r, a), + color_type::multiply(g, a), + color_type::multiply(b, a), + a, cover); + } + }; + + //=========================================comp_op_adaptor_clip_to_dst_rgba + template + struct comp_op_adaptor_clip_to_dst_rgba + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + r = color_type::multiply(r, a); + g = color_type::multiply(g, a); + b = color_type::multiply(b, a); + value_type da = p[Order::A]; + comp_op_table_rgba::g_comp_op_func[op](p, + color_type::multiply(r, da), + color_type::multiply(g, da), + color_type::multiply(b, da), + color_type::multiply(a, da), cover); + } + }; + + //================================================comp_op_adaptor_rgba_pre + template + struct comp_op_adaptor_rgba_pre + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + comp_op_table_rgba::g_comp_op_func[op](p, r, g, b, a, cover); + } + }; + + //=====================================comp_op_adaptor_clip_to_dst_rgba_pre + template + struct comp_op_adaptor_clip_to_dst_rgba_pre + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + value_type da = p[Order::A]; + comp_op_table_rgba::g_comp_op_func[op](p, + color_type::multiply(r, da), + color_type::multiply(g, da), + color_type::multiply(b, da), + color_type::multiply(a, da), cover); + } + }; + + //====================================================comp_op_adaptor_rgba_plain + template + struct comp_op_adaptor_rgba_plain + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + multiplier_rgba::premultiply(p); + comp_op_adaptor_rgba::blend_pix(op, p, r, g, b, a, cover); + multiplier_rgba::demultiply(p); + } + }; + + //=========================================comp_op_adaptor_clip_to_dst_rgba_plain + template + struct comp_op_adaptor_clip_to_dst_rgba_plain + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + multiplier_rgba::premultiply(p); + comp_op_adaptor_clip_to_dst_rgba::blend_pix(op, p, r, g, b, a, cover); + multiplier_rgba::demultiply(p); + } + }; + + //=======================================================comp_adaptor_rgba + template + struct comp_adaptor_rgba + { + typedef typename BlenderPre::color_type color_type; + typedef typename BlenderPre::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + BlenderPre::blend_pix(p, + color_type::multiply(r, a), + color_type::multiply(g, a), + color_type::multiply(b, a), + a, cover); + } + }; + + //==========================================comp_adaptor_clip_to_dst_rgba + template + struct comp_adaptor_clip_to_dst_rgba + { + typedef typename BlenderPre::color_type color_type; + typedef typename BlenderPre::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + r = color_type::multiply(r, a); + g = color_type::multiply(g, a); + b = color_type::multiply(b, a); + value_type da = p[order_type::A]; + BlenderPre::blend_pix(p, + color_type::multiply(r, da), + color_type::multiply(g, da), + color_type::multiply(b, da), + color_type::multiply(a, da), cover); + } + }; + + //=======================================================comp_adaptor_rgba_pre + template + struct comp_adaptor_rgba_pre + { + typedef typename BlenderPre::color_type color_type; + typedef typename BlenderPre::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + BlenderPre::blend_pix(p, r, g, b, a, cover); + } + }; + + //======================================comp_adaptor_clip_to_dst_rgba_pre + template + struct comp_adaptor_clip_to_dst_rgba_pre + { + typedef typename BlenderPre::color_type color_type; + typedef typename BlenderPre::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + unsigned da = p[order_type::A]; + BlenderPre::blend_pix(p, + color_type::multiply(r, da), + color_type::multiply(g, da), + color_type::multiply(b, da), + color_type::multiply(a, da), + cover); + } + }; + + //=======================================================comp_adaptor_rgba_plain + template + struct comp_adaptor_rgba_plain + { + typedef typename BlenderPre::color_type color_type; + typedef typename BlenderPre::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + multiplier_rgba::premultiply(p); + comp_adaptor_rgba::blend_pix(op, p, r, g, b, a, cover); + multiplier_rgba::demultiply(p); + } + }; + + //==========================================comp_adaptor_clip_to_dst_rgba_plain + template + struct comp_adaptor_clip_to_dst_rgba_plain + { + typedef typename BlenderPre::color_type color_type; + typedef typename BlenderPre::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + multiplier_rgba::premultiply(p); + comp_adaptor_clip_to_dst_rgba::blend_pix(op, p, r, g, b, a, cover); + multiplier_rgba::demultiply(p); + } + }; + + + //=================================================pixfmt_alpha_blend_rgba + template + class pixfmt_alpha_blend_rgba + { + public: + typedef pixfmt_rgba_tag pixfmt_category; + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum + { + num_components = 4, + pix_step = 4, + pix_width = sizeof(value_type) * pix_step, + }; + struct pixel_type + { + value_type c[num_components]; + + void set(value_type r, value_type g, value_type b, value_type a) + { + c[order_type::R] = r; + c[order_type::G] = g; + c[order_type::B] = b; + c[order_type::A] = a; + } + + void set(const color_type& color) + { + set(color.r, color.g, color.b, color.a); + } + + void get(value_type& r, value_type& g, value_type& b, value_type& a) const + { + r = c[order_type::R]; + g = c[order_type::G]; + b = c[order_type::B]; + a = c[order_type::A]; + } + + color_type get() const + { + return color_type( + c[order_type::R], + c[order_type::G], + c[order_type::B], + c[order_type::A]); + } + + pixel_type* next() + { + return (pixel_type*)(c + pix_step); + } + + const pixel_type* next() const + { + return (const pixel_type*)(c + pix_step); + } + + pixel_type* advance(int n) + { + return (pixel_type*)(c + n * pix_step); + } + + const pixel_type* advance(int n) const + { + return (const pixel_type*)(c + n * pix_step); + } + }; + + private: + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover) + { + m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, const color_type& c) + { + m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover) + { + if (!c.is_transparent()) + { + if (c.is_opaque() && cover == cover_mask) + { + p->set(c.r, c.g, c.b, c.a); + } + else + { + m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a, cover); + } + } + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c) + { + if (!c.is_transparent()) + { + if (c.is_opaque()) + { + p->set(c.r, c.g, c.b, c.a); + } + else + { + m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a); + } + } + } + + public: + //-------------------------------------------------------------------- + pixfmt_alpha_blend_rgba() : m_rbuf(0) {} + explicit pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + + //-------------------------------------------------------------------- + template + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) + { + rect_i r(x1, y1, x2, y2); + if (r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + { + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; + } + return false; + } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step); + } + + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step); + } + + // Return pointer to pixel value, forcing row to be allocated. + AGG_INLINE pixel_type* pix_value_ptr(int x, int y, unsigned len) + { + return (pixel_type*)(m_rbuf->row_ptr(x, y, len) + sizeof(value_type) * (x * pix_step)); + } + + // Return pointer to pixel value, or null if row not allocated. + AGG_INLINE const pixel_type* pix_value_ptr(int x, int y) const + { + int8u* p = m_rbuf->row_ptr(y); + return p ? (pixel_type*)(p + sizeof(value_type) * (x * pix_step)) : 0; + } + + // Get pixel pointer from raw buffer pointer. + AGG_INLINE static pixel_type* pix_value_ptr(void* p) + { + return (pixel_type*)p; + } + + // Get pixel pointer from raw buffer pointer. + AGG_INLINE static const pixel_type* pix_value_ptr(const void* p) + { + return (const pixel_type*)p; + } + + //-------------------------------------------------------------------- + AGG_INLINE static void write_plain_color(void* p, color_type c) + { + blender_type::set_plain_color(pix_value_ptr(p)->c, c); + } + + //-------------------------------------------------------------------- + AGG_INLINE static color_type read_plain_color(const void* p) + { + return blender_type::get_plain_color(pix_value_ptr(p)->c); + } + + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { + ((pixel_type*)p)->set(c); + } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + if (const pixel_type* p = pix_value_ptr(x, y)) + { + return p->get(); + } + return color_type::no_color(); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_pixel(int x, int y, const color_type& c) + { + pix_value_ptr(x, y, 1)->set(c); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + copy_or_blend_pix(pix_value_ptr(x, y, 1), c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type v; + v.set(c); + pixel_type* p = pix_value_ptr(x, y, len); + do + { + *p = v; + p = p->next(); + } + while (--len); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type v; + v.set(c); + do + { + *pix_value_ptr(x, y++, 1) = v; + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (!c.is_transparent()) + { + pixel_type* p = pix_value_ptr(x, y, len); + if (c.is_opaque() && cover == cover_mask) + { + pixel_type v; + v.set(c); + do + { + *p = v; + p = p->next(); + } + while (--len); + } + else + { + if (cover == cover_mask) + { + do + { + blend_pix(p, c); + p = p->next(); + } + while (--len); + } + else + { + do + { + blend_pix(p, c, cover); + p = p->next(); + } + while (--len); + } + } + } + } + + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (!c.is_transparent()) + { + if (c.is_opaque() && cover == cover_mask) + { + pixel_type v; + v.set(c); + do + { + *pix_value_ptr(x, y++, 1) = v; + } + while (--len); + } + else + { + if (cover == cover_mask) + { + do + { + blend_pix(pix_value_ptr(x, y++, 1), c, c.a); + } + while (--len); + } + else + { + do + { + blend_pix(pix_value_ptr(x, y++, 1), c, cover); + } + while (--len); + } + } + } + } + + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (!c.is_transparent()) + { + pixel_type* p = pix_value_ptr(x, y, len); + do + { + if (c.is_opaque() && *covers == cover_mask) + { + p->set(c); + } + else + { + blend_pix(p, c, *covers); + } + p = p->next(); + ++covers; + } + while (--len); + } + } + + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (!c.is_transparent()) + { + do + { + pixel_type* p = pix_value_ptr(x, y++, 1); + if (c.is_opaque() && *covers == cover_mask) + { + p->set(c); + } + else + { + blend_pix(p, c, *covers); + } + ++covers; + } + while (--len); + } + } + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + pixel_type* p = pix_value_ptr(x, y, len); + do + { + p->set(*colors++); + p = p->next(); + } + while (--len); + } + + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + pix_value_ptr(x, y++, 1)->set(*colors++); + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + pixel_type* p = pix_value_ptr(x, y, len); + if (covers) + { + do + { + copy_or_blend_pix(p, *colors++, *covers++); + p = p->next(); + } + while (--len); + } + else + { + if (cover == cover_mask) + { + do + { + copy_or_blend_pix(p, *colors++); + p = p->next(); + } + while (--len); + } + else + { + do + { + copy_or_blend_pix(p, *colors++, cover); + p = p->next(); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + if (covers) + { + do + { + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, *covers++); + } + while (--len); + } + else + { + if (cover == cover_mask) + { + do + { + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++); + } + while (--len); + } + else + { + do + { + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, cover); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + template void for_each_pixel(Function f) + { + for (unsigned y = 0; y < height(); ++y) + { + row_data r = m_rbuf->row(y); + if (r.ptr) + { + unsigned len = r.x2 - r.x1 + 1; + pixel_type* p = pix_value_ptr(r.x1, y, len); + do + { + f(p->c); + p = p->next(); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + void premultiply() + { + for_each_pixel(multiplier_rgba::premultiply); + } + + //-------------------------------------------------------------------- + void demultiply() + { + for_each_pixel(multiplier_rgba::demultiply); + } + + //-------------------------------------------------------------------- + template void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_rgba(g)); + } + + //-------------------------------------------------------------------- + template void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_rgba(g)); + } + + //-------------------------------------------------------------------- + template void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + if (const int8u* p = from.row_ptr(ysrc)) + { + std::memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } + + //-------------------------------------------------------------------- + // Blend from another RGBA surface. + template + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + int srcinc = 1; + int dstinc = 1; + + if (xdst > xsrc) + { + psrc = psrc->advance(len - 1); + pdst = pdst->advance(len - 1); + srcinc = -1; + dstinc = -1; + } + + if (cover == cover_mask) + { + do + { + copy_or_blend_pix(pdst, psrc->get()); + psrc = psrc->advance(srcinc); + pdst = pdst->advance(dstinc); + } + while (--len); + } + else + { + do + { + copy_or_blend_pix(pdst, psrc->get(), cover); + psrc = psrc->advance(srcinc); + pdst = pdst->advance(dstinc); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + // Combine single color with grayscale surface and blend. + template + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + typedef typename SrcPixelFormatRenderer::color_type src_color_type; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + do + { + copy_or_blend_pix(pdst, color, + src_color_type::scale_cover(cover, psrc->c[0])); + psrc = psrc->next(); + pdst = pdst->next(); + } + while (--len); + } + } + + //-------------------------------------------------------------------- + // Blend from color table, using grayscale surface as indexes into table. + // Obviously, this only works for integer value types. + template + void blend_from_lut(const SrcPixelFormatRenderer& from, + const color_type* color_lut, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + if (cover == cover_mask) + { + do + { + copy_or_blend_pix(pdst, color_lut[psrc->c[0]]); + psrc = psrc->next(); + pdst = pdst->next(); + } + while (--len); + } + else + { + do + { + copy_or_blend_pix(pdst, color_lut[psrc->c[0]], cover); + psrc = psrc->next(); + pdst = pdst->next(); + } + while (--len); + } + } + } + + private: + rbuf_type* m_rbuf; + Blender m_blender; + }; + + //================================================pixfmt_custom_blend_rgba + template class pixfmt_custom_blend_rgba + { + public: + typedef pixfmt_rgba_tag pixfmt_category; + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum + { + num_components = 4, + pix_step = 4, + pix_width = sizeof(value_type) * pix_step, + }; + struct pixel_type + { + value_type c[num_components]; + + void set(value_type r, value_type g, value_type b, value_type a) + { + c[order_type::R] = r; + c[order_type::G] = g; + c[order_type::B] = b; + c[order_type::A] = a; + } + + void set(const color_type& color) + { + set(color.r, color.g, color.b, color.a); + } + + void get(value_type& r, value_type& g, value_type& b, value_type& a) const + { + r = c[order_type::R]; + g = c[order_type::G]; + b = c[order_type::B]; + a = c[order_type::A]; + } + + color_type get() const + { + return color_type( + c[order_type::R], + c[order_type::G], + c[order_type::B], + c[order_type::A]); + } + + pixel_type* next() + { + return (pixel_type*)(c + pix_step); + } + + const pixel_type* next() const + { + return (const pixel_type*)(c + pix_step); + } + + pixel_type* advance(int n) + { + return (pixel_type*)(c + n * pix_step); + } + + const pixel_type* advance(int n) const + { + return (const pixel_type*)(c + n * pix_step); + } + }; + + + private: + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover = cover_full) + { + m_blender.blend_pix(m_comp_op, p->c, c.r, c.g, c.b, c.a, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover = cover_full) + { + if (!c.is_transparent()) + { + if (c.is_opaque() && cover == cover_mask) + { + p->set(c.r, c.g, c.b, c.a); + } + else + { + blend_pix(p, c, cover); + } + } + } + + public: + //-------------------------------------------------------------------- + pixfmt_custom_blend_rgba() : m_rbuf(0), m_comp_op(3) {} + explicit pixfmt_custom_blend_rgba(rbuf_type& rb, unsigned comp_op=3) : + m_rbuf(&rb), + m_comp_op(comp_op) + {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + + //-------------------------------------------------------------------- + template + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) + { + rect_i r(x1, y1, x2, y2); + if (r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + { + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; + } + return false; + } + + //-------------------------------------------------------------------- + void comp_op(unsigned op) { m_comp_op = op; } + unsigned comp_op() const { return m_comp_op; } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step); + } + + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step); + } + + // Return pointer to pixel value, forcing row to be allocated. + AGG_INLINE pixel_type* pix_value_ptr(int x, int y, unsigned len) + { + return (pixel_type*)(m_rbuf->row_ptr(x, y, len) + sizeof(value_type) * (x * pix_step)); + } + + // Return pointer to pixel value, or null if row not allocated. + AGG_INLINE const pixel_type* pix_value_ptr(int x, int y) const + { + int8u* p = m_rbuf->row_ptr(y); + return p ? (pixel_type*)(p + sizeof(value_type) * (x * pix_step)) : 0; + } + + // Get pixel pointer from raw buffer pointer. + AGG_INLINE static pixel_type* pix_value_ptr(void* p) + { + return (pixel_type*)p; + } + + // Get pixel pointer from raw buffer pointer. + AGG_INLINE static const pixel_type* pix_value_ptr(const void* p) + { + return (const pixel_type*)p; + } + + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { + ((pixel_type*)p)->set(c); + } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + if (const pixel_type* p = pix_value_ptr(x, y)) + { + return p->get(); + } + return color_type::no_color(); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_pixel(int x, int y, const color_type& c) + { + make_pix(pix_value_ptr(x, y, 1), c); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + blend_pix(pix_value_ptr(x, y, 1), c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type v; + v.set(c); + pixel_type* p = pix_value_ptr(x, y, len); + do + { + *p = v; + p = p->next(); + } + while (--len); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type v; + v.set(c); + do + { + *pix_value_ptr(x, y++, 1) = v; + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, unsigned len, + const color_type& c, int8u cover) + { + + pixel_type* p = pix_value_ptr(x, y, len); + do + { + blend_pix(p, c, cover); + p = p->next(); + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, unsigned len, + const color_type& c, int8u cover) + { + do + { + blend_pix(pix_value_ptr(x, y++, 1), c, cover); + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, unsigned len, + const color_type& c, const int8u* covers) + { + pixel_type* p = pix_value_ptr(x, y, len); + + do + { + blend_pix(p, c, *covers++); + p = p->next(); + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, unsigned len, + const color_type& c, const int8u* covers) + { + do + { + blend_pix(pix_value_ptr(x, y++, 1), c, *covers++); + } + while (--len); + } + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + pixel_type* p = pix_value_ptr(x, y, len); + + do + { + p->set(*colors++); + p = p->next(); + } + while (--len); + } + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + pix_value_ptr(x, y++, 1)->set(*colors++); + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + pixel_type* p = pix_value_ptr(x, y, len); + + do + { + blend_pix(p, *colors++, covers ? *covers++ : cover); + p = p->next(); + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + do + { + blend_pix(pix_value_ptr(x, y++, 1), *colors++, covers ? *covers++ : cover); + } + while (--len); + + } + + //-------------------------------------------------------------------- + template void for_each_pixel(Function f) + { + unsigned y; + for (y = 0; y < height(); ++y) + { + row_data r = m_rbuf->row(y); + if (r.ptr) + { + unsigned len = r.x2 - r.x1 + 1; + pixel_type* p = pix_value_ptr(r.x1, y, len); + do + { + f(p->c); + p = p->next(); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + void premultiply() + { + for_each_pixel(multiplier_rgba::premultiply); + } + + //-------------------------------------------------------------------- + void demultiply() + { + for_each_pixel(multiplier_rgba::demultiply); + } + + //-------------------------------------------------------------------- + template void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_rgba(g)); + } + + //-------------------------------------------------------------------- + template void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_rgba(g)); + } + + //-------------------------------------------------------------------- + template void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + if (const int8u* p = from.row_ptr(ysrc)) + { + std::memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } + + //-------------------------------------------------------------------- + // Blend from another RGBA surface. + template + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + int srcinc = 1; + int dstinc = 1; + + if (xdst > xsrc) + { + psrc = psrc->advance(len - 1); + pdst = pdst->advance(len - 1); + srcinc = -1; + dstinc = -1; + } + + do + { + blend_pix(pdst, psrc->get(), cover); + psrc = psrc->advance(srcinc); + pdst = pdst->advance(dstinc); + } + while (--len); + } + } + + //-------------------------------------------------------------------- + // Blend from single color, using grayscale surface as alpha channel. + template + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + typedef typename SrcPixelFormatRenderer::color_type src_color_type; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + do + { + blend_pix(pdst, color, + src_color_type::scale_cover(cover, psrc->c[0])); + psrc = psrc->next(); + pdst = pdst->next(); + } + while (--len); + } + } + + //-------------------------------------------------------------------- + // Blend from color table, using grayscale surface as indexes into table. + // Obviously, this only works for integer value types. + template + void blend_from_lut(const SrcPixelFormatRenderer& from, + const color_type* color_lut, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + do + { + blend_pix(pdst, color_lut[psrc->c[0]], cover); + psrc = psrc->next(); + pdst = pdst->next(); + } + while (--len); + } + } + + private: + rbuf_type* m_rbuf; + Blender m_blender; + unsigned m_comp_op; + }; + + + //----------------------------------------------------------------------- + typedef blender_rgba blender_rgba32; + typedef blender_rgba blender_argb32; + typedef blender_rgba blender_abgr32; + typedef blender_rgba blender_bgra32; + + typedef blender_rgba blender_srgba32; + typedef blender_rgba blender_sargb32; + typedef blender_rgba blender_sabgr32; + typedef blender_rgba blender_sbgra32; + + typedef blender_rgba_pre blender_rgba32_pre; + typedef blender_rgba_pre blender_argb32_pre; + typedef blender_rgba_pre blender_abgr32_pre; + typedef blender_rgba_pre blender_bgra32_pre; + + typedef blender_rgba_pre blender_srgba32_pre; + typedef blender_rgba_pre blender_sargb32_pre; + typedef blender_rgba_pre blender_sabgr32_pre; + typedef blender_rgba_pre blender_sbgra32_pre; + + typedef blender_rgba_plain blender_rgba32_plain; + typedef blender_rgba_plain blender_argb32_plain; + typedef blender_rgba_plain blender_abgr32_plain; + typedef blender_rgba_plain blender_bgra32_plain; + + typedef blender_rgba_plain blender_srgba32_plain; + typedef blender_rgba_plain blender_sargb32_plain; + typedef blender_rgba_plain blender_sabgr32_plain; + typedef blender_rgba_plain blender_sbgra32_plain; + + typedef blender_rgba blender_rgba64; + typedef blender_rgba blender_argb64; + typedef blender_rgba blender_abgr64; + typedef blender_rgba blender_bgra64; + + typedef blender_rgba_pre blender_rgba64_pre; + typedef blender_rgba_pre blender_argb64_pre; + typedef blender_rgba_pre blender_abgr64_pre; + typedef blender_rgba_pre blender_bgra64_pre; + + typedef blender_rgba_plain blender_rgba64_plain; + typedef blender_rgba_plain blender_argb64_plain; + typedef blender_rgba_plain blender_abgr64_plain; + typedef blender_rgba_plain blender_bgra64_plain; + + typedef blender_rgba blender_rgba128; + typedef blender_rgba blender_argb128; + typedef blender_rgba blender_abgr128; + typedef blender_rgba blender_bgra128; + + typedef blender_rgba_pre blender_rgba128_pre; + typedef blender_rgba_pre blender_argb128_pre; + typedef blender_rgba_pre blender_abgr128_pre; + typedef blender_rgba_pre blender_bgra128_pre; + + typedef blender_rgba_plain blender_rgba128_plain; + typedef blender_rgba_plain blender_argb128_plain; + typedef blender_rgba_plain blender_abgr128_plain; + typedef blender_rgba_plain blender_bgra128_plain; + + + //----------------------------------------------------------------------- + typedef pixfmt_alpha_blend_rgba pixfmt_rgba32; + typedef pixfmt_alpha_blend_rgba pixfmt_argb32; + typedef pixfmt_alpha_blend_rgba pixfmt_abgr32; + typedef pixfmt_alpha_blend_rgba pixfmt_bgra32; + + typedef pixfmt_alpha_blend_rgba pixfmt_srgba32; + typedef pixfmt_alpha_blend_rgba pixfmt_sargb32; + typedef pixfmt_alpha_blend_rgba pixfmt_sabgr32; + typedef pixfmt_alpha_blend_rgba pixfmt_sbgra32; + + typedef pixfmt_alpha_blend_rgba pixfmt_rgba32_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_argb32_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_abgr32_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_bgra32_pre; + + typedef pixfmt_alpha_blend_rgba pixfmt_srgba32_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_sargb32_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_sabgr32_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_sbgra32_pre; + + typedef pixfmt_alpha_blend_rgba pixfmt_rgba32_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_argb32_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_abgr32_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_bgra32_plain; + + typedef pixfmt_alpha_blend_rgba pixfmt_srgba32_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_sargb32_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_sabgr32_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_sbgra32_plain; + + typedef pixfmt_alpha_blend_rgba pixfmt_rgba64; + typedef pixfmt_alpha_blend_rgba pixfmt_argb64; + typedef pixfmt_alpha_blend_rgba pixfmt_abgr64; + typedef pixfmt_alpha_blend_rgba pixfmt_bgra64; + + typedef pixfmt_alpha_blend_rgba pixfmt_rgba64_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_argb64_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_abgr64_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_bgra64_pre; + + typedef pixfmt_alpha_blend_rgba pixfmt_rgba64_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_argb64_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_abgr64_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_bgra64_plain; + + typedef pixfmt_alpha_blend_rgba pixfmt_rgba128; + typedef pixfmt_alpha_blend_rgba pixfmt_argb128; + typedef pixfmt_alpha_blend_rgba pixfmt_abgr128; + typedef pixfmt_alpha_blend_rgba pixfmt_bgra128; + + typedef pixfmt_alpha_blend_rgba pixfmt_rgba128_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_argb128_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_abgr128_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_bgra128_pre; + + typedef pixfmt_alpha_blend_rgba pixfmt_rgba128_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_argb128_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_abgr128_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_bgra128_plain; + +} + +#endif + diff --git a/agg/include/agg_pixfmt_transposer.h b/agg/include/agg_pixfmt_transposer.h new file mode 100644 index 0000000..64738b6 --- /dev/null +++ b/agg/include/agg_pixfmt_transposer.h @@ -0,0 +1,157 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_PIXFMT_TRANSPOSER_INCLUDED +#define AGG_PIXFMT_TRANSPOSER_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //=======================================================pixfmt_transposer + template class pixfmt_transposer + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::row_data row_data; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + + //-------------------------------------------------------------------- + pixfmt_transposer() : m_pixf(0) {} + explicit pixfmt_transposer(pixfmt_type& pixf) : m_pixf(&pixf) {} + void attach(pixfmt_type& pixf) { m_pixf = &pixf; } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_pixf->height(); } + AGG_INLINE unsigned height() const { return m_pixf->width(); } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + return m_pixf->pixel(y, x); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_pixel(int x, int y, const color_type& c) + { + m_pixf->copy_pixel(y, x, c); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pixel(int x, int y, + const color_type& c, + int8u cover) + { + m_pixf->blend_pixel(y, x, c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + m_pixf->copy_vline(y, x, len, c); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + m_pixf->copy_hline(y, x, len, c); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_hline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + m_pixf->blend_vline(y, x, len, c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + m_pixf->blend_hline(y, x, len, c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + m_pixf->blend_solid_vspan(y, x, len, c, covers); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + m_pixf->blend_solid_hspan(y, x, len, c, covers); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + m_pixf->copy_color_vspan(y, x, len, colors); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + m_pixf->copy_color_hspan(y, x, len, colors); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + m_pixf->blend_color_vspan(y, x, len, colors, covers, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + m_pixf->blend_color_hspan(y, x, len, colors, covers, cover); + } + + private: + pixfmt_type* m_pixf; + }; +} + +#endif + + diff --git a/agg/include/agg_rasterizer_cells_aa.h b/agg/include/agg_rasterizer_cells_aa.h new file mode 100644 index 0000000..4dd905f --- /dev/null +++ b/agg/include/agg_rasterizer_cells_aa.h @@ -0,0 +1,742 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// +// The author gratefully acknowleges the support of David Turner, +// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType +// libray - in producing this work. See http://www.freetype.org for details. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- +#ifndef AGG_RASTERIZER_CELLS_AA_INCLUDED +#define AGG_RASTERIZER_CELLS_AA_INCLUDED + +#include +#include +#include +#include "agg_math.h" +#include "agg_array.h" + + +namespace agg +{ + + //-----------------------------------------------------rasterizer_cells_aa + // An internal class that implements the main rasterization algorithm. + // Used in the rasterizer. Should not be used direcly. + template class rasterizer_cells_aa + { + enum cell_block_scale_e + { + cell_block_shift = 12, + cell_block_size = 1 << cell_block_shift, + cell_block_mask = cell_block_size - 1, + cell_block_pool = 256 + }; + + struct sorted_y + { + unsigned start; + unsigned num; + }; + + public: + typedef Cell cell_type; + typedef rasterizer_cells_aa self_type; + + ~rasterizer_cells_aa(); + rasterizer_cells_aa(unsigned cell_block_limit=1024); + + void reset(); + void style(const cell_type& style_cell); + void line(int x1, int y1, int x2, int y2); + + int min_x() const { return m_min_x; } + int min_y() const { return m_min_y; } + int max_x() const { return m_max_x; } + int max_y() const { return m_max_y; } + + void sort_cells(); + + unsigned total_cells() const + { + return m_num_cells; + } + + unsigned scanline_num_cells(unsigned y) const + { + return m_sorted_y[y - m_min_y].num; + } + + const cell_type* const* scanline_cells(unsigned y) const + { + return m_sorted_cells.data() + m_sorted_y[y - m_min_y].start; + } + + bool sorted() const { return m_sorted; } + + private: + rasterizer_cells_aa(const self_type&); + const self_type& operator = (const self_type&); + + void set_curr_cell(int x, int y); + void add_curr_cell(); + void render_hline(int ey, int x1, int y1, int x2, int y2); + void allocate_block(); + + private: + unsigned m_num_blocks; + unsigned m_max_blocks; + unsigned m_curr_block; + unsigned m_num_cells; + unsigned m_cell_block_limit; + cell_type** m_cells; + cell_type* m_curr_cell_ptr; + pod_vector m_sorted_cells; + pod_vector m_sorted_y; + cell_type m_curr_cell; + cell_type m_style_cell; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + bool m_sorted; + }; + + + + + //------------------------------------------------------------------------ + template + rasterizer_cells_aa::~rasterizer_cells_aa() + { + if(m_num_blocks) + { + cell_type** ptr = m_cells + m_num_blocks - 1; + while(m_num_blocks--) + { + pod_allocator::deallocate(*ptr, cell_block_size); + ptr--; + } + pod_allocator::deallocate(m_cells, m_max_blocks); + } + } + + //------------------------------------------------------------------------ + template + rasterizer_cells_aa::rasterizer_cells_aa(unsigned cell_block_limit) : + m_num_blocks(0), + m_max_blocks(0), + m_curr_block(0), + m_num_cells(0), + m_cell_block_limit(cell_block_limit), + m_cells(0), + m_curr_cell_ptr(0), + m_sorted_cells(), + m_sorted_y(), + m_min_x(std::numeric_limits::max()), + m_min_y(std::numeric_limits::max()), + m_max_x(std::numeric_limits::min()), + m_max_y(std::numeric_limits::min()), + m_sorted(false) + { + m_style_cell.initial(); + m_curr_cell.initial(); + } + + //------------------------------------------------------------------------ + template + void rasterizer_cells_aa::reset() + { + m_num_cells = 0; + m_curr_block = 0; + m_curr_cell.initial(); + m_style_cell.initial(); + m_sorted = false; + m_min_x = std::numeric_limits::max(); + m_min_y = std::numeric_limits::max(); + m_max_x = std::numeric_limits::min(); + m_max_y = std::numeric_limits::min(); + } + + //------------------------------------------------------------------------ + template + AGG_INLINE void rasterizer_cells_aa::add_curr_cell() + { + if(m_curr_cell.area | m_curr_cell.cover) + { + if((m_num_cells & cell_block_mask) == 0) + { + if(m_num_blocks >= m_cell_block_limit) return; + allocate_block(); + } + *m_curr_cell_ptr++ = m_curr_cell; + ++m_num_cells; + } + } + + //------------------------------------------------------------------------ + template + AGG_INLINE void rasterizer_cells_aa::set_curr_cell(int x, int y) + { + if(m_curr_cell.not_equal(x, y, m_style_cell)) + { + add_curr_cell(); + m_curr_cell.style(m_style_cell); + m_curr_cell.x = x; + m_curr_cell.y = y; + m_curr_cell.cover = 0; + m_curr_cell.area = 0; + } + } + + //------------------------------------------------------------------------ + template + AGG_INLINE void rasterizer_cells_aa::render_hline(int ey, + int x1, int y1, + int x2, int y2) + { + int ex1 = x1 >> poly_subpixel_shift; + int ex2 = x2 >> poly_subpixel_shift; + int fx1 = x1 & poly_subpixel_mask; + int fx2 = x2 & poly_subpixel_mask; + + int delta, p, first; + long long dx; + int incr, lift, mod, rem; + + //trivial case. Happens often + if(y1 == y2) + { + set_curr_cell(ex2, ey); + return; + } + + //everything is located in a single cell. That is easy! + if(ex1 == ex2) + { + delta = y2 - y1; + m_curr_cell.cover += delta; + m_curr_cell.area += (fx1 + fx2) * delta; + return; + } + + //ok, we'll have to render a run of adjacent cells on the same + //hline... + p = (poly_subpixel_scale - fx1) * (y2 - y1); + first = poly_subpixel_scale; + incr = 1; + + dx = (long long)x2 - (long long)x1; + + if(dx < 0) + { + p = fx1 * (y2 - y1); + first = 0; + incr = -1; + dx = -dx; + } + + delta = (int)(p / dx); + mod = (int)(p % dx); + + if(mod < 0) + { + delta--; + mod += dx; + } + + m_curr_cell.cover += delta; + m_curr_cell.area += (fx1 + first) * delta; + + ex1 += incr; + set_curr_cell(ex1, ey); + y1 += delta; + + if(ex1 != ex2) + { + p = poly_subpixel_scale * (y2 - y1 + delta); + lift = (int)(p / dx); + rem = (int)(p % dx); + + if (rem < 0) + { + lift--; + rem += dx; + } + + mod -= dx; + + while (ex1 != ex2) + { + delta = lift; + mod += rem; + if(mod >= 0) + { + mod -= dx; + delta++; + } + + m_curr_cell.cover += delta; + m_curr_cell.area += poly_subpixel_scale * delta; + y1 += delta; + ex1 += incr; + set_curr_cell(ex1, ey); + } + } + delta = y2 - y1; + m_curr_cell.cover += delta; + m_curr_cell.area += (fx2 + poly_subpixel_scale - first) * delta; + } + + //------------------------------------------------------------------------ + template + AGG_INLINE void rasterizer_cells_aa::style(const cell_type& style_cell) + { + m_style_cell.style(style_cell); + } + + //------------------------------------------------------------------------ + template + void rasterizer_cells_aa::line(int x1, int y1, int x2, int y2) + { + enum dx_limit_e { dx_limit = 16384 << poly_subpixel_shift }; + + long long dx = (long long)x2 - (long long)x1; + + if(dx >= dx_limit || dx <= -dx_limit) + { + int cx = (int)(((long long)x1 + (long long)x2) >> 1); + int cy = (int)(((long long)y1 + (long long)y2) >> 1); + line(x1, y1, cx, cy); + line(cx, cy, x2, y2); + } + + long long dy = (long long)y2 - (long long)y1; + int ex1 = x1 >> poly_subpixel_shift; + int ex2 = x2 >> poly_subpixel_shift; + int ey1 = y1 >> poly_subpixel_shift; + int ey2 = y2 >> poly_subpixel_shift; + int fy1 = y1 & poly_subpixel_mask; + int fy2 = y2 & poly_subpixel_mask; + + int x_from, x_to; + int rem, mod, lift, delta, first, incr; + long long p; + + if(ex1 < m_min_x) m_min_x = ex1; + if(ex1 > m_max_x) m_max_x = ex1; + if(ey1 < m_min_y) m_min_y = ey1; + if(ey1 > m_max_y) m_max_y = ey1; + if(ex2 < m_min_x) m_min_x = ex2; + if(ex2 > m_max_x) m_max_x = ex2; + if(ey2 < m_min_y) m_min_y = ey2; + if(ey2 > m_max_y) m_max_y = ey2; + + set_curr_cell(ex1, ey1); + + //everything is on a single hline + if(ey1 == ey2) + { + render_hline(ey1, x1, fy1, x2, fy2); + return; + } + + //Vertical line - we have to calculate start and end cells, + //and then - the common values of the area and coverage for + //all cells of the line. We know exactly there's only one + //cell, so, we don't have to call render_hline(). + incr = 1; + if(dx == 0) + { + int ex = x1 >> poly_subpixel_shift; + int two_fx = (x1 - (ex << poly_subpixel_shift)) << 1; + int area; + + first = poly_subpixel_scale; + if(dy < 0) + { + first = 0; + incr = -1; + } + + x_from = x1; + + //render_hline(ey1, x_from, fy1, x_from, first); + delta = first - fy1; + m_curr_cell.cover += delta; + m_curr_cell.area += two_fx * delta; + + ey1 += incr; + set_curr_cell(ex, ey1); + + delta = first + first - poly_subpixel_scale; + area = two_fx * delta; + while(ey1 != ey2) + { + //render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, first); + m_curr_cell.cover = delta; + m_curr_cell.area = area; + ey1 += incr; + set_curr_cell(ex, ey1); + } + //render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, fy2); + delta = fy2 - poly_subpixel_scale + first; + m_curr_cell.cover += delta; + m_curr_cell.area += two_fx * delta; + return; + } + + //ok, we have to render several hlines + p = (poly_subpixel_scale - fy1) * dx; + first = poly_subpixel_scale; + + if(dy < 0) + { + p = fy1 * dx; + first = 0; + incr = -1; + dy = -dy; + } + + delta = (int)(p / dy); + mod = (int)(p % dy); + + if(mod < 0) + { + delta--; + mod += dy; + } + + x_from = x1 + delta; + render_hline(ey1, x1, fy1, x_from, first); + + ey1 += incr; + set_curr_cell(x_from >> poly_subpixel_shift, ey1); + + if(ey1 != ey2) + { + p = poly_subpixel_scale * dx; + lift = (int)(p / dy); + rem = (int)(p % dy); + + if(rem < 0) + { + lift--; + rem += dy; + } + mod -= dy; + + while(ey1 != ey2) + { + delta = lift; + mod += rem; + if (mod >= 0) + { + mod -= dy; + delta++; + } + + x_to = x_from + delta; + render_hline(ey1, x_from, poly_subpixel_scale - first, x_to, first); + x_from = x_to; + + ey1 += incr; + set_curr_cell(x_from >> poly_subpixel_shift, ey1); + } + } + render_hline(ey1, x_from, poly_subpixel_scale - first, x2, fy2); + } + + //------------------------------------------------------------------------ + template + void rasterizer_cells_aa::allocate_block() + { + if(m_curr_block >= m_num_blocks) + { + if(m_num_blocks >= m_max_blocks) + { + cell_type** new_cells = + pod_allocator::allocate(m_max_blocks + + cell_block_pool); + + if(m_cells) + { + std::memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_type*)); + pod_allocator::deallocate(m_cells, m_max_blocks); + } + m_cells = new_cells; + m_max_blocks += cell_block_pool; + } + + m_cells[m_num_blocks++] = + pod_allocator::allocate(cell_block_size); + + } + m_curr_cell_ptr = m_cells[m_curr_block++]; + } + + + + //------------------------------------------------------------------------ + template static AGG_INLINE void swap_cells(T* a, T* b) + { + T temp = *a; + *a = *b; + *b = temp; + } + + + //------------------------------------------------------------------------ + enum + { + qsort_threshold = 9 + }; + + + //------------------------------------------------------------------------ + template + void qsort_cells(Cell** start, unsigned num) + { + Cell** stack[80]; + Cell*** top; + Cell** limit; + Cell** base; + + limit = start + num; + base = start; + top = stack; + + for (;;) + { + int len = int(limit - base); + + Cell** i; + Cell** j; + Cell** pivot; + + if(len > qsort_threshold) + { + // we use base + len/2 as the pivot + pivot = base + len / 2; + swap_cells(base, pivot); + + i = base + 1; + j = limit - 1; + + // now ensure that *i <= *base <= *j + if((*j)->x < (*i)->x) + { + swap_cells(i, j); + } + + if((*base)->x < (*i)->x) + { + swap_cells(base, i); + } + + if((*j)->x < (*base)->x) + { + swap_cells(base, j); + } + + for(;;) + { + int x = (*base)->x; + do i++; while( (*i)->x < x ); + do j--; while( x < (*j)->x ); + + if(i > j) + { + break; + } + + swap_cells(i, j); + } + + swap_cells(base, j); + + // now, push the largest sub-array + if(j - base > limit - i) + { + top[0] = base; + top[1] = j; + base = i; + } + else + { + top[0] = i; + top[1] = limit; + limit = j; + } + top += 2; + } + else + { + // the sub-array is small, perform insertion sort + j = base; + i = j + 1; + + for(; i < limit; j = i, i++) + { + for(; j[1]->x < (*j)->x; j--) + { + swap_cells(j + 1, j); + if (j == base) + { + break; + } + } + } + + if(top > stack) + { + top -= 2; + base = top[0]; + limit = top[1]; + } + else + { + break; + } + } + } + } + + + //------------------------------------------------------------------------ + template + void rasterizer_cells_aa::sort_cells() + { + if(m_sorted) return; //Perform sort only the first time. + + add_curr_cell(); + m_curr_cell.x = std::numeric_limits::max(); + m_curr_cell.y = std::numeric_limits::max(); + m_curr_cell.cover = 0; + m_curr_cell.area = 0; + + if(m_num_cells == 0) return; + +// DBG: Check to see if min/max works well. +//for(unsigned nc = 0; nc < m_num_cells; nc++) +//{ +// cell_type* cell = m_cells[nc >> cell_block_shift] + (nc & cell_block_mask); +// if(cell->x < m_min_x || +// cell->y < m_min_y || +// cell->x > m_max_x || +// cell->y > m_max_y) +// { +// cell = cell; // Breakpoint here +// } +//} + // Allocate the array of cell pointers + m_sorted_cells.allocate(m_num_cells, 16); + + // Allocate and zero the Y array + m_sorted_y.allocate(m_max_y - m_min_y + 1, 16); + m_sorted_y.zero(); + + // Create the Y-histogram (count the numbers of cells for each Y) + cell_type** block_ptr = m_cells; + cell_type* cell_ptr; + unsigned nb = m_num_cells; + unsigned i; + while(nb) + { + cell_ptr = *block_ptr++; + i = (nb > cell_block_size) ? unsigned(cell_block_size) : nb; + nb -= i; + while(i--) + { + m_sorted_y[cell_ptr->y - m_min_y].start++; + ++cell_ptr; + } + } + + // Convert the Y-histogram into the array of starting indexes + unsigned start = 0; + for(i = 0; i < m_sorted_y.size(); i++) + { + unsigned v = m_sorted_y[i].start; + m_sorted_y[i].start = start; + start += v; + } + + // Fill the cell pointer array sorted by Y + block_ptr = m_cells; + nb = m_num_cells; + while(nb) + { + cell_ptr = *block_ptr++; + i = (nb > cell_block_size) ? unsigned(cell_block_size) : nb; + nb -= i; + while(i--) + { + sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y]; + m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr; + ++curr_y.num; + ++cell_ptr; + } + } + + // Finally arrange the X-arrays + for(i = 0; i < m_sorted_y.size(); i++) + { + const sorted_y& curr_y = m_sorted_y[i]; + if(curr_y.num) + { + qsort_cells(m_sorted_cells.data() + curr_y.start, curr_y.num); + } + } + m_sorted = true; + } + + + + //------------------------------------------------------scanline_hit_test + class scanline_hit_test + { + public: + scanline_hit_test(int x) : m_x(x), m_hit(false) {} + + void reset_spans() {} + void finalize(int) {} + void add_cell(int x, int) + { + if(m_x == x) m_hit = true; + } + void add_span(int x, int len, int) + { + if(m_x >= x && m_x < x+len) m_hit = true; + } + unsigned num_spans() const { return 1; } + bool hit() const { return m_hit; } + + private: + int m_x; + bool m_hit; + }; + + +} + +#endif diff --git a/agg/include/agg_rasterizer_compound_aa.h b/agg/include/agg_rasterizer_compound_aa.h new file mode 100644 index 0000000..72d811b --- /dev/null +++ b/agg/include/agg_rasterizer_compound_aa.h @@ -0,0 +1,665 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.3 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// +// The author gratefully acknowleges the support of David Turner, +// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType +// libray - in producing this work. See http://www.freetype.org for details. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- +#ifndef AGG_RASTERIZER_COMPOUND_AA_INCLUDED +#define AGG_RASTERIZER_COMPOUND_AA_INCLUDED + +#include +#include "agg_rasterizer_cells_aa.h" +#include "agg_rasterizer_sl_clip.h" + +namespace agg +{ + + //-----------------------------------------------------------cell_style_aa + // A pixel cell. There're no constructors defined and it was done + // intentionally in order to avoid extra overhead when allocating an + // array of cells. + struct cell_style_aa + { + int x; + int y; + int cover; + int area; + int16 left, right; + + void initial() + { + x = std::numeric_limits::max(); + y = std::numeric_limits::max(); + cover = 0; + area = 0; + left = -1; + right = -1; + } + + void style(const cell_style_aa& c) + { + left = c.left; + right = c.right; + } + + int not_equal(int ex, int ey, const cell_style_aa& c) const + { + return ((unsigned)ex - (unsigned)x) | ((unsigned)ey - (unsigned)y) | + ((unsigned)left - (unsigned)c.left) | ((unsigned)right - (unsigned)c.right); + } + }; + + + //===========================================================layer_order_e + enum layer_order_e + { + layer_unsorted, //------layer_unsorted + layer_direct, //------layer_direct + layer_inverse //------layer_inverse + }; + + + //==================================================rasterizer_compound_aa + template class rasterizer_compound_aa + { + struct style_info + { + unsigned start_cell; + unsigned num_cells; + int last_x; + }; + + struct cell_info + { + int x, area, cover; + }; + + public: + typedef Clip clip_type; + typedef typename Clip::conv_type conv_type; + typedef typename Clip::coord_type coord_type; + + enum aa_scale_e + { + aa_shift = 8, + aa_scale = 1 << aa_shift, + aa_mask = aa_scale - 1, + aa_scale2 = aa_scale * 2, + aa_mask2 = aa_scale2 - 1 + }; + + //-------------------------------------------------------------------- + rasterizer_compound_aa() : + m_outline(), + m_clipper(), + m_filling_rule(fill_non_zero), + m_layer_order(layer_direct), + m_styles(), // Active Styles + m_ast(), // Active Style Table (unique values) + m_asm(), // Active Style Mask + m_cells(), + m_cover_buf(), + m_min_style(std::numeric_limits::max()), + m_max_style(std::numeric_limits::min()), + m_start_x(0), + m_start_y(0), + m_scan_y(std::numeric_limits::max()), + m_sl_start(0), + m_sl_len(0) + {} + + //-------------------------------------------------------------------- + void reset(); + void reset_clipping(); + void clip_box(double x1, double y1, double x2, double y2); + void filling_rule(filling_rule_e filling_rule); + void layer_order(layer_order_e order); + + //-------------------------------------------------------------------- + void styles(int left, int right); + void move_to(int x, int y); + void line_to(int x, int y); + void move_to_d(double x, double y); + void line_to_d(double x, double y); + void add_vertex(double x, double y, unsigned cmd); + + void edge(int x1, int y1, int x2, int y2); + void edge_d(double x1, double y1, double x2, double y2); + + //------------------------------------------------------------------- + template + void add_path(VertexSource& vs, unsigned path_id=0) + { + double x; + double y; + + unsigned cmd; + vs.rewind(path_id); + if(m_outline.sorted()) reset(); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + add_vertex(x, y, cmd); + } + } + + + //-------------------------------------------------------------------- + int min_x() const { return m_outline.min_x(); } + int min_y() const { return m_outline.min_y(); } + int max_x() const { return m_outline.max_x(); } + int max_y() const { return m_outline.max_y(); } + int min_style() const { return m_min_style; } + int max_style() const { return m_max_style; } + + //-------------------------------------------------------------------- + void sort(); + bool rewind_scanlines(); + unsigned sweep_styles(); + int scanline_start() const { return m_sl_start; } + unsigned scanline_length() const { return m_sl_len; } + unsigned style(unsigned style_idx) const; + + cover_type* allocate_cover_buffer(unsigned len); + + //-------------------------------------------------------------------- + bool navigate_scanline(int y); + bool hit_test(int tx, int ty); + + //-------------------------------------------------------------------- + AGG_INLINE unsigned calculate_alpha(int area) const + { + int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift); + if(cover < 0) cover = -cover; + if(m_filling_rule == fill_even_odd) + { + cover &= aa_mask2; + if(cover > aa_scale) + { + cover = aa_scale2 - cover; + } + } + if(cover > aa_mask) cover = aa_mask; + return cover; + } + + //-------------------------------------------------------------------- + // Sweeps one scanline with one style index. The style ID can be + // determined by calling style(). + template bool sweep_scanline(Scanline& sl, int style_idx) + { + int scan_y = m_scan_y - 1; + if(scan_y > m_outline.max_y()) return false; + + sl.reset_spans(); + + if(style_idx < 0) + { + style_idx = 0; + } + else + { + style_idx++; + } + + const style_info& st = m_styles[m_ast[style_idx]]; + + unsigned num_cells = st.num_cells; + cell_info* cell = &m_cells[st.start_cell]; + + int cover = 0; + while(num_cells--) + { + unsigned alpha; + int x = cell->x; + int area = cell->area; + + cover += cell->cover; + + ++cell; + + if(area) + { + alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area); + sl.add_cell(x, alpha); + x++; + } + + if(num_cells && cell->x > x) + { + alpha = calculate_alpha(cover << (poly_subpixel_shift + 1)); + if(alpha) + { + sl.add_span(x, cell->x - x, alpha); + } + } + } + + if(sl.num_spans() == 0) return false; + sl.finalize(scan_y); + return true; + } + + private: + void add_style(int style_id); + + //-------------------------------------------------------------------- + // Disable copying + rasterizer_compound_aa(const rasterizer_compound_aa&); + const rasterizer_compound_aa& + operator = (const rasterizer_compound_aa&); + + private: + rasterizer_cells_aa m_outline; + clip_type m_clipper; + filling_rule_e m_filling_rule; + layer_order_e m_layer_order; + pod_vector m_styles; // Active Styles + pod_vector m_ast; // Active Style Table (unique values) + pod_vector m_asm; // Active Style Mask + pod_vector m_cells; + pod_vector m_cover_buf; + + int m_min_style; + int m_max_style; + coord_type m_start_x; + coord_type m_start_y; + int m_scan_y; + int m_sl_start; + unsigned m_sl_len; + }; + + + + + + + + + + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::reset() + { + m_outline.reset(); + m_min_style = std::numeric_limits::max(); + m_max_style = std::numeric_limits::min(); + m_scan_y = std::numeric_limits::max(); + m_sl_start = 0; + m_sl_len = 0; + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::filling_rule(filling_rule_e filling_rule) + { + m_filling_rule = filling_rule; + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::layer_order(layer_order_e order) + { + m_layer_order = order; + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::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 + void rasterizer_compound_aa::reset_clipping() + { + reset(); + m_clipper.reset_clipping(); + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::styles(int left, int right) + { + cell_style_aa cell; + cell.initial(); + cell.left = (int16)left; + cell.right = (int16)right; + m_outline.style(cell); + if(left >= 0 && left < m_min_style) m_min_style = left; + if(left >= 0 && left > m_max_style) m_max_style = left; + if(right >= 0 && right < m_min_style) m_min_style = right; + if(right >= 0 && right > m_max_style) m_max_style = right; + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::move_to(int x, int y) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(m_start_x = conv_type::downscale(x), + m_start_y = conv_type::downscale(y)); + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::line_to(int x, int y) + { + m_clipper.line_to(m_outline, + conv_type::downscale(x), + conv_type::downscale(y)); + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::move_to_d(double x, double y) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(m_start_x = conv_type::upscale(x), + m_start_y = conv_type::upscale(y)); + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::line_to_d(double x, double y) + { + m_clipper.line_to(m_outline, + conv_type::upscale(x), + conv_type::upscale(y)); + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::add_vertex(double x, double y, unsigned cmd) + { + if(is_move_to(cmd)) + { + move_to_d(x, y); + } + else + if(is_vertex(cmd)) + { + line_to_d(x, y); + } + else + if(is_close(cmd)) + { + m_clipper.line_to(m_outline, m_start_x, m_start_y); + } + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::edge(int x1, int y1, int x2, int y2) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1)); + m_clipper.line_to(m_outline, + conv_type::downscale(x2), + conv_type::downscale(y2)); + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::edge_d(double x1, double y1, + double x2, double y2) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1)); + m_clipper.line_to(m_outline, + conv_type::upscale(x2), + conv_type::upscale(y2)); + } + + //------------------------------------------------------------------------ + template + AGG_INLINE void rasterizer_compound_aa::sort() + { + m_outline.sort_cells(); + } + + //------------------------------------------------------------------------ + template + AGG_INLINE bool rasterizer_compound_aa::rewind_scanlines() + { + m_outline.sort_cells(); + if(m_outline.total_cells() == 0) + { + return false; + } + if(m_max_style < m_min_style) + { + return false; + } + m_scan_y = m_outline.min_y(); + m_styles.allocate(m_max_style - m_min_style + 2, 128); + return true; + } + + //------------------------------------------------------------------------ + template + AGG_INLINE void rasterizer_compound_aa::add_style(int style_id) + { + if(style_id < 0) style_id = 0; + else style_id -= m_min_style - 1; + + unsigned nbyte = style_id >> 3; + unsigned mask = 1 << (style_id & 7); + + style_info* style = &m_styles[style_id]; + if((m_asm[nbyte] & mask) == 0) + { + m_ast.add(style_id); + m_asm[nbyte] |= mask; + style->start_cell = 0; + style->num_cells = 0; + style->last_x = std::numeric_limits::min(); + } + ++style->start_cell; + } + + //------------------------------------------------------------------------ + // Returns the number of styles + template + unsigned rasterizer_compound_aa::sweep_styles() + { + for(;;) + { + if(m_scan_y > m_outline.max_y()) return 0; + unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); + const cell_style_aa* const* cells = m_outline.scanline_cells(m_scan_y); + unsigned num_styles = m_max_style - m_min_style + 2; + const cell_style_aa* curr_cell; + unsigned style_id; + style_info* style; + cell_info* cell; + + m_cells.allocate(num_cells * 2, 256); // Each cell can have two styles + m_ast.capacity(num_styles, 64); + m_asm.allocate((num_styles + 7) >> 3, 8); + m_asm.zero(); + + if(num_cells) + { + // Pre-add zero (for no-fill style, that is, -1). + // We need that to ensure that the "-1 style" would go first. + m_asm[0] |= 1; + m_ast.add(0); + style = &m_styles[0]; + style->start_cell = 0; + style->num_cells = 0; + style->last_x = std::numeric_limits::min(); + + m_sl_start = cells[0]->x; + m_sl_len = cells[num_cells-1]->x - m_sl_start + 1; + while(num_cells--) + { + curr_cell = *cells++; + add_style(curr_cell->left); + add_style(curr_cell->right); + } + + // Convert the Y-histogram into the array of starting indexes + unsigned i; + unsigned start_cell = 0; + for(i = 0; i < m_ast.size(); i++) + { + style_info& st = m_styles[m_ast[i]]; + unsigned v = st.start_cell; + st.start_cell = start_cell; + start_cell += v; + } + + cells = m_outline.scanline_cells(m_scan_y); + num_cells = m_outline.scanline_num_cells(m_scan_y); + + while(num_cells--) + { + curr_cell = *cells++; + style_id = (curr_cell->left < 0) ? 0 : + curr_cell->left - m_min_style + 1; + + style = &m_styles[style_id]; + if(curr_cell->x == style->last_x) + { + cell = &m_cells[style->start_cell + style->num_cells - 1]; + cell->area += curr_cell->area; + cell->cover += curr_cell->cover; + } + else + { + cell = &m_cells[style->start_cell + style->num_cells]; + cell->x = curr_cell->x; + cell->area = curr_cell->area; + cell->cover = curr_cell->cover; + style->last_x = curr_cell->x; + style->num_cells++; + } + + style_id = (curr_cell->right < 0) ? 0 : + curr_cell->right - m_min_style + 1; + + style = &m_styles[style_id]; + if(curr_cell->x == style->last_x) + { + cell = &m_cells[style->start_cell + style->num_cells - 1]; + cell->area -= curr_cell->area; + cell->cover -= curr_cell->cover; + } + else + { + cell = &m_cells[style->start_cell + style->num_cells]; + cell->x = curr_cell->x; + cell->area = -curr_cell->area; + cell->cover = -curr_cell->cover; + style->last_x = curr_cell->x; + style->num_cells++; + } + } + } + if(m_ast.size() > 1) break; + ++m_scan_y; + } + ++m_scan_y; + + if(m_layer_order != layer_unsorted) + { + range_adaptor > ra(m_ast, 1, m_ast.size() - 1); + if(m_layer_order == layer_direct) quick_sort(ra, unsigned_greater); + else quick_sort(ra, unsigned_less); + } + + return m_ast.size() - 1; + } + + //------------------------------------------------------------------------ + // Returns style ID depending of the existing style index + template + AGG_INLINE + unsigned rasterizer_compound_aa::style(unsigned style_idx) const + { + return m_ast[style_idx + 1] + m_min_style - 1; + } + + //------------------------------------------------------------------------ + template + AGG_INLINE bool rasterizer_compound_aa::navigate_scanline(int y) + { + m_outline.sort_cells(); + if(m_outline.total_cells() == 0) + { + return false; + } + if(m_max_style < m_min_style) + { + return false; + } + if(y < m_outline.min_y() || y > m_outline.max_y()) + { + return false; + } + m_scan_y = y; + m_styles.allocate(m_max_style - m_min_style + 2, 128); + return true; + } + + //------------------------------------------------------------------------ + template + bool rasterizer_compound_aa::hit_test(int tx, int ty) + { + if(!navigate_scanline(ty)) + { + return false; + } + + unsigned num_styles = sweep_styles(); + if(num_styles <= 0) + { + return false; + } + + scanline_hit_test sl(tx); + sweep_scanline(sl, -1); + return sl.hit(); + } + + //------------------------------------------------------------------------ + template + cover_type* rasterizer_compound_aa::allocate_cover_buffer(unsigned len) + { + m_cover_buf.allocate(len, 256); + return &m_cover_buf[0]; + } + +} + + + +#endif + diff --git a/agg2/include/agg_rasterizer_outline.h b/agg/include/agg_rasterizer_outline.h similarity index 82% rename from agg2/include/agg_rasterizer_outline.h rename to agg/include/agg_rasterizer_outline.h index 2cd187e..65203e3 100644 --- a/agg2/include/agg_rasterizer_outline.h +++ b/agg/include/agg_rasterizer_outline.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -23,19 +23,26 @@ namespace agg template class rasterizer_outline { public: - rasterizer_outline(Renderer& ren) : m_ren(&ren), m_start_x(0), m_start_y(0) - { - } + explicit rasterizer_outline(Renderer& ren) : + m_ren(&ren), + m_start_x(0), + m_start_y(0), + m_vertices(0) + {} + void attach(Renderer& ren) { m_ren = &ren; } + //-------------------------------------------------------------------- void move_to(int x, int y) { + m_vertices = 1; m_ren->move_to(m_start_x = x, m_start_y = y); } //-------------------------------------------------------------------- void line_to(int x, int y) { + ++m_vertices; m_ren->line_to(x, y); } @@ -54,7 +61,11 @@ namespace agg //-------------------------------------------------------------------- void close() { - line_to(m_start_x, m_start_y); + if(m_vertices > 2) + { + line_to(m_start_x, m_start_y); + } + m_vertices = 0; } //-------------------------------------------------------------------- @@ -80,13 +91,13 @@ namespace agg //-------------------------------------------------------------------- template - void add_path(VertexSource& vs, unsigned id=0) + void add_path(VertexSource& vs, unsigned path_id=0) { double x; double y; unsigned cmd; - vs.rewind(id); + vs.rewind(path_id); while(!is_stop(cmd = vs.vertex(&x, &y))) { add_vertex(x, y, cmd); @@ -98,13 +109,13 @@ namespace agg template void render_all_paths(VertexSource& vs, const ColorStorage& colors, - const PathId& id, + const PathId& path_id, unsigned num_paths) { for(unsigned i = 0; i < num_paths; i++) { m_ren->line_color(colors[i]); - add_path(vs, id[i]); + add_path(vs, path_id[i]); } } @@ -125,6 +136,7 @@ namespace agg Renderer* m_ren; int m_start_x; int m_start_y; + unsigned m_vertices; }; diff --git a/agg2/include/agg_rasterizer_outline_aa.h b/agg/include/agg_rasterizer_outline_aa.h similarity index 57% rename from agg2/include/agg_rasterizer_outline_aa.h rename to agg/include/agg_rasterizer_outline_aa.h index 1ef5633..1f60331 100644 --- a/agg2/include/agg_rasterizer_outline_aa.h +++ b/agg/include/agg_rasterizer_outline_aa.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -15,6 +15,7 @@ #ifndef AGG_RASTERIZER_OUTLINE_AA_INCLUDED #define AGG_RASTERIZER_OUTLINE_AA_INCLUDED +#include #include "agg_basics.h" #include "agg_line_aa_basics.h" #include "agg_vertex_sequence.h" @@ -49,16 +50,23 @@ namespace agg { double dx = val.x - x; double dy = val.y - y; - return (len = int(sqrt(dx * dx + dy * dy))) > - (line_subpixel_size + line_subpixel_size / 2); + return (len = uround(std::sqrt(dx * dx + dy * dy))) > + (line_subpixel_scale + line_subpixel_scale / 2); } }; - + //----------------------------------------------------------outline_aa_join_e + enum outline_aa_join_e + { + outline_no_join, //-----outline_no_join + outline_miter_join, //-----outline_miter_join + outline_round_join, //-----outline_round_join + outline_miter_accurate_join //-----outline_accurate_join + }; //=======================================================rasterizer_outline_aa - template class rasterizer_outline_aa + template class rasterizer_outline_aa { private: //------------------------------------------------------------------------ @@ -78,21 +86,25 @@ namespace agg typedef line_aa_vertex vertex_type; typedef vertex_sequence vertex_storage_type; - rasterizer_outline_aa(Renderer& ren) : - m_ren(ren), - m_accurate_join(m_ren.accurate_join_only()), + explicit rasterizer_outline_aa(Renderer& ren) : + m_ren(&ren), + m_line_join(ren.accurate_join_only() ? + outline_miter_accurate_join : + outline_round_join), m_round_cap(false), m_start_x(0), m_start_y(0) - { - } + {} + void attach(Renderer& ren) { m_ren = &ren; } //------------------------------------------------------------------------ - void accurate_join(bool v) + void line_join(outline_aa_join_e join) { - m_accurate_join = m_ren.accurate_join_only() ? true : v; + m_line_join = m_ren->accurate_join_only() ? + outline_miter_accurate_join : + join; } - bool accurate_join() const { return m_accurate_join; } + bool line_join() const { return m_line_join; } //------------------------------------------------------------------------ void round_cap(bool v) { m_round_cap = v; } @@ -113,13 +125,13 @@ namespace agg //------------------------------------------------------------------------ void move_to_d(double x, double y) { - move_to(line_coord(x), line_coord(y)); + move_to(Coord::conv(x), Coord::conv(y)); } //------------------------------------------------------------------------ void line_to_d(double x, double y) { - line_to(line_coord(x), line_coord(y)); + line_to(Coord::conv(x), Coord::conv(y)); } //------------------------------------------------------------------------ @@ -138,7 +150,10 @@ namespace agg if(is_end_poly(cmd)) { render(is_closed(cmd)); - if(is_closed(cmd)) move_to(m_start_x, m_start_y); + if(is_closed(cmd)) + { + move_to(m_start_x, m_start_y); + } } else { @@ -149,13 +164,13 @@ namespace agg //------------------------------------------------------------------------ template - void add_path(VertexSource& vs, unsigned id=0) + void add_path(VertexSource& vs, unsigned path_id=0) { double x; double y; unsigned cmd; - vs.rewind(id); + vs.rewind(path_id); while(!is_stop(cmd = vs.vertex(&x, &y))) { add_vertex(x, y, cmd); @@ -168,13 +183,13 @@ namespace agg template void render_all_paths(VertexSource& vs, const ColorStorage& colors, - const PathId& id, + const PathId& path_id, unsigned num_paths) { for(unsigned i = 0; i < num_paths; i++) { - m_ren.color(colors[i]); - add_path(vs, id[i]); + m_ren->color(colors[i]); + add_path(vs, path_id[i]); } } @@ -185,22 +200,22 @@ namespace agg unsigned i; for(i = 0; i < c.num_paths(); i++) { - m_ren.color(c.color(i)); + m_ren->color(c.color(i)); add_path(c, i); } } private: - rasterizer_outline_aa(const rasterizer_outline_aa&); - const rasterizer_outline_aa& operator = - (const rasterizer_outline_aa&); + rasterizer_outline_aa(const rasterizer_outline_aa&); + const rasterizer_outline_aa& operator = + (const rasterizer_outline_aa&); - Renderer& m_ren; + Renderer* m_ren; vertex_storage_type m_src_vertices; - bool m_accurate_join; - bool m_round_cap; - int m_start_x; - int m_start_y; + outline_aa_join_e m_line_join; + bool m_round_cap; + int m_start_x; + int m_start_y; }; @@ -211,20 +226,39 @@ namespace agg //---------------------------------------------------------------------------- - template - void rasterizer_outline_aa::draw(draw_vars& dv, unsigned start, unsigned end) + template + void rasterizer_outline_aa::draw(draw_vars& dv, + unsigned start, + unsigned end) { unsigned i; const vertex_storage_type::value_type* v; for(i = start; i < end; i++) { + if(m_line_join == outline_round_join) + { + dv.xb1 = dv.curr.x1 + (dv.curr.y2 - dv.curr.y1); + dv.yb1 = dv.curr.y1 - (dv.curr.x2 - dv.curr.x1); + dv.xb2 = dv.curr.x2 + (dv.curr.y2 - dv.curr.y1); + dv.yb2 = dv.curr.y2 - (dv.curr.x2 - dv.curr.x1); + } + switch(dv.flags) { - case 0: m_ren.line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break; - case 1: m_ren.line2(dv.curr, dv.xb2, dv.yb2); break; - case 2: m_ren.line1(dv.curr, dv.xb1, dv.yb1); break; - case 3: m_ren.line0(dv.curr); break; + case 0: m_ren->line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break; + case 1: m_ren->line2(dv.curr, dv.xb2, dv.yb2); break; + case 2: m_ren->line1(dv.curr, dv.xb1, dv.yb1); break; + case 3: m_ren->line0(dv.curr); break; + } + + if(m_line_join == outline_round_join && (dv.flags & 2) == 0) + { + m_ren->pie(dv.curr.x2, dv.curr.y2, + dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y2 - (dv.curr.x2 - dv.curr.x1), + dv.curr.x2 + (dv.next.y2 - dv.next.y1), + dv.curr.y2 - (dv.next.x2 - dv.next.x1)); } dv.x1 = dv.x2; @@ -244,20 +278,32 @@ namespace agg dv.xb1 = dv.xb2; dv.yb1 = dv.yb2; - if(m_accurate_join) - { - dv.flags = 0; - } - else + switch(m_line_join) { + case outline_no_join: + dv.flags = 3; + break; + + case outline_miter_join: dv.flags >>= 1; dv.flags |= ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); - } + if((dv.flags & 2) == 0) + { + bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); + } + break; - if((dv.flags & 2) == 0) - { + case outline_round_join: + dv.flags >>= 1; + dv.flags |= ((dv.curr.diagonal_quadrant() == + dv.next.diagonal_quadrant()) << 1); + break; + + case outline_miter_accurate_join: + dv.flags = 0; bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); + break; } } } @@ -266,8 +312,8 @@ namespace agg //---------------------------------------------------------------------------- - template - void rasterizer_outline_aa::render(bool close_polygon) + template + void rasterizer_outline_aa::render(bool close_polygon) { m_src_vertices.close(close_polygon); draw_vars dv; @@ -311,23 +357,30 @@ namespace agg dv.xb2 = 0; dv.yb2 = 0; - if(m_accurate_join) - { - dv.flags = 0; - } - else + switch(m_line_join) { + case outline_no_join: + dv.flags = 3; + break; + + case outline_miter_join: + case outline_round_join: dv.flags = (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); + break; + + case outline_miter_accurate_join: + dv.flags = 0; + break; } - if((dv.flags & 1) == 0) + if((dv.flags & 1) == 0 && m_line_join != outline_round_join) { bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); } - if((dv.flags & 2) == 0) + if((dv.flags & 2) == 0 && m_line_join != outline_round_join) { bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); } @@ -354,16 +407,16 @@ namespace agg line_parameters lp(x1, y1, x2, y2, lprev); if(m_round_cap) { - m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); + m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); } - m_ren.line3(lp, - x1 + (y2 - y1), - y1 - (x2 - x1), - x2 + (y2 - y1), - y2 - (x2 - x1)); + m_ren->line3(lp, + x1 + (y2 - y1), + y1 - (x2 - x1), + x2 + (y2 - y1), + y2 - (x2 - x1)); if(m_round_cap) { - m_ren.semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1)); + m_ren->semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1)); } } break; @@ -385,26 +438,35 @@ namespace agg y3 = v->y; line_parameters lp1(x1, y1, x2, y2, lprev); line_parameters lp2(x2, y2, x3, y3, lnext); - bisectrix(lp1, lp2, &dv.xb1, &dv.yb1); if(m_round_cap) { - m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); + m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); + } + + if(m_line_join == outline_round_join) + { + m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1), + x2 + (y2 - y1), y2 - (x2 - x1)); + + m_ren->pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1), + x2 + (y3 - y2), y2 - (x3 - x2)); + + m_ren->line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2), + x3 + (y3 - y2), y3 - (x3 - x2)); + } + else + { + bisectrix(lp1, lp2, &dv.xb1, &dv.yb1); + m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1), + dv.xb1, dv.yb1); + + m_ren->line3(lp2, dv.xb1, dv.yb1, + x3 + (y3 - y2), y3 - (x3 - x2)); } - m_ren.line3(lp1, - x1 + (y2 - y1), - y1 - (x2 - x1), - dv.xb1, - dv.yb1); - - m_ren.line3(lp2, - dv.xb1, - dv.yb1, - x3 + (y3 - y2), - y3 - (x3 - x2)); if(m_round_cap) { - m_ren.semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2)); + m_ren->semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2)); } } break; @@ -440,37 +502,53 @@ namespace agg dv.xb2 = 0; dv.yb2 = 0; - if(m_accurate_join) - { - dv.flags = 0; - } - else + switch(m_line_join) { + case outline_no_join: + dv.flags = 3; + break; + + case outline_miter_join: + case outline_round_join: dv.flags = (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); + break; + + case outline_miter_accurate_join: + dv.flags = 0; + break; } - if((dv.flags & 1) == 0) + if(m_round_cap) { - bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); - m_ren.line3(prev, - x1 + (y2 - y1), - y1 - (x2 - x1), - dv.xb1, - dv.yb1); + m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); } - else + if((dv.flags & 1) == 0) { - m_ren.line1(prev, - x1 + (y2 - y1), - y1 - (x2 - x1)); + if(m_line_join == outline_round_join) + { + m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), + x2 + (y2 - y1), y2 - (x2 - x1)); + m_ren->pie(prev.x2, prev.y2, + x2 + (y2 - y1), y2 - (x2 - x1), + dv.curr.x1 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y1 - (dv.curr.x2 - dv.curr.x1)); + } + else + { + bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); + m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), + dv.xb1, dv.yb1); + } } - if(m_round_cap) + else { - m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); + m_ren->line1(prev, + x1 + (y2 - y1), + y1 - (x2 - x1)); } - if((dv.flags & 2) == 0) + if((dv.flags & 2) == 0 && m_line_join != outline_round_join) { bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); } @@ -479,23 +557,32 @@ namespace agg if((dv.flags & 1) == 0) { - m_ren.line3(dv.curr, - dv.xb1, - dv.yb1, - dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), - dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + if(m_line_join == outline_round_join) + { + m_ren->line3(dv.curr, + dv.curr.x1 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y1 - (dv.curr.x2 - dv.curr.x1), + dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + } + else + { + m_ren->line3(dv.curr, dv.xb1, dv.yb1, + dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + } } else { - m_ren.line2(dv.curr, - dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), - dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + m_ren->line2(dv.curr, + dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); } if(m_round_cap) { - m_ren.semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2, - dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), - dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + m_ren->semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2, + dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); } } diff --git a/agg/include/agg_rasterizer_scanline_aa.h b/agg/include/agg_rasterizer_scanline_aa.h new file mode 100644 index 0000000..b788afe --- /dev/null +++ b/agg/include/agg_rasterizer_scanline_aa.h @@ -0,0 +1,481 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// +// The author gratefully acknowleges the support of David Turner, +// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType +// libray - in producing this work. See http://www.freetype.org for details. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- +#ifndef AGG_RASTERIZER_SCANLINE_AA_INCLUDED +#define AGG_RASTERIZER_SCANLINE_AA_INCLUDED + +#include "agg_rasterizer_cells_aa.h" +#include "agg_rasterizer_sl_clip.h" +#include "agg_rasterizer_scanline_aa_nogamma.h" +#include "agg_gamma_functions.h" + + +namespace agg +{ + //==================================================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 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(unsigned cell_block_limit=1024) : + m_outline(cell_block_limit), + m_clipper(), + m_filling_rule(fill_non_zero), + m_auto_close(true), + m_start_x(0), + m_start_y(0), + m_status(status_initial) + { + int i; + for(i = 0; i < aa_scale; i++) m_gamma[i] = i; + } + + //-------------------------------------------------------------------- + template + rasterizer_scanline_aa(const GammaF& gamma_function, unsigned cell_block_limit) : + m_outline(cell_block_limit), + m_clipper(m_outline), + m_filling_rule(fill_non_zero), + m_auto_close(true), + m_start_x(0), + m_start_y(0), + m_status(status_initial) + { + gamma(gamma_function); + } + + //-------------------------------------------------------------------- + void reset(); + void reset_clipping(); + void clip_box(double x1, double y1, double x2, double y2); + void filling_rule(filling_rule_e filling_rule); + void auto_close(bool flag) { m_auto_close = flag; } + + //-------------------------------------------------------------------- + template void gamma(const GammaF& gamma_function) + { + int i; + for(i = 0; i < aa_scale; i++) + { + m_gamma[i] = uround(gamma_function(double(i) / aa_mask) * aa_mask); + } + } + + //-------------------------------------------------------------------- + unsigned apply_gamma(unsigned cover) const + { + return m_gamma[cover]; + } + + //-------------------------------------------------------------------- + void move_to(int x, int y); + void line_to(int x, int y); + void move_to_d(double x, double y); + void line_to_d(double x, double y); + void close_polygon(); + void add_vertex(double x, double y, unsigned cmd); + + void edge(int x1, int y1, int x2, int y2); + void edge_d(double x1, double y1, double x2, double y2); + + //------------------------------------------------------------------- + template + void add_path(VertexSource& vs, unsigned path_id=0) + { + double x; + double y; + + unsigned cmd; + vs.rewind(path_id); + if(m_outline.sorted()) reset(); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + add_vertex(x, y, cmd); + } + } + + //-------------------------------------------------------------------- + int min_x() const { return m_outline.min_x(); } + int min_y() const { return m_outline.min_y(); } + int max_x() const { return m_outline.max_x(); } + int max_y() const { return m_outline.max_y(); } + + //-------------------------------------------------------------------- + void sort(); + bool rewind_scanlines(); + bool navigate_scanline(int y); + + //-------------------------------------------------------------------- + AGG_INLINE unsigned calculate_alpha(int area) const + { + int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift); + + if(cover < 0) cover = -cover; + if(m_filling_rule == fill_even_odd) + { + cover &= aa_mask2; + if(cover > aa_scale) + { + cover = aa_scale2 - cover; + } + } + if(cover > aa_mask) cover = aa_mask; + return m_gamma[cover]; + } + + //-------------------------------------------------------------------- + template bool sweep_scanline(Scanline& sl) + { + for(;;) + { + if(m_scan_y > m_outline.max_y()) return false; + sl.reset_spans(); + unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); + const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y); + int cover = 0; + + while(num_cells) + { + const cell_aa* cur_cell = *cells; + int x = cur_cell->x; + int area = cur_cell->area; + unsigned alpha; + + cover += cur_cell->cover; + + //accumulate all cells with the same X + while(--num_cells) + { + cur_cell = *++cells; + if(cur_cell->x != x) break; + area += cur_cell->area; + cover += cur_cell->cover; + } + + if(area) + { + alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area); + if(alpha) + { + sl.add_cell(x, alpha); + } + x++; + } + + if(num_cells && cur_cell->x > x) + { + alpha = calculate_alpha(cover << (poly_subpixel_shift + 1)); + if(alpha) + { + sl.add_span(x, cur_cell->x - x, alpha); + } + } + } + + if(sl.num_spans()) break; + ++m_scan_y; + } + + sl.finalize(m_scan_y); + ++m_scan_y; + return true; + } + + //-------------------------------------------------------------------- + bool hit_test(int tx, int ty); + + + private: + //-------------------------------------------------------------------- + // Disable copying + rasterizer_scanline_aa(const rasterizer_scanline_aa&); + const rasterizer_scanline_aa& + operator = (const rasterizer_scanline_aa&); + + private: + rasterizer_cells_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 + void rasterizer_scanline_aa::reset() + { + m_outline.reset(); + m_status = status_initial; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa::filling_rule(filling_rule_e filling_rule) + { + m_filling_rule = filling_rule; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa::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 + void rasterizer_scanline_aa::reset_clipping() + { + reset(); + m_clipper.reset_clipping(); + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa::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 + void rasterizer_scanline_aa::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 + void rasterizer_scanline_aa::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 + void rasterizer_scanline_aa::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 + void rasterizer_scanline_aa::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 + void rasterizer_scanline_aa::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 + void rasterizer_scanline_aa::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 + void rasterizer_scanline_aa::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 + void rasterizer_scanline_aa::sort() + { + if(m_auto_close) close_polygon(); + m_outline.sort_cells(); + } + + //------------------------------------------------------------------------ + template + AGG_INLINE bool rasterizer_scanline_aa::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 + AGG_INLINE bool rasterizer_scanline_aa::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 + bool rasterizer_scanline_aa::hit_test(int tx, int ty) + { + if(!navigate_scanline(ty)) return false; + scanline_hit_test sl(tx); + sweep_scanline(sl); + return sl.hit(); + } + + + +} + + + +#endif + diff --git a/agg/include/agg_rasterizer_scanline_aa_nogamma.h b/agg/include/agg_rasterizer_scanline_aa_nogamma.h new file mode 100644 index 0000000..ece8fdc --- /dev/null +++ b/agg/include/agg_rasterizer_scanline_aa_nogamma.h @@ -0,0 +1,483 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// +// The author gratefully acknowleges the support of David Turner, +// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType +// libray - in producing this work. See http://www.freetype.org for details. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- +#ifndef AGG_RASTERIZER_SCANLINE_AA_NOGAMMA_INCLUDED +#define AGG_RASTERIZER_SCANLINE_AA_NOGAMMA_INCLUDED + +#include +#include "agg_rasterizer_cells_aa.h" +#include "agg_rasterizer_sl_clip.h" + + +namespace agg +{ + + + //-----------------------------------------------------------------cell_aa + // A pixel cell. There're no constructors defined and it was done + // intentionally in order to avoid extra overhead when allocating an + // array of cells. + struct cell_aa + { + int x; + int y; + int cover; + int area; + + void initial() + { + x = std::numeric_limits::max(); + y = std::numeric_limits::max(); + cover = 0; + area = 0; + } + + void style(const cell_aa&) {} + + int not_equal(int ex, int ey, const cell_aa&) const + { + return ((unsigned)ex - (unsigned)x) | ((unsigned)ey - (unsigned)y); + } + }; + + + //==================================================rasterizer_scanline_aa_nogamma + // 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 rasterizer_scanline_aa_nogamma + { + 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_nogamma(unsigned cell_block_limit=1024) : + m_outline(cell_block_limit), + m_clipper(), + m_filling_rule(fill_non_zero), + m_auto_close(true), + m_start_x(0), + m_start_y(0), + m_status(status_initial) + { + } + + //-------------------------------------------------------------------- + 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; } + + //-------------------------------------------------------------------- + unsigned apply_gamma(unsigned cover) const + { + return 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 + void add_path(VertexSource& vs, unsigned path_id=0) + { + double x; + double y; + + unsigned cmd; + vs.rewind(path_id); + if(m_outline.sorted()) reset(); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + add_vertex(x, y, cmd); + } + } + + //-------------------------------------------------------------------- + int min_x() const { return m_outline.min_x(); } + int min_y() const { return m_outline.min_y(); } + int max_x() const { return m_outline.max_x(); } + int max_y() const { return m_outline.max_y(); } + + //-------------------------------------------------------------------- + void sort(); + bool rewind_scanlines(); + bool navigate_scanline(int y); + + //-------------------------------------------------------------------- + AGG_INLINE unsigned calculate_alpha(int area) const + { + int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift); + + if(cover < 0) cover = -cover; + if(m_filling_rule == fill_even_odd) + { + cover &= aa_mask2; + if(cover > aa_scale) + { + cover = aa_scale2 - cover; + } + } + if(cover > aa_mask) cover = aa_mask; + return cover; + } + + //-------------------------------------------------------------------- + template bool sweep_scanline(Scanline& sl) + { + for(;;) + { + if(m_scan_y > m_outline.max_y()) return false; + sl.reset_spans(); + unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); + const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y); + int cover = 0; + + while(num_cells) + { + const cell_aa* cur_cell = *cells; + int x = cur_cell->x; + int area = cur_cell->area; + unsigned alpha; + + cover += cur_cell->cover; + + //accumulate all cells with the same X + while(--num_cells) + { + cur_cell = *++cells; + if(cur_cell->x != x) break; + area += cur_cell->area; + cover += cur_cell->cover; + } + + if(area) + { + alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area); + if(alpha) + { + sl.add_cell(x, alpha); + } + x++; + } + + if(num_cells && cur_cell->x > x) + { + alpha = calculate_alpha(cover << (poly_subpixel_shift + 1)); + if(alpha) + { + sl.add_span(x, cur_cell->x - x, alpha); + } + } + } + + if(sl.num_spans()) break; + ++m_scan_y; + } + + sl.finalize(m_scan_y); + ++m_scan_y; + return true; + } + + //-------------------------------------------------------------------- + bool hit_test(int tx, int ty); + + + private: + //-------------------------------------------------------------------- + // Disable copying + rasterizer_scanline_aa_nogamma(const rasterizer_scanline_aa_nogamma&); + const rasterizer_scanline_aa_nogamma& + operator = (const rasterizer_scanline_aa_nogamma&); + + private: + rasterizer_cells_aa m_outline; + clip_type m_clipper; + 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 + void rasterizer_scanline_aa_nogamma::reset() + { + m_outline.reset(); + m_status = status_initial; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_nogamma::filling_rule(filling_rule_e filling_rule) + { + m_filling_rule = filling_rule; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_nogamma::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 + void rasterizer_scanline_aa_nogamma::reset_clipping() + { + reset(); + m_clipper.reset_clipping(); + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_nogamma::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 + void rasterizer_scanline_aa_nogamma::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 + void rasterizer_scanline_aa_nogamma::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 + void rasterizer_scanline_aa_nogamma::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 + void rasterizer_scanline_aa_nogamma::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 + void rasterizer_scanline_aa_nogamma::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 + void rasterizer_scanline_aa_nogamma::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 + void rasterizer_scanline_aa_nogamma::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 + void rasterizer_scanline_aa_nogamma::sort() + { + if(m_auto_close) close_polygon(); + m_outline.sort_cells(); + } + + //------------------------------------------------------------------------ + template + AGG_INLINE bool rasterizer_scanline_aa_nogamma::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 + AGG_INLINE bool rasterizer_scanline_aa_nogamma::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 + bool rasterizer_scanline_aa_nogamma::hit_test(int tx, int ty) + { + if(!navigate_scanline(ty)) return false; + scanline_hit_test sl(tx); + sweep_scanline(sl); + return sl.hit(); + } + + + +} + + + +#endif + diff --git a/agg/include/agg_rasterizer_sl_clip.h b/agg/include/agg_rasterizer_sl_clip.h new file mode 100644 index 0000000..3a7f3a1 --- /dev/null +++ b/agg/include/agg_rasterizer_sl_clip.h @@ -0,0 +1,351 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +#ifndef AGG_RASTERIZER_SL_CLIP_INCLUDED +#define AGG_RASTERIZER_SL_CLIP_INCLUDED + +#include "agg_clip_liang_barsky.h" + +namespace agg +{ + //--------------------------------------------------------poly_max_coord_e + enum poly_max_coord_e + { + poly_max_coord = (1 << 30) - 1 //----poly_max_coord + }; + + //------------------------------------------------------------ras_conv_int + struct ras_conv_int + { + typedef int coord_type; + static AGG_INLINE int mul_div(double a, double b, double c) + { + return iround(a * b / c); + } + static int xi(int v) { return v; } + static int yi(int v) { return v; } + static int upscale(double v) { return iround(v * poly_subpixel_scale); } + static int downscale(int v) { return v; } + }; + + //--------------------------------------------------------ras_conv_int_sat + struct ras_conv_int_sat + { + typedef int coord_type; + static AGG_INLINE int mul_div(double a, double b, double c) + { + return saturation::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::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 rasterizer_sl_clip + { + public: + typedef Conv conv_type; + typedef typename Conv::coord_type coord_type; + typedef rect_base 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 + AGG_INLINE void line_clip_y(Rasterizer& ras, + coord_type x1, coord_type y1, + coord_type x2, coord_type y2, + unsigned f1, unsigned f2) const + { + f1 &= 10; + f2 &= 10; + if((f1 | f2) == 0) + { + // Fully visible + ras.line(Conv::xi(x1), Conv::yi(y1), Conv::xi(x2), Conv::yi(y2)); + } + else + { + if(f1 == f2) + { + // Invisible by Y + return; + } + + coord_type tx1 = x1; + coord_type ty1 = y1; + coord_type tx2 = x2; + coord_type ty2 = y2; + + if(f1 & 8) // y1 < clip.y1 + { + tx1 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1); + ty1 = m_clip_box.y1; + } + + if(f1 & 2) // y1 > clip.y2 + { + tx1 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1); + ty1 = m_clip_box.y2; + } + + if(f2 & 8) // y2 < clip.y1 + { + tx2 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1); + ty2 = m_clip_box.y1; + } + + if(f2 & 2) // y2 > clip.y2 + { + tx2 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1); + ty2 = m_clip_box.y2; + } + ras.line(Conv::xi(tx1), Conv::yi(ty1), + Conv::xi(tx2), Conv::yi(ty2)); + } + } + + + public: + //-------------------------------------------------------------------- + template + void line_to(Rasterizer& ras, coord_type x2, coord_type y2) + { + if(m_clipping) + { + unsigned f2 = clipping_flags(x2, y2, m_clip_box); + + if((m_f1 & 10) == (f2 & 10) && (m_f1 & 10) != 0) + { + // Invisible by Y + m_x1 = x2; + m_y1 = y2; + m_f1 = f2; + return; + } + + coord_type x1 = m_x1; + coord_type y1 = m_y1; + unsigned f1 = m_f1; + coord_type y3, y4; + unsigned f3, f4; + + switch(((f1 & 5) << 1) | (f2 & 5)) + { + case 0: // Visible by X + line_clip_y(ras, x1, y1, x2, y2, f1, f2); + break; + + case 1: // x2 > clip.x2 + y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + line_clip_y(ras, x1, y1, m_clip_box.x2, y3, f1, f3); + line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x2, y2, f3, f2); + break; + + case 2: // x1 > clip.x2 + y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3); + line_clip_y(ras, m_clip_box.x2, y3, x2, y2, f3, f2); + break; + + case 3: // x1 > clip.x2 && x2 > clip.x2 + line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y2, f1, f2); + break; + + case 4: // x2 < clip.x1 + y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + line_clip_y(ras, x1, y1, m_clip_box.x1, y3, f1, f3); + line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x1, y2, f3, f2); + break; + + case 6: // x1 > clip.x2 && x2 < clip.x1 + y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); + y4 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + f4 = clipping_flags_y(y4, m_clip_box); + line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3); + line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x1, y4, f3, f4); + line_clip_y(ras, m_clip_box.x1, y4, m_clip_box.x1, y2, f4, f2); + break; + + case 8: // x1 < clip.x1 + y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3); + line_clip_y(ras, m_clip_box.x1, y3, x2, y2, f3, f2); + break; + + case 9: // x1 < clip.x1 && x2 > clip.x2 + y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); + y4 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + f4 = clipping_flags_y(y4, m_clip_box); + line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3); + line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x2, y4, f3, f4); + line_clip_y(ras, m_clip_box.x2, y4, m_clip_box.x2, y2, f4, f2); + break; + + case 12: // x1 < clip.x1 && x2 < clip.x1 + line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y2, f1, f2); + break; + } + m_f1 = f2; + } + else + { + ras.line(Conv::xi(m_x1), Conv::yi(m_y1), + Conv::xi(x2), Conv::yi(y2)); + } + m_x1 = x2; + m_y1 = y2; + } + + + private: + rect_type m_clip_box; + coord_type m_x1; + coord_type m_y1; + unsigned m_f1; + bool m_clipping; + }; + + + + + //---------------------------------------------------rasterizer_sl_no_clip + class rasterizer_sl_no_clip + { + public: + typedef ras_conv_int conv_type; + typedef int coord_type; + + rasterizer_sl_no_clip() : m_x1(0), m_y1(0) {} + + void reset_clipping() {} + void clip_box(coord_type, coord_type, coord_type, coord_type) {} + void move_to(coord_type x1, coord_type y1) { m_x1 = x1; m_y1 = y1; } + + template + void line_to(Rasterizer& ras, coord_type x2, coord_type y2) + { + ras.line(m_x1, m_y1, x2, y2); + m_x1 = x2; + m_y1 = y2; + } + + private: + int m_x1, m_y1; + }; + + + // -----rasterizer_sl_clip_int + // -----rasterizer_sl_clip_int_sat + // -----rasterizer_sl_clip_int_3x + // -----rasterizer_sl_clip_dbl + // -----rasterizer_sl_clip_dbl_3x + //------------------------------------------------------------------------ + typedef rasterizer_sl_clip rasterizer_sl_clip_int; + typedef rasterizer_sl_clip rasterizer_sl_clip_int_sat; + typedef rasterizer_sl_clip rasterizer_sl_clip_int_3x; + typedef rasterizer_sl_clip rasterizer_sl_clip_dbl; + typedef rasterizer_sl_clip rasterizer_sl_clip_dbl_3x; + + +} + +#endif diff --git a/agg/include/agg_renderer_base.h b/agg/include/agg_renderer_base.h new file mode 100644 index 0000000..527c62f --- /dev/null +++ b/agg/include/agg_renderer_base.h @@ -0,0 +1,731 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// class renderer_base +// +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERER_BASE_INCLUDED +#define AGG_RENDERER_BASE_INCLUDED + +#include "agg_basics.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + + //-----------------------------------------------------------renderer_base + template class renderer_base + { + public: + typedef PixelFormat pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::row_data row_data; + + //-------------------------------------------------------------------- + renderer_base() : m_ren(0), m_clip_box(1, 1, 0, 0) {} + explicit renderer_base(pixfmt_type& ren) : + m_ren(&ren), + m_clip_box(0, 0, ren.width() - 1, ren.height() - 1) + {} + void attach(pixfmt_type& ren) + { + m_ren = &ren; + m_clip_box = rect_i(0, 0, ren.width() - 1, ren.height() - 1); + } + + //-------------------------------------------------------------------- + const pixfmt_type& ren() const { return *m_ren; } + pixfmt_type& ren() { return *m_ren; } + + //-------------------------------------------------------------------- + unsigned width() const { return m_ren->width(); } + unsigned height() const { return m_ren->height(); } + + //-------------------------------------------------------------------- + bool clip_box(int x1, int y1, int x2, int y2) + { + rect_i cb(x1, y1, x2, y2); + cb.normalize(); + if(cb.clip(rect_i(0, 0, width() - 1, height() - 1))) + { + m_clip_box = cb; + return true; + } + m_clip_box.x1 = 1; + m_clip_box.y1 = 1; + m_clip_box.x2 = 0; + m_clip_box.y2 = 0; + return false; + } + + //-------------------------------------------------------------------- + void reset_clipping(bool visibility) + { + if(visibility) + { + m_clip_box.x1 = 0; + m_clip_box.y1 = 0; + m_clip_box.x2 = width() - 1; + m_clip_box.y2 = height() - 1; + } + else + { + m_clip_box.x1 = 1; + m_clip_box.y1 = 1; + m_clip_box.x2 = 0; + m_clip_box.y2 = 0; + } + } + + //-------------------------------------------------------------------- + void clip_box_naked(int x1, int y1, int x2, int y2) + { + m_clip_box.x1 = x1; + m_clip_box.y1 = y1; + m_clip_box.x2 = x2; + m_clip_box.y2 = y2; + } + + //-------------------------------------------------------------------- + bool inbox(int x, int y) const + { + return x >= m_clip_box.x1 && y >= m_clip_box.y1 && + x <= m_clip_box.x2 && y <= m_clip_box.y2; + } + + //-------------------------------------------------------------------- + const rect_i& clip_box() const { return m_clip_box; } + int xmin() const { return m_clip_box.x1; } + int ymin() const { return m_clip_box.y1; } + int xmax() const { return m_clip_box.x2; } + int ymax() const { return m_clip_box.y2; } + + //-------------------------------------------------------------------- + const rect_i& bounding_clip_box() const { return m_clip_box; } + int bounding_xmin() const { return m_clip_box.x1; } + int bounding_ymin() const { return m_clip_box.y1; } + int bounding_xmax() const { return m_clip_box.x2; } + int bounding_ymax() const { return m_clip_box.y2; } + + //-------------------------------------------------------------------- + void clear(const color_type& c) + { + unsigned y; + if(width()) + { + for(y = 0; y < height(); y++) + { + m_ren->copy_hline(0, y, width(), c); + } + } + } + + + //-------------------------------------------------------------------- + void fill(const color_type& c) + { + unsigned y; + if(width()) + { + for(y = 0; y < height(); y++) + { + m_ren->blend_hline(0, y, width(), c, cover_mask); + } + } + } + + //-------------------------------------------------------------------- + void copy_pixel(int x, int y, const color_type& c) + { + if(inbox(x, y)) + { + m_ren->copy_pixel(x, y, c); + } + } + + //-------------------------------------------------------------------- + void blend_pixel(int x, int y, const color_type& c, cover_type cover) + { + if(inbox(x, y)) + { + m_ren->blend_pixel(x, y, c, cover); + } + } + + //-------------------------------------------------------------------- + color_type pixel(int x, int y) const + { + return inbox(x, y) ? + m_ren->pixel(x, y) : + color_type::no_color(); + } + + //-------------------------------------------------------------------- + void copy_hline(int x1, int y, int x2, const color_type& c) + { + if(x1 > x2) { int t = x2; x2 = x1; x1 = t; } + if(y > ymax()) return; + if(y < ymin()) return; + if(x1 > xmax()) return; + if(x2 < xmin()) return; + + if(x1 < xmin()) x1 = xmin(); + if(x2 > xmax()) x2 = xmax(); + + m_ren->copy_hline(x1, y, x2 - x1 + 1, c); + } + + //-------------------------------------------------------------------- + void copy_vline(int x, int y1, int y2, const color_type& c) + { + if(y1 > y2) { int t = y2; y2 = y1; y1 = t; } + if(x > xmax()) return; + if(x < xmin()) return; + if(y1 > ymax()) return; + if(y2 < ymin()) return; + + if(y1 < ymin()) y1 = ymin(); + if(y2 > ymax()) y2 = ymax(); + + m_ren->copy_vline(x, y1, y2 - y1 + 1, c); + } + + //-------------------------------------------------------------------- + void blend_hline(int x1, int y, int x2, + const color_type& c, cover_type cover) + { + if(x1 > x2) { int t = x2; x2 = x1; x1 = t; } + if(y > ymax()) return; + if(y < ymin()) return; + if(x1 > xmax()) return; + if(x2 < xmin()) return; + + if(x1 < xmin()) x1 = xmin(); + if(x2 > xmax()) x2 = xmax(); + + m_ren->blend_hline(x1, y, x2 - x1 + 1, c, cover); + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y1, int y2, + const color_type& c, cover_type cover) + { + if(y1 > y2) { int t = y2; y2 = y1; y1 = t; } + if(x > xmax()) return; + if(x < xmin()) return; + if(y1 > ymax()) return; + if(y2 < ymin()) return; + + if(y1 < ymin()) y1 = ymin(); + if(y2 > ymax()) y2 = ymax(); + + m_ren->blend_vline(x, y1, y2 - y1 + 1, c, cover); + } + + + //-------------------------------------------------------------------- + void copy_bar(int x1, int y1, int x2, int y2, const color_type& c) + { + rect_i rc(x1, y1, x2, y2); + rc.normalize(); + if(rc.clip(clip_box())) + { + int y; + for(y = rc.y1; y <= rc.y2; y++) + { + m_ren->copy_hline(rc.x1, y, unsigned(rc.x2 - rc.x1 + 1), c); + } + } + } + + //-------------------------------------------------------------------- + void blend_bar(int x1, int y1, int x2, int y2, + const color_type& c, cover_type cover) + { + rect_i rc(x1, y1, x2, y2); + rc.normalize(); + if(rc.clip(clip_box())) + { + int y; + for(y = rc.y1; y <= rc.y2; y++) + { + m_ren->blend_hline(rc.x1, + y, + unsigned(rc.x2 - rc.x1 + 1), + c, + cover); + } + } + } + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, int len, + const color_type& c, + const cover_type* covers) + { + if(y > ymax()) return; + if(y < ymin()) return; + + if(x < xmin()) + { + len -= xmin() - x; + if(len <= 0) return; + covers += xmin() - x; + x = xmin(); + } + if(x + len > xmax()) + { + len = xmax() - x + 1; + if(len <= 0) return; + } + m_ren->blend_solid_hspan(x, y, len, c, covers); + } + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, int len, + const color_type& c, + const cover_type* covers) + { + if(x > xmax()) return; + if(x < xmin()) return; + + if(y < ymin()) + { + len -= ymin() - y; + if(len <= 0) return; + covers += ymin() - y; + y = ymin(); + } + if(y + len > ymax()) + { + len = ymax() - y + 1; + if(len <= 0) return; + } + m_ren->blend_solid_vspan(x, y, len, c, covers); + } + + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, int len, const color_type* colors) + { + if(y > ymax()) return; + if(y < ymin()) return; + + if(x < xmin()) + { + int d = xmin() - x; + len -= d; + if(len <= 0) return; + colors += d; + x = xmin(); + } + if(x + len > xmax()) + { + len = xmax() - x + 1; + if(len <= 0) return; + } + m_ren->copy_color_hspan(x, y, len, colors); + } + + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, int len, const color_type* colors) + { + if(x > xmax()) return; + if(x < xmin()) return; + + if(y < ymin()) + { + int d = ymin() - y; + len -= d; + if(len <= 0) return; + colors += d; + y = ymin(); + } + if(y + len > ymax()) + { + len = ymax() - y + 1; + if(len <= 0) return; + } + m_ren->copy_color_vspan(x, y, len, colors); + } + + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, int len, + const color_type* colors, + const cover_type* covers, + cover_type cover = agg::cover_full) + { + if(y > ymax()) return; + if(y < ymin()) return; + + if(x < xmin()) + { + int d = xmin() - x; + len -= d; + if(len <= 0) return; + if(covers) covers += d; + colors += d; + x = xmin(); + } + if(x + len > xmax()) + { + len = xmax() - x + 1; + if(len <= 0) return; + } + m_ren->blend_color_hspan(x, y, len, colors, covers, cover); + } + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, int len, + const color_type* colors, + const cover_type* covers, + cover_type cover = agg::cover_full) + { + if(x > xmax()) return; + if(x < xmin()) return; + + if(y < ymin()) + { + int d = ymin() - y; + len -= d; + if(len <= 0) return; + if(covers) covers += d; + colors += d; + y = ymin(); + } + if(y + len > ymax()) + { + len = ymax() - y + 1; + if(len <= 0) return; + } + m_ren->blend_color_vspan(x, y, len, colors, covers, cover); + } + + //-------------------------------------------------------------------- + rect_i clip_rect_area(rect_i& dst, rect_i& src, int wsrc, int hsrc) const + { + rect_i rc(0,0,0,0); + rect_i cb = clip_box(); + ++cb.x2; + ++cb.y2; + + if(src.x1 < 0) + { + dst.x1 -= src.x1; + src.x1 = 0; + } + if(src.y1 < 0) + { + dst.y1 -= src.y1; + src.y1 = 0; + } + + if(src.x2 > wsrc) src.x2 = wsrc; + if(src.y2 > hsrc) src.y2 = hsrc; + + if(dst.x1 < cb.x1) + { + src.x1 += cb.x1 - dst.x1; + dst.x1 = cb.x1; + } + if(dst.y1 < cb.y1) + { + src.y1 += cb.y1 - dst.y1; + dst.y1 = cb.y1; + } + + if(dst.x2 > cb.x2) dst.x2 = cb.x2; + if(dst.y2 > cb.y2) dst.y2 = cb.y2; + + rc.x2 = dst.x2 - dst.x1; + rc.y2 = dst.y2 - dst.y1; + + if(rc.x2 > src.x2 - src.x1) rc.x2 = src.x2 - src.x1; + if(rc.y2 > src.y2 - src.y1) rc.y2 = src.y2 - src.y1; + return rc; + } + + //-------------------------------------------------------------------- + template + void copy_from(const RenBuf& src, + const rect_i* rect_src_ptr = 0, + int dx = 0, + int dy = 0) + { + rect_i rsrc(0, 0, src.width(), src.height()); + if(rect_src_ptr) + { + rsrc.x1 = rect_src_ptr->x1; + rsrc.y1 = rect_src_ptr->y1; + rsrc.x2 = rect_src_ptr->x2 + 1; + rsrc.y2 = rect_src_ptr->y2 + 1; + } + + // Version with xdst, ydst (absolute positioning) + //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); + + // Version with dx, dy (relative positioning) + rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); + + rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); + + if(rc.x2 > 0) + { + int incy = 1; + if(rdst.y1 > rsrc.y1) + { + rsrc.y1 += rc.y2 - 1; + rdst.y1 += rc.y2 - 1; + incy = -1; + } + while(rc.y2 > 0) + { + m_ren->copy_from(src, + rdst.x1, rdst.y1, + rsrc.x1, rsrc.y1, + rc.x2); + rdst.y1 += incy; + rsrc.y1 += incy; + --rc.y2; + } + } + } + + //-------------------------------------------------------------------- + template + void blend_from(const SrcPixelFormatRenderer& src, + const rect_i* rect_src_ptr = 0, + int dx = 0, + int dy = 0, + cover_type cover = agg::cover_full) + { + rect_i rsrc(0, 0, src.width(), src.height()); + if(rect_src_ptr) + { + rsrc.x1 = rect_src_ptr->x1; + rsrc.y1 = rect_src_ptr->y1; + rsrc.x2 = rect_src_ptr->x2 + 1; + rsrc.y2 = rect_src_ptr->y2 + 1; + } + + // Version with xdst, ydst (absolute positioning) + //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); + + // Version with dx, dy (relative positioning) + rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); + rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); + + if(rc.x2 > 0) + { + int incy = 1; + if(rdst.y1 > rsrc.y1) + { + rsrc.y1 += rc.y2 - 1; + rdst.y1 += rc.y2 - 1; + incy = -1; + } + while(rc.y2 > 0) + { + typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1); + if(rw.ptr) + { + int x1src = rsrc.x1; + int x1dst = rdst.x1; + int len = rc.x2; + if(rw.x1 > x1src) + { + x1dst += rw.x1 - x1src; + len -= rw.x1 - x1src; + x1src = rw.x1; + } + if(len > 0) + { + if(x1src + len-1 > rw.x2) + { + len -= x1src + len - rw.x2 - 1; + } + if(len > 0) + { + m_ren->blend_from(src, + x1dst, rdst.y1, + x1src, rsrc.y1, + len, + cover); + } + } + } + rdst.y1 += incy; + rsrc.y1 += incy; + --rc.y2; + } + } + } + + //-------------------------------------------------------------------- + template + void blend_from_color(const SrcPixelFormatRenderer& src, + const color_type& color, + const rect_i* rect_src_ptr = 0, + int dx = 0, + int dy = 0, + cover_type cover = agg::cover_full) + { + rect_i rsrc(0, 0, src.width(), src.height()); + if(rect_src_ptr) + { + rsrc.x1 = rect_src_ptr->x1; + rsrc.y1 = rect_src_ptr->y1; + rsrc.x2 = rect_src_ptr->x2 + 1; + rsrc.y2 = rect_src_ptr->y2 + 1; + } + + // Version with xdst, ydst (absolute positioning) + //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); + + // Version with dx, dy (relative positioning) + rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); + rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); + + if(rc.x2 > 0) + { + int incy = 1; + if(rdst.y1 > rsrc.y1) + { + rsrc.y1 += rc.y2 - 1; + rdst.y1 += rc.y2 - 1; + incy = -1; + } + while(rc.y2 > 0) + { + typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1); + if(rw.ptr) + { + int x1src = rsrc.x1; + int x1dst = rdst.x1; + int len = rc.x2; + if(rw.x1 > x1src) + { + x1dst += rw.x1 - x1src; + len -= rw.x1 - x1src; + x1src = rw.x1; + } + if(len > 0) + { + if(x1src + len-1 > rw.x2) + { + len -= x1src + len - rw.x2 - 1; + } + if(len > 0) + { + m_ren->blend_from_color(src, + color, + x1dst, rdst.y1, + x1src, rsrc.y1, + len, + cover); + } + } + } + rdst.y1 += incy; + rsrc.y1 += incy; + --rc.y2; + } + } + } + + //-------------------------------------------------------------------- + template + void blend_from_lut(const SrcPixelFormatRenderer& src, + const color_type* color_lut, + const rect_i* rect_src_ptr = 0, + int dx = 0, + int dy = 0, + cover_type cover = agg::cover_full) + { + rect_i rsrc(0, 0, src.width(), src.height()); + if(rect_src_ptr) + { + rsrc.x1 = rect_src_ptr->x1; + rsrc.y1 = rect_src_ptr->y1; + rsrc.x2 = rect_src_ptr->x2 + 1; + rsrc.y2 = rect_src_ptr->y2 + 1; + } + + // Version with xdst, ydst (absolute positioning) + //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); + + // Version with dx, dy (relative positioning) + rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); + rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); + + if(rc.x2 > 0) + { + int incy = 1; + if(rdst.y1 > rsrc.y1) + { + rsrc.y1 += rc.y2 - 1; + rdst.y1 += rc.y2 - 1; + incy = -1; + } + while(rc.y2 > 0) + { + typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1); + if(rw.ptr) + { + int x1src = rsrc.x1; + int x1dst = rdst.x1; + int len = rc.x2; + if(rw.x1 > x1src) + { + x1dst += rw.x1 - x1src; + len -= rw.x1 - x1src; + x1src = rw.x1; + } + if(len > 0) + { + if(x1src + len-1 > rw.x2) + { + len -= x1src + len - rw.x2 - 1; + } + if(len > 0) + { + m_ren->blend_from_lut(src, + color_lut, + x1dst, rdst.y1, + x1src, rsrc.y1, + len, + cover); + } + } + } + rdst.y1 += incy; + rsrc.y1 += incy; + --rc.y2; + } + } + } + + private: + pixfmt_type* m_ren; + rect_i m_clip_box; + }; + + +} + +#endif diff --git a/agg2/include/agg_renderer_markers.h b/agg/include/agg_renderer_markers.h similarity index 98% rename from agg2/include/agg_renderer_markers.h rename to agg/include/agg_renderer_markers.h index a0acb36..6ff0534 100644 --- a/agg2/include/agg_renderer_markers.h +++ b/agg/include/agg_renderer_markers.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -65,13 +65,12 @@ namespace agg //-------------------------------------------------------------------- renderer_markers(base_ren_type& rbuf) : base_type(rbuf) - { - } + {} //-------------------------------------------------------------------- bool visible(int x, int y, int r) const { - rect rc(x-r, y-r, x+y, y+r); + rect_i rc(x-r, y-r, x+y, y+r); return rc.clip(base_type::ren().bounding_clip_box()); } @@ -573,6 +572,7 @@ namespace agg case marker_dash: dash(x, y, r); break; case marker_dot: dot(x, y, r); break; case marker_pixel: pixel(x, y, r); break; + case end_of_markers: break; } } @@ -614,6 +614,7 @@ namespace agg case marker_dash: do { dash (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; case marker_dot: do { dot (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; case marker_pixel: do { pixel (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case end_of_markers: break; } } @@ -642,6 +643,7 @@ namespace agg case marker_dash: do { dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; case marker_dot: do { dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; case marker_pixel: do { pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case end_of_markers: break; } } @@ -670,6 +672,7 @@ namespace agg case marker_dash: do { base_type::fill_color(*fc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; case marker_dot: do { base_type::fill_color(*fc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; case marker_pixel: do { base_type::fill_color(*fc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case end_of_markers: break; } } @@ -698,6 +701,7 @@ namespace agg case marker_dash: do { base_type::fill_color(*fc); base_type::line_color(*lc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; case marker_dot: do { base_type::fill_color(*fc); base_type::line_color(*lc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; case marker_pixel: do { base_type::fill_color(*fc); base_type::line_color(*lc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case end_of_markers: break; } } }; diff --git a/agg2/include/agg_renderer_mclip.h b/agg/include/agg_renderer_mclip.h similarity index 81% rename from agg2/include/agg_renderer_mclip.h rename to agg/include/agg_renderer_mclip.h index e4fe12c..96a7d4e 100644 --- a/agg2/include/agg_renderer_mclip.h +++ b/agg/include/agg_renderer_mclip.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -33,14 +33,19 @@ namespace agg public: typedef PixelFormat pixfmt_type; typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::row_data row_data; typedef renderer_base base_ren_type; //-------------------------------------------------------------------- - renderer_mclip(pixfmt_type& ren) : - m_ren(ren), + explicit renderer_mclip(pixfmt_type& pixf) : + m_ren(pixf), m_curr_cb(0), m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax()) + {} + void attach(pixfmt_type& pixf) { + m_ren.attach(pixf); + reset_clipping(true); } //-------------------------------------------------------------------- @@ -52,18 +57,18 @@ namespace agg unsigned height() const { return m_ren.height(); } //-------------------------------------------------------------------- - const rect& 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& 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& 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; } + 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() @@ -71,7 +76,7 @@ namespace agg m_curr_cb = 0; if(m_clip.size()) { - const rect& cb = m_clip[0]; + const rect_i& cb = m_clip[0]; m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2); } } @@ -81,7 +86,7 @@ namespace agg { if(++m_curr_cb < m_clip.size()) { - const rect& cb = m_clip[m_curr_cb]; + const rect_i& cb = m_clip[m_curr_cb]; m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2); return true; } @@ -100,9 +105,9 @@ namespace agg //-------------------------------------------------------------------- void add_clip_box(int x1, int y1, int x2, int y2) { - rect cb(x1, y1, x2, y2); + rect_i cb(x1, y1, x2, y2); cb.normalize(); - if(cb.clip(rect(0, 0, width() - 1, height() - 1))) + 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; @@ -232,7 +237,6 @@ namespace agg while(next_clip_box()); } - //-------------------------------------------------------------------- void blend_solid_hspan(int x, int y, int len, const color_type& c, const cover_type* covers) @@ -257,6 +261,18 @@ namespace agg while(next_clip_box()); } + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, int len, const color_type* colors) + { + first_clip_box(); + do + { + m_ren.copy_color_hspan(x, y, len, colors); + } + while(next_clip_box()); + } + //-------------------------------------------------------------------- void blend_color_hspan(int x, int y, int len, const color_type* colors, @@ -280,32 +296,14 @@ namespace agg first_clip_box(); do { - m_ren.blend_color_hspan(x, y, len, colors, covers, cover); + m_ren.blend_color_vspan(x, y, len, colors, covers, cover); } while(next_clip_box()); } - //-------------------------------------------------------------------- - void blend_color_hspan_no_clip(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) - { - m_ren.blend_color_hspan_no_clip(x, y, len, colors, covers, cover); - } - - //-------------------------------------------------------------------- - void blend_color_vspan_no_clip(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) - { - m_ren.blend_color_vspan_no_clip(x, y, len, colors, covers, cover); - } - //-------------------------------------------------------------------- void copy_from(const rendering_buffer& from, - const rect* rc=0, + const rect_i* rc=0, int x_to=0, int y_to=0) { @@ -316,16 +314,33 @@ namespace agg } while(next_clip_box()); } + + //-------------------------------------------------------------------- + template + 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&); const renderer_mclip& operator = (const renderer_mclip&); - base_ren_type m_ren; - pod_deque m_clip; - unsigned m_curr_cb; - rect m_bounds; + base_ren_type m_ren; + pod_bvector m_clip; + unsigned m_curr_cb; + rect_i m_bounds; }; diff --git a/agg2/include/agg_renderer_outline_aa.h b/agg/include/agg_renderer_outline_aa.h similarity index 75% rename from agg2/include/agg_renderer_outline_aa.h rename to agg/include/agg_renderer_outline_aa.h index 90ade6c..a1a248c 100644 --- a/agg2/include/agg_renderer_outline_aa.h +++ b/agg/include/agg_renderer_outline_aa.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -15,13 +15,15 @@ #ifndef AGG_RENDERER_OUTLINE_AA_INCLUDED #define AGG_RENDERER_OUTLINE_AA_INCLUDED -#include "agg_basics.h" +#include +#include "agg_array.h" #include "agg_math.h" #include "agg_line_aa_basics.h" #include "agg_dda_line.h" #include "agg_ellipse_bresenham.h" #include "agg_renderer_base.h" #include "agg_gamma_functions.h" +#include "agg_clip_liang_barsky.h" namespace agg { @@ -35,8 +37,8 @@ namespace agg distance_interpolator0(int x1, int y1, int x2, int y2, int x, int y) : m_dx(line_mr(x2) - line_mr(x1)), m_dy(line_mr(y2) - line_mr(y1)), - m_dist((line_mr(x + line_subpixel_size/2) - line_mr(x2)) * m_dy - - (line_mr(y + line_subpixel_size/2) - line_mr(y2)) * m_dx) + m_dist((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy - + (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx) { m_dx <<= line_mr_subpixel_shift; m_dy <<= line_mr_subpixel_shift; @@ -44,56 +46,54 @@ namespace agg //--------------------------------------------------------------------- void inc_x() { m_dist += m_dy; } - void dec_x() { m_dist -= m_dy; } - void inc_y() { m_dist -= m_dx; } - void dec_y() { m_dist += m_dx; } - - //--------------------------------------------------------------------- - void inc_x(int dy) - { - m_dist += m_dy; - if(dy > 0) m_dist -= m_dx; - if(dy < 0) m_dist += m_dx; - } - - //--------------------------------------------------------------------- - void dec_x(int dy) - { - m_dist -= m_dy; - if(dy > 0) m_dist -= m_dx; - if(dy < 0) m_dist += m_dx; - } + int dist() const { return m_dist; } + private: //--------------------------------------------------------------------- - void inc_y(int dx) - { - m_dist -= m_dx; - if(dx > 0) m_dist += m_dy; - if(dx < 0) m_dist -= m_dy; - } + int m_dx; + int m_dy; + int m_dist; + }; - void dec_y(int dx) + //==================================================distance_interpolator00 + class distance_interpolator00 + { + public: //--------------------------------------------------------------------- + distance_interpolator00() {} + distance_interpolator00(int xc, int yc, + int x1, int y1, int x2, int y2, + int x, int y) : + m_dx1(line_mr(x1) - line_mr(xc)), + m_dy1(line_mr(y1) - line_mr(yc)), + m_dx2(line_mr(x2) - line_mr(xc)), + m_dy2(line_mr(y2) - line_mr(yc)), + m_dist1((line_mr(x + line_subpixel_scale/2) - line_mr(x1)) * m_dy1 - + (line_mr(y + line_subpixel_scale/2) - line_mr(y1)) * m_dx1), + m_dist2((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy2 - + (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx2) { - m_dist += m_dx; - if(dx > 0) m_dist += m_dy; - if(dx < 0) m_dist -= m_dy; + m_dx1 <<= line_mr_subpixel_shift; + m_dy1 <<= line_mr_subpixel_shift; + m_dx2 <<= line_mr_subpixel_shift; + m_dy2 <<= line_mr_subpixel_shift; } //--------------------------------------------------------------------- - int dist() const { return m_dist; } - int dx() const { return m_dx; } - int dy() const { return m_dy; } + void inc_x() { m_dist1 += m_dy1; m_dist2 += m_dy2; } + int dist1() const { return m_dist1; } + int dist2() const { return m_dist2; } private: //--------------------------------------------------------------------- - int m_dx; - int m_dy; - int m_dist; + int m_dx1; + int m_dy1; + int m_dx2; + int m_dy2; + int m_dist1; + int m_dist2; }; - - //===================================================distance_interpolator1 class distance_interpolator1 { @@ -103,8 +103,8 @@ namespace agg distance_interpolator1(int x1, int y1, int x2, int y2, int x, int y) : m_dx(x2 - x1), m_dy(y2 - y1), - m_dist(int(double(x + line_subpixel_size/2 - x2) * double(m_dy) - - double(y + line_subpixel_size/2 - y2) * double(m_dx))) + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))) { m_dx <<= line_subpixel_shift; m_dy <<= line_subpixel_shift; @@ -177,11 +177,11 @@ namespace agg m_dx_start(line_mr(sx) - line_mr(x1)), m_dy_start(line_mr(sy) - line_mr(y1)), - m_dist(int(double(x + line_subpixel_size/2 - x2) * double(m_dy) - - double(y + line_subpixel_size/2 - y2) * double(m_dx))), + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))), - m_dist_start((line_mr(x + line_subpixel_size/2) - line_mr(sx)) * m_dy_start - - (line_mr(y + line_subpixel_size/2) - line_mr(sy)) * m_dx_start) + m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - + (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start) { m_dx <<= line_subpixel_shift; m_dy <<= line_subpixel_shift; @@ -196,11 +196,11 @@ namespace agg m_dx_start(line_mr(ex) - line_mr(x2)), m_dy_start(line_mr(ey) - line_mr(y2)), - m_dist(int(double(x + line_subpixel_size/2 - x2) * double(m_dy) - - double(y + line_subpixel_size/2 - y2) * double(m_dx))), + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))), - m_dist_start((line_mr(x + line_subpixel_size/2) - line_mr(ex)) * m_dy_start - - (line_mr(y + line_subpixel_size/2) - line_mr(ey)) * m_dx_start) + m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_start - + (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_start) { m_dx <<= line_subpixel_shift; m_dy <<= line_subpixel_shift; @@ -327,14 +327,14 @@ namespace agg m_dx_end(line_mr(ex) - line_mr(x2)), m_dy_end(line_mr(ey) - line_mr(y2)), - m_dist(int(double(x + line_subpixel_size/2 - x2) * double(m_dy) - - double(y + line_subpixel_size/2 - y2) * double(m_dx))), + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))), - m_dist_start((line_mr(x + line_subpixel_size/2) - line_mr(sx)) * m_dy_start - - (line_mr(y + line_subpixel_size/2) - line_mr(sy)) * m_dx_start), + m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - + (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start), - m_dist_end((line_mr(x + line_subpixel_size/2) - line_mr(ex)) * m_dy_end - - (line_mr(y + line_subpixel_size/2) - line_mr(ey)) * m_dx_end) + m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end - + (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end) { m_dx <<= line_subpixel_shift; m_dy <<= line_subpixel_shift; @@ -469,28 +469,29 @@ namespace agg typedef typename Renderer::color_type color_type; //--------------------------------------------------------------------- - enum + enum max_half_width_e { max_half_width = 64 }; //--------------------------------------------------------------------- - line_interpolator_aa_base(renderer_type& ren, const line_parameters& lp) : + line_interpolator_aa_base(renderer_type& ren, line_parameters& lp) : m_lp(&lp), m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) : line_dbl_hr(lp.y2 - lp.y1), - lp.vertical ? abs(lp.y2 - lp.y1) : - abs(lp.x2 - lp.x1) + 1), + lp.vertical ? std::abs(lp.y2 - lp.y1) : + std::abs(lp.x2 - lp.x1) + 1), m_ren(ren), m_len((lp.vertical == (lp.inc > 0)) ? -lp.len : lp.len), m_x(lp.x1 >> line_subpixel_shift), m_y(lp.y1 >> line_subpixel_shift), m_old_x(m_x), m_old_y(m_y), - m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) : - abs((lp.x2 >> line_subpixel_shift) - m_x))), + m_count((lp.vertical ? std::abs((lp.y2 >> line_subpixel_shift) - m_y) : + std::abs((lp.x2 >> line_subpixel_shift) - m_x))), m_width(ren.subpixel_width()), - m_max_extent(m_width >> (line_subpixel_shift - 2)), + //m_max_extent(m_width >> (line_subpixel_shift - 2)), + m_max_extent((m_width + line_subpixel_mask) >> line_subpixel_shift), m_step(0) { agg::dda2_line_interpolator li(0, lp.vertical ? @@ -499,7 +500,7 @@ namespace agg lp.len); unsigned i; - int stop = m_width + line_subpixel_size * 2; + int stop = m_width + line_subpixel_scale * 2; for(i = 0; i < max_half_width; ++i) { m_dist[i] = li.y(); @@ -550,7 +551,7 @@ namespace agg operator = (const line_interpolator_aa_base&); protected: - const line_parameters* m_lp; + line_parameters* m_lp; dda2_line_interpolator m_li; renderer_type& m_ren; int m_len; @@ -582,7 +583,7 @@ namespace agg typedef line_interpolator_aa_base base_type; //--------------------------------------------------------------------- - line_interpolator_aa0(renderer_type& ren, const line_parameters& lp) : + line_interpolator_aa0(renderer_type& ren, line_parameters& lp) : line_interpolator_aa_base(ren, lp), m_di(lp.x1, lp.y1, lp.x2, lp.y2, lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask) @@ -676,7 +677,7 @@ namespace agg typedef line_interpolator_aa_base base_type; //--------------------------------------------------------------------- - line_interpolator_aa1(renderer_type& ren, const line_parameters& lp, + line_interpolator_aa1(renderer_type& ren, line_parameters& lp, int sx, int sy) : line_interpolator_aa_base(ren, lp), m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, @@ -887,7 +888,7 @@ namespace agg typedef line_interpolator_aa_base base_type; //--------------------------------------------------------------------- - line_interpolator_aa2(renderer_type& ren, const line_parameters& lp, + line_interpolator_aa2(renderer_type& ren, line_parameters& lp, int ex, int ey) : line_interpolator_aa_base(ren, lp), m_di(lp.x1, lp.y1, lp.x2, lp.y2, ex, ey, @@ -1036,7 +1037,7 @@ namespace agg typedef line_interpolator_aa_base base_type; //--------------------------------------------------------------------- - line_interpolator_aa3(renderer_type& ren, const line_parameters& lp, + line_interpolator_aa3(renderer_type& ren, line_parameters& lp, int sx, int sy, int ex, int ey) : line_interpolator_aa_base(ren, lp), m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, @@ -1259,40 +1260,33 @@ namespace agg public: //--------------------------------------------------------------------- typedef int8u value_type; - enum + enum subpixel_scale_e { subpixel_shift = line_subpixel_shift, - subpixel_size = 1 << subpixel_shift, - subpixel_mask = subpixel_size - 1 + subpixel_scale = 1 << subpixel_shift, + subpixel_mask = subpixel_scale - 1 }; - enum + enum aa_scale_e { aa_shift = 8, - aa_num = 1 << aa_shift, - aa_mask = aa_num - 1 + aa_scale = 1 << aa_shift, + aa_mask = aa_scale - 1 }; - //--------------------------------------------------------------------- - ~line_profile_aa() { delete [] m_profile; } - //--------------------------------------------------------------------- line_profile_aa() : - m_size(0), - m_profile(0), m_subpixel_width(0), m_min_width(1.0), m_smoother_width(1.0) { int i; - for(i = 0; i < aa_num; i++) m_gamma[i] = (value_type)i; + for(i = 0; i < aa_scale; i++) m_gamma[i] = (value_type)i; } //--------------------------------------------------------------------- template line_profile_aa(double w, const GammaF& gamma_function) : - m_size(0), - m_profile(0), m_subpixel_width(0), m_min_width(1.0), m_smoother_width(1.0) @@ -1309,17 +1303,16 @@ namespace agg template void gamma(const GammaF& gamma_function) { int i; - for(i = 0; i < aa_num; i++) + for(i = 0; i < aa_scale; i++) { m_gamma[i] = value_type( - floor( - gamma_function(double(i) / aa_mask) * aa_mask + 0.5)); + uround(gamma_function(double(i) / aa_mask) * aa_mask)); } } void width(double w); - unsigned profile_size() const { return m_size; } + unsigned profile_size() const { return m_profile.size(); } int subpixel_width() const { return m_subpixel_width; } //--------------------------------------------------------------------- @@ -1329,7 +1322,7 @@ namespace agg //--------------------------------------------------------------------- value_type value(int dist) const { - return m_profile[dist + subpixel_size*2]; + return m_profile[dist + subpixel_scale*2]; } private: @@ -1340,19 +1333,14 @@ namespace agg void set(double center_width, double smoother_width); //--------------------------------------------------------------------- - unsigned m_size; - value_type* m_profile; - value_type m_gamma[aa_num]; - int m_subpixel_width; - double m_min_width; - double m_smoother_width; + pod_array m_profile; + value_type m_gamma[aa_scale]; + int m_subpixel_width; + double m_min_width; + double m_smoother_width; }; - - - - //======================================================renderer_outline_aa template class renderer_outline_aa { @@ -1365,22 +1353,35 @@ namespace agg //--------------------------------------------------------------------- renderer_outline_aa(base_ren_type& ren, line_profile_aa& prof) : m_ren(&ren), - m_profile(&prof) - { - } + m_profile(&prof), + m_clip_box(0,0,0,0), + m_clipping(false) + {} + void attach(base_ren_type& ren) { m_ren = &ren; } //--------------------------------------------------------------------- void color(const color_type& c) { m_color = c; } const color_type& color() const { return m_color; } //--------------------------------------------------------------------- - void profile(const line_profile_aa& prof) { m_profile = &prof; } + void profile(line_profile_aa& prof) { m_profile = &prof; } const line_profile_aa& profile() const { return *m_profile; } line_profile_aa& profile() { return *m_profile; } //--------------------------------------------------------------------- int subpixel_width() const { return m_profile->subpixel_width(); } + //--------------------------------------------------------------------- + void reset_clipping() { m_clipping = false; } + void clip_box(double x1, double y1, double x2, double y2) + { + m_clip_box.x1 = line_coord_sat::conv(x1); + m_clip_box.y1 = line_coord_sat::conv(y1); + m_clip_box.x2 = line_coord_sat::conv(x2); + m_clip_box.y2 = line_coord_sat::conv(y2); + m_clipping = true; + } + //--------------------------------------------------------------------- int cover(int d) const { @@ -1415,8 +1416,8 @@ namespace agg int y = y1 << line_subpixel_shift; int w = subpixel_width(); distance_interpolator0 di(xc1, yc1, xc2, yc2, x, y); - x += line_subpixel_size/2; - y += line_subpixel_size/2; + x += line_subpixel_scale/2; + y += line_subpixel_scale/2; int x0 = x1; int dx = x - xc1; @@ -1430,7 +1431,7 @@ namespace agg *p1 = (cover_type)cover(d); } ++p1; - dx += line_subpixel_size; + dx += line_subpixel_scale; di.inc_x(); } while(++x1 <= x2); @@ -1444,6 +1445,8 @@ namespace agg template void semidot(Cmp cmp, int xc1, int yc1, int xc2, int yc2) { + if(m_clipping && clipping_flags(xc1, yc1, m_clip_box)) return; + int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift); if(r < 1) r = 1; ellipse_bresenham_interpolator ei(r, r); @@ -1473,8 +1476,88 @@ namespace agg } //------------------------------------------------------------------------- - void line0(const line_parameters& lp) + void pie_hline(int xc, int yc, int xp1, int yp1, int xp2, int yp2, + int xh1, int yh1, int xh2) { + if(m_clipping && clipping_flags(xc, yc, m_clip_box)) return; + + cover_type covers[line_interpolator_aa_base::max_half_width * 2 + 4]; + cover_type* p0 = covers; + cover_type* p1 = covers; + int x = xh1 << line_subpixel_shift; + int y = yh1 << line_subpixel_shift; + int w = subpixel_width(); + + distance_interpolator00 di(xc, yc, xp1, yp1, xp2, yp2, x, y); + x += line_subpixel_scale/2; + y += line_subpixel_scale/2; + + int xh0 = xh1; + int dx = x - xc; + int dy = y - yc; + do + { + int d = int(fast_sqrt(dx*dx + dy*dy)); + *p1 = 0; + if(di.dist1() <= 0 && di.dist2() > 0 && d <= w) + { + *p1 = (cover_type)cover(d); + } + ++p1; + dx += line_subpixel_scale; + di.inc_x(); + } + while(++xh1 <= xh2); + m_ren->blend_solid_hspan(xh0, yh1, + unsigned(p1 - p0), + color(), + p0); + } + + + //------------------------------------------------------------------------- + void pie(int xc, int yc, int x1, int y1, int x2, int y2) + { + int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift); + if(r < 1) r = 1; + ellipse_bresenham_interpolator ei(r, r); + int dx = 0; + int dy = -r; + int dy0 = dy; + int dx0 = dx; + int x = xc >> line_subpixel_shift; + int y = yc >> line_subpixel_shift; + + do + { + dx += ei.dx(); + dy += ei.dy(); + + if(dy != dy0) + { + pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0); + pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y-dy0, x+dx0); + } + dx0 = dx; + dy0 = dy; + ++ei; + } + while(dy < 0); + pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0); + } + + //------------------------------------------------------------------------- + void line0_no_clip(line_parameters& lp) + { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + line0_no_clip(lp1); + line0_no_clip(lp2); + return; + } + line_interpolator_aa0 li(*this, lp); if(li.count()) { @@ -1490,8 +1573,48 @@ namespace agg } //------------------------------------------------------------------------- - void line1(const line_parameters& lp, int sx, int sy) + void line0(line_parameters& lp) { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + line0_no_clip(lp2); + } + else + { + line0_no_clip(lp); + } + } + } + else + { + line0_no_clip(lp); + } + } + + //------------------------------------------------------------------------- + void line1_no_clip(line_parameters& lp, int sx, int sy) + { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + line1_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1); + line1_no_clip(lp2, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1)); + return; + } + + fix_degenerate_bisectrix_start(lp, &sx, &sy); line_interpolator_aa1 li(*this, lp, sx, sy); if(li.vertical()) { @@ -1503,9 +1626,63 @@ namespace agg } } + //------------------------------------------------------------------------- - void line2(const line_parameters& lp, int ex, int ey) + void line1(line_parameters& lp, int sx, int sy) { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + if(flags & 1) + { + sx = x1 + (y2 - y1); + sy = y1 - (x2 - x1); + } + else + { + while(std::abs(sx - lp.x1) + std::abs(sy - lp.y1) > lp2.len) + { + sx = (lp.x1 + sx) >> 1; + sy = (lp.y1 + sy) >> 1; + } + } + line1_no_clip(lp2, sx, sy); + } + else + { + line1_no_clip(lp, sx, sy); + } + } + } + else + { + line1_no_clip(lp, sx, sy); + } + } + + //------------------------------------------------------------------------- + void line2_no_clip(line_parameters& lp, int ex, int ey) + { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + line2_no_clip(lp1, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1)); + line2_no_clip(lp2, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); + return; + } + + fix_degenerate_bisectrix_end(lp, &ex, &ey); line_interpolator_aa2 li(*this, lp, ex, ey); if(li.vertical()) { @@ -1518,9 +1695,65 @@ namespace agg } //------------------------------------------------------------------------- - void line3(const line_parameters& lp, - int sx, int sy, int ex, int ey) + void line2(line_parameters& lp, int ex, int ey) + { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + if(flags & 2) + { + ex = x2 + (y2 - y1); + ey = y2 - (x2 - x1); + } + else + { + while(std::abs(ex - lp.x2) + std::abs(ey - lp.y2) > lp2.len) + { + ex = (lp.x2 + ex) >> 1; + ey = (lp.y2 + ey) >> 1; + } + } + line2_no_clip(lp2, ex, ey); + } + else + { + line2_no_clip(lp, ex, ey); + } + } + } + else + { + line2_no_clip(lp, ex, ey); + } + } + + //------------------------------------------------------------------------- + void line3_no_clip(line_parameters& lp, + int sx, int sy, int ex, int ey) { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + int mx = lp1.x2 + (lp1.y2 - lp1.y1); + int my = lp1.y2 - (lp1.x2 - lp1.x1); + line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my); + line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); + return; + } + + fix_degenerate_bisectrix_start(lp, &sx, &sy); + fix_degenerate_bisectrix_end(lp, &ex, &ey); line_interpolator_aa3 li(*this, lp, sx, sy, ex, ey); if(li.vertical()) { @@ -1532,10 +1765,70 @@ namespace agg } } + //------------------------------------------------------------------------- + void line3(line_parameters& lp, + int sx, int sy, int ex, int ey) + { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + if(flags & 1) + { + sx = x1 + (y2 - y1); + sy = y1 - (x2 - x1); + } + else + { + while(std::abs(sx - lp.x1) + std::abs(sy - lp.y1) > lp2.len) + { + sx = (lp.x1 + sx) >> 1; + sy = (lp.y1 + sy) >> 1; + } + } + if(flags & 2) + { + ex = x2 + (y2 - y1); + ey = y2 - (x2 - x1); + } + else + { + while(std::abs(ex - lp.x2) + std::abs(ey - lp.y2) > lp2.len) + { + ex = (lp.x2 + ex) >> 1; + ey = (lp.y2 + ey) >> 1; + } + } + line3_no_clip(lp2, sx, sy, ex, ey); + } + else + { + line3_no_clip(lp, sx, sy, ex, ey); + } + } + } + else + { + line3_no_clip(lp, sx, sy, ex, ey); + } + } + + private: - base_ren_type* m_ren; + base_ren_type* m_ren; line_profile_aa* m_profile; - color_type m_color; + color_type m_color; + rect_i m_clip_box; + bool m_clipping; }; diff --git a/agg2/include/agg_renderer_outline_image.h b/agg/include/agg_renderer_outline_image.h similarity index 73% rename from agg2/include/agg_renderer_outline_image.h rename to agg/include/agg_renderer_outline_image.h index 79a2c14..7ecded5 100644 --- a/agg2/include/agg_renderer_outline_image.h +++ b/agg/include/agg_renderer_outline_image.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -15,10 +15,13 @@ #ifndef AGG_RENDERER_OUTLINE_IMAGE_INCLUDED #define AGG_RENDERER_OUTLINE_IMAGE_INCLUDED -#include +#include +#include "agg_array.h" +#include "agg_math.h" #include "agg_line_aa_basics.h" #include "agg_dda_line.h" #include "agg_rendering_buffer.h" +#include "agg_clip_liang_barsky.h" namespace agg @@ -32,7 +35,8 @@ namespace agg line_image_scale(const Source& src, double height) : m_source(src), m_height(height), - m_scale(src.height() / height) + m_scale(src.height() / height), + m_scale_inv(height / src.height()) { } @@ -41,13 +45,34 @@ namespace agg color_type pixel(int x, int y) const { - double src_y = y * m_scale; - int h = int(m_source.height()) - 1; - int y1 = int(floor(src_y)); - int y2 = y1 + 1; - color_type pix1 = (y1 < 0) ? m_source.pixel(x, 0).transparent() : m_source.pixel(x, y1); - color_type pix2 = (y2 > h) ? m_source.pixel(x, h).transparent() : m_source.pixel(x, y2); - return pix1.gradient(pix2, src_y - y1); + if (m_scale < 1.0) + { + // Interpolate between nearest source pixels. + double src_y = (y + 0.5) * m_scale - 0.5; + int h = m_source.height() - 1; + int y1 = ifloor(src_y); + int y2 = y1 + 1; + rgba pix1 = (y1 < 0) ? rgba::no_color() : rgba(m_source.pixel(x, y1)); + rgba pix2 = (y2 > h) ? rgba::no_color() : rgba(m_source.pixel(x, y2)); + return pix1.gradient(pix2, src_y - y1); + } + else + { + // Average source pixels between y and y+1. + double src_y1 = (y + 0.5) * m_scale - 0.5; + double src_y2 = src_y1 + m_scale; + int h = m_source.height() - 1; + int y1 = ifloor(src_y1); + int y2 = ifloor(src_y2); + rgba c = rgba::no_color(); + if (y1 >= 0) c += rgba(m_source.pixel(x, y1)) *= y1 + 1 - src_y1; + while (++y1 < y2) + { + if (y1 <= h) c += m_source.pixel(x, y1); + } + if (y2 <= h) c += rgba(m_source.pixel(x, y2)) *= src_y2 - y2; + return c *= m_scale_inv; + } } private: @@ -57,6 +82,7 @@ namespace agg const Source& m_source; double m_height; double m_scale; + double m_scale_inv; }; @@ -69,17 +95,11 @@ namespace agg typedef typename filter_type::color_type color_type; //-------------------------------------------------------------------- - ~line_image_pattern() - { - delete [] m_data; - } - - //-------------------------------------------------------------------- - line_image_pattern(const Filter& filter) : + line_image_pattern(Filter& filter) : m_filter(&filter), m_dilation(filter.dilation() + 1), m_dilation_hr(m_dilation << line_subpixel_shift), - m_data(0), + m_data(), m_width(0), m_height(0), m_width_hr(0), @@ -91,11 +111,11 @@ namespace agg // Create //-------------------------------------------------------------------- template - line_image_pattern(const Filter& filter, const Source& src) : + line_image_pattern(Filter& filter, const Source& src) : m_filter(&filter), m_dilation(filter.dilation() + 1), m_dilation_hr(m_dilation << line_subpixel_shift), - m_data(0), + m_data(), m_width(0), m_height(0), m_width_hr(0), @@ -109,25 +129,24 @@ namespace agg //-------------------------------------------------------------------- template void create(const Source& src) { - m_height = unsigned(ceil((double)src.height())); - m_width = unsigned(ceil((double)src.width())); - m_width_hr = int(src.width() * line_subpixel_size); - m_half_height_hr = int(src.height() * line_subpixel_size/2); - m_offset_y_hr = m_dilation_hr + m_half_height_hr - line_subpixel_size/2; - m_half_height_hr += line_subpixel_size/2; - - delete [] m_data; - m_data = new color_type [(m_width + m_dilation * 2) * (m_height + m_dilation * 2)]; - - m_buf.attach(m_data, m_width + m_dilation * 2, - m_height + m_dilation * 2, - m_width + m_dilation * 2); + m_height = uceil(src.height()); + m_width = uceil(src.width()); + m_width_hr = uround(src.width() * line_subpixel_scale); + m_half_height_hr = uround(src.height() * line_subpixel_scale/2); + m_offset_y_hr = m_dilation_hr + m_half_height_hr - line_subpixel_scale/2; + m_half_height_hr += line_subpixel_scale/2; + + m_data.resize((m_width + m_dilation * 2) * (m_height + m_dilation * 2)); + + m_buf.attach(&m_data[0], m_width + m_dilation * 2, + m_height + m_dilation * 2, + m_width + m_dilation * 2); unsigned x, y; color_type* d1; color_type* d2; for(y = 0; y < m_height; y++) { - d1 = m_buf.row(y + m_dilation) + m_dilation; + d1 = m_buf.row_ptr(y + m_dilation) + m_dilation; for(x = 0; x < m_width; x++) { *d1++ = src.pixel(x, y); @@ -138,24 +157,26 @@ namespace agg const color_type* s2; for(y = 0; y < m_dilation; y++) { - s1 = m_buf.row(m_height + m_dilation - 1) + m_dilation; - s2 = m_buf.row(m_dilation) + m_dilation; - d1 = m_buf.row(m_dilation + m_height + y) + m_dilation; - d2 = m_buf.row(m_dilation - y - 1) + m_dilation; + //s1 = m_buf.row_ptr(m_height + m_dilation - 1) + m_dilation; + //s2 = m_buf.row_ptr(m_dilation) + m_dilation; + d1 = m_buf.row_ptr(m_dilation + m_height + y) + m_dilation; + d2 = m_buf.row_ptr(m_dilation - y - 1) + m_dilation; for(x = 0; x < m_width; x++) { - *d1++ = color_type(*s1++, 0); - *d2++ = color_type(*s2++, 0); + //*d1++ = color_type(*s1++, 0); + //*d2++ = color_type(*s2++, 0); + *d1++ = color_type::no_color(); + *d2++ = color_type::no_color(); } } unsigned h = m_height + m_dilation * 2; for(y = 0; y < h; y++) { - s1 = m_buf.row(y) + m_dilation; - s2 = m_buf.row(y) + m_dilation + m_width; - d1 = m_buf.row(y) + m_dilation + m_width; - d2 = m_buf.row(y) + m_dilation; + s1 = m_buf.row_ptr(y) + m_dilation; + s2 = m_buf.row_ptr(y) + m_dilation + m_width; + d1 = m_buf.row_ptr(y) + m_dilation + m_width; + d2 = m_buf.row_ptr(y) + m_dilation; for(x = 0; x < m_dilation; x++) { @@ -168,18 +189,19 @@ namespace agg //-------------------------------------------------------------------- int pattern_width() const { return m_width_hr; } int line_width() const { return m_half_height_hr; } + double width() const { return m_height; } //-------------------------------------------------------------------- - color_type pixel(int x, int y) const + void pixel(color_type* p, int x, int y) const { - return m_filter->pixel_high_res(m_buf.rows(), - x % m_width_hr + m_dilation_hr, - y + m_offset_y_hr); + m_filter->pixel_high_res(m_buf.rows(), + p, + x % m_width_hr + m_dilation_hr, + y + m_offset_y_hr); } //-------------------------------------------------------------------- - const filter_type& filter() const { return m_filter; } - filter_type& filter() { return m_filter; } + const filter_type& filter() const { return *m_filter; } private: line_image_pattern(const line_image_pattern&); @@ -191,7 +213,7 @@ namespace agg const filter_type* m_filter; unsigned m_dilation; int m_dilation_hr; - color_type* m_data; + pod_array m_data; unsigned m_width; unsigned m_height; int m_width_hr; @@ -212,14 +234,14 @@ namespace agg typedef Filter filter_type; typedef typename filter_type::color_type color_type; typedef line_image_pattern base_type; - + //-------------------------------------------------------------------- - line_image_pattern_pow2(const Filter& filter) : + line_image_pattern_pow2(Filter& filter) : line_image_pattern(filter), m_mask(line_subpixel_mask) {} //-------------------------------------------------------------------- template - line_image_pattern_pow2(const Filter& filter, const Source& src) : + line_image_pattern_pow2(Filter& filter, const Source& src) : line_image_pattern(filter), m_mask(line_subpixel_mask) { create(src); @@ -275,23 +297,23 @@ namespace agg m_dx_end(line_mr(ex) - line_mr(x2)), m_dy_end(line_mr(ey) - line_mr(y2)), - m_dist(int(double(x + line_subpixel_size/2 - x2) * double(m_dy) - - double(y + line_subpixel_size/2 - y2) * double(m_dx))), + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))), - m_dist_start((line_mr(x + line_subpixel_size/2) - line_mr(sx)) * m_dy_start - - (line_mr(y + line_subpixel_size/2) - line_mr(sy)) * m_dx_start), + m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - + (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start), - m_dist_end((line_mr(x + line_subpixel_size/2) - line_mr(ex)) * m_dy_end - - (line_mr(y + line_subpixel_size/2) - line_mr(ey)) * m_dx_end), - m_len(int(len / scale)) + m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end - + (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end), + m_len(uround(len / scale)) { double d = len * scale; - int dx = int(((x2 - x1) << line_subpixel_shift) / d); - int dy = int(((y2 - y1) << line_subpixel_shift) / d); + int dx = iround(((x2 - x1) << line_subpixel_shift) / d); + int dy = iround(((y2 - y1) << line_subpixel_shift) / d); m_dx_pict = -dy; m_dy_pict = dx; - m_dist_pict = ((x + line_subpixel_size/2 - (x1 - dy)) * m_dy_pict - - (y + line_subpixel_size/2 - (y1 + dx)) * m_dx_pict) >> + m_dist_pict = ((x + line_subpixel_scale/2 - (x1 - dy)) * m_dy_pict - + (y + line_subpixel_scale/2 - (y1 + dx)) * m_dx_pict) >> line_subpixel_shift; m_dx <<= line_subpixel_shift; @@ -477,7 +499,7 @@ namespace agg typedef typename Renderer::color_type color_type; //--------------------------------------------------------------------- - enum + enum max_half_width_e { max_half_width = 64 }; @@ -490,8 +512,8 @@ namespace agg m_lp(lp), m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) : line_dbl_hr(lp.y2 - lp.y1), - lp.vertical ? abs(lp.y2 - lp.y1) : - abs(lp.x2 - lp.x1) + 1), + lp.vertical ? std::abs(lp.y2 - lp.y1) : + std::abs(lp.x2 - lp.x1) + 1), m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, lp.len, scale_x, lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask), m_ren(ren), @@ -499,10 +521,11 @@ namespace agg m_y(lp.y1 >> line_subpixel_shift), m_old_x(m_x), m_old_y(m_y), - m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) : - abs((lp.x2 >> line_subpixel_shift) - m_x))), + m_count((lp.vertical ? std::abs((lp.y2 >> line_subpixel_shift) - m_y) : + std::abs((lp.x2 >> line_subpixel_shift) - m_x))), m_width(ren.subpixel_width()), - m_max_extent(m_width >> (line_subpixel_shift - 2)), + //m_max_extent(m_width >> (line_subpixel_shift - 2)), + m_max_extent((m_width + line_subpixel_scale) >> line_subpixel_shift), m_start(pattern_start + (m_max_extent + 2) * ren.pattern_width()), m_step(0) { @@ -512,7 +535,7 @@ namespace agg lp.len); unsigned i; - int stop = m_width + line_subpixel_size * 2; + int stop = m_width + line_subpixel_scale * 2; for(i = 0; i < max_half_width; ++i) { m_dist_pos[i] = li.y(); @@ -817,25 +840,43 @@ namespace agg //--------------------------------------------------------------------- - renderer_outline_image(base_ren_type& ren, const pattern_type& patt) : + renderer_outline_image(base_ren_type& ren, pattern_type& patt) : m_ren(&ren), m_pattern(&patt), m_start(0), - m_scale_x(1.0) + m_scale_x(1.0), + m_clip_box(0,0,0,0), + m_clipping(false) + {} + void attach(base_ren_type& ren) { m_ren = &ren; } + + //--------------------------------------------------------------------- + void pattern(pattern_type& p) { m_pattern = &p; } + pattern_type& pattern() const { return *m_pattern; } + + //--------------------------------------------------------------------- + void reset_clipping() { m_clipping = false; } + void clip_box(double x1, double y1, double x2, double y2) { + m_clip_box.x1 = line_coord_sat::conv(x1); + m_clip_box.y1 = line_coord_sat::conv(y1); + m_clip_box.x2 = line_coord_sat::conv(x2); + m_clip_box.y2 = line_coord_sat::conv(y2); + m_clipping = true; } //--------------------------------------------------------------------- - void pattern(const pattern_type& p) { m_pattern = &p; } - const pattern_type& pattern() const { return *m_pattern; } + void scale_x(double s) { m_scale_x = s; } + double scale_x() const { return m_scale_x; } //--------------------------------------------------------------------- - void scale_x(double s) { m_scale_x = s; } - double scale_x() const { return m_scale_x; } + void start_x(double s) { m_start = iround(s * line_subpixel_scale); } + double start_x() const { return double(m_start) / line_subpixel_scale; } //--------------------------------------------------------------------- int subpixel_width() const { return m_pattern->line_width(); } int pattern_width() const { return m_pattern->pattern_width(); } + double width() const { return double(subpixel_width()) / line_subpixel_scale; } //------------------------------------------------------------------------- void pixel(color_type* p, int x, int y) const @@ -864,6 +905,11 @@ namespace agg { } + //------------------------------------------------------------------------- + void pie(int, int, int, int, int, int) + { + } + //------------------------------------------------------------------------- void line0(const line_parameters&) { @@ -880,9 +926,22 @@ namespace agg } //------------------------------------------------------------------------- - void line3(const line_parameters& lp, - int sx, int sy, int ex, int ey) + void line3_no_clip(const line_parameters& lp, + int sx, int sy, int ex, int ey) { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + int mx = lp1.x2 + (lp1.y2 - lp1.y1); + int my = lp1.y2 - (lp1.x2 - lp1.x1); + line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my); + line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); + return; + } + + fix_degenerate_bisectrix_start(lp, &sx, &sy); + fix_degenerate_bisectrix_end(lp, &ex, &ey); line_interpolator_image li(*this, lp, sx, sy, ex, ey, @@ -895,14 +954,76 @@ namespace agg { while(li.step_hor()); } - m_start = li.pattern_end(); + m_start += uround(lp.len / m_scale_x); + } + + //------------------------------------------------------------------------- + void line3(const line_parameters& lp, + int sx, int sy, int ex, int ey) + { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + int start = m_start; + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + if(flags & 1) + { + m_start += uround(calc_distance(lp.x1, lp.y1, x1, y1) / m_scale_x); + sx = x1 + (y2 - y1); + sy = y1 - (x2 - x1); + } + else + { + while(std::abs(sx - lp.x1) + std::abs(sy - lp.y1) > lp2.len) + { + sx = (lp.x1 + sx) >> 1; + sy = (lp.y1 + sy) >> 1; + } + } + if(flags & 2) + { + ex = x2 + (y2 - y1); + ey = y2 - (x2 - x1); + } + else + { + while(std::abs(ex - lp.x2) + std::abs(ey - lp.y2) > lp2.len) + { + ex = (lp.x2 + ex) >> 1; + ey = (lp.y2 + ey) >> 1; + } + } + line3_no_clip(lp2, sx, sy, ex, ey); + } + else + { + line3_no_clip(lp, sx, sy, ex, ey); + } + } + m_start = start + uround(lp.len / m_scale_x); + } + else + { + line3_no_clip(lp, sx, sy, ex, ey); + } } private: base_ren_type* m_ren; - const pattern_type* m_pattern; + pattern_type* m_pattern; int m_start; double m_scale_x; + rect_i m_clip_box; + bool m_clipping; }; diff --git a/agg2/include/agg_renderer_primitives.h b/agg/include/agg_renderer_primitives.h similarity index 96% rename from agg2/include/agg_renderer_primitives.h rename to agg/include/agg_renderer_primitives.h index 502599b..f008db7 100644 --- a/agg2/include/agg_renderer_primitives.h +++ b/agg/include/agg_renderer_primitives.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -35,19 +35,19 @@ namespace agg typedef typename base_ren_type::color_type color_type; //-------------------------------------------------------------------- - renderer_primitives(base_ren_type& ren) : + 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 int(c * line_bresenham_interpolator::subpixel_size); + return iround(c * line_bresenham_interpolator::subpixel_scale); } //-------------------------------------------------------------------- diff --git a/agg2/include/agg_renderer_raster_text.h b/agg/include/agg_renderer_raster_text.h similarity index 97% rename from agg2/include/agg_renderer_raster_text.h rename to agg/include/agg_renderer_raster_text.h index 366f6d1..87b43f9 100644 --- a/agg2/include/agg_renderer_raster_text.h +++ b/agg/include/agg_renderer_raster_text.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -34,8 +34,8 @@ namespace agg 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; } @@ -219,7 +219,7 @@ namespace agg m_glyph->prepare(&r, x, y, *str, flip); if(r.x2 >= r.x1) { - m_ren->prepare(r.x2 - r.x1 + 1); + m_ren->prepare(); int i; if(flip) { diff --git a/agg/include/agg_renderer_scanline.h b/agg/include/agg_renderer_scanline.h new file mode 100644 index 0000000..47d6f11 --- /dev/null +++ b/agg/include/agg_renderer_scanline.h @@ -0,0 +1,855 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERER_SCANLINE_INCLUDED +#define AGG_RENDERER_SCANLINE_INCLUDED + +#include +#include +#include +#include "agg_basics.h" +#include "agg_renderer_base.h" + +namespace agg +{ + + //================================================render_scanline_aa_solid + template + void render_scanline_aa_solid(const Scanline& sl, + BaseRenderer& ren, + const ColorT& color) + { + int y = sl.y(); + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + + for(;;) + { + int x = span->x; + if(span->len > 0) + { + ren.blend_solid_hspan(x, y, (unsigned)span->len, + color, + span->covers); + } + else + { + ren.blend_hline(x, y, (unsigned)(x - span->len - 1), + color, + *(span->covers)); + } + if(--num_spans == 0) break; + ++span; + } + } + + //===============================================render_scanlines_aa_solid + template + void render_scanlines_aa_solid(Rasterizer& ras, Scanline& sl, + BaseRenderer& ren, const ColorT& color) + { + if(ras.rewind_scanlines()) + { + // Explicitly convert "color" to the BaseRenderer color type. + // For example, it can be called with color type "rgba", while + // "rgba8" is needed. Otherwise it will be implicitly + // converted in the loop many times. + //---------------------- + typename BaseRenderer::color_type ren_color = color; + + sl.reset(ras.min_x(), ras.max_x()); + while(ras.sweep_scanline(sl)) + { + //render_scanline_aa_solid(sl, ren, ren_color); + + // This code is equivalent to the above call (copy/paste). + // It's just a "manual" optimization for old compilers, + // like Microsoft Visual C++ v6.0 + //------------------------------- + int y = sl.y(); + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + + for(;;) + { + int x = span->x; + if(span->len > 0) + { + ren.blend_solid_hspan(x, y, (unsigned)span->len, + ren_color, + span->covers); + } + else + { + ren.blend_hline(x, y, (unsigned)(x - span->len - 1), + ren_color, + *(span->covers)); + } + if(--num_spans == 0) break; + ++span; + } + } + } + } + + //==============================================renderer_scanline_aa_solid + template class renderer_scanline_aa_solid + { + public: + typedef BaseRenderer base_ren_type; + typedef typename base_ren_type::color_type color_type; + + //-------------------------------------------------------------------- + renderer_scanline_aa_solid() : m_ren(0) {} + explicit renderer_scanline_aa_solid(base_ren_type& ren) : m_ren(&ren) {} + void attach(base_ren_type& ren) + { + m_ren = &ren; + } + + //-------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + template void render(const Scanline& sl) + { + render_scanline_aa_solid(sl, *m_ren, m_color); + } + + private: + base_ren_type* m_ren; + color_type m_color; + }; + + + + + + + + + + + + + + //======================================================render_scanline_aa + template + void render_scanline_aa(const Scanline& sl, BaseRenderer& ren, + SpanAllocator& alloc, SpanGenerator& span_gen) + { + int y = sl.y(); + + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + for(;;) + { + int x = span->x; + int len = span->len; + const typename Scanline::cover_type* covers = span->covers; + + if(len < 0) len = -len; + typename BaseRenderer::color_type* colors = alloc.allocate(len); + span_gen.generate(colors, x, y, len); + ren.blend_color_hspan(x, y, len, colors, + (span->len < 0) ? 0 : covers, *covers); + + if(--num_spans == 0) break; + ++span; + } + } + + //=====================================================render_scanlines_aa + template + void render_scanlines_aa(Rasterizer& ras, Scanline& sl, BaseRenderer& ren, + SpanAllocator& alloc, SpanGenerator& span_gen) + { + if(ras.rewind_scanlines()) + { + sl.reset(ras.min_x(), ras.max_x()); + span_gen.prepare(); + while(ras.sweep_scanline(sl)) + { + render_scanline_aa(sl, ren, alloc, span_gen); + } + } + } + + //====================================================renderer_scanline_aa + template + class renderer_scanline_aa + { + public: + typedef BaseRenderer base_ren_type; + typedef SpanAllocator alloc_type; + typedef SpanGenerator span_gen_type; + + //-------------------------------------------------------------------- + renderer_scanline_aa() : m_ren(0), m_alloc(0), m_span_gen(0) {} + renderer_scanline_aa(base_ren_type& ren, + alloc_type& alloc, + span_gen_type& span_gen) : + m_ren(&ren), + m_alloc(&alloc), + m_span_gen(&span_gen) + {} + void attach(base_ren_type& ren, + alloc_type& alloc, + span_gen_type& span_gen) + { + m_ren = &ren; + m_alloc = &alloc; + m_span_gen = &span_gen; + } + + //-------------------------------------------------------------------- + void prepare() { m_span_gen->prepare(); } + + //-------------------------------------------------------------------- + template void render(const Scanline& sl) + { + render_scanline_aa(sl, *m_ren, *m_alloc, *m_span_gen); + } + + private: + base_ren_type* m_ren; + alloc_type* m_alloc; + span_gen_type* m_span_gen; + }; + + + + + + + //===============================================render_scanline_bin_solid + template + void render_scanline_bin_solid(const Scanline& sl, + BaseRenderer& ren, + const ColorT& color) + { + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + for(;;) + { + ren.blend_hline(span->x, + sl.y(), + span->x - 1 + ((span->len < 0) ? + -span->len : + span->len), + color, + cover_full); + if(--num_spans == 0) break; + ++span; + } + } + + //==============================================render_scanlines_bin_solid + template + void render_scanlines_bin_solid(Rasterizer& ras, Scanline& sl, + BaseRenderer& ren, const ColorT& color) + { + if(ras.rewind_scanlines()) + { + // Explicitly convert "color" to the BaseRenderer color type. + // For example, it can be called with color type "rgba", while + // "rgba8" is needed. Otherwise it will be implicitly + // converted in the loop many times. + //---------------------- + typename BaseRenderer::color_type ren_color(color); + + sl.reset(ras.min_x(), ras.max_x()); + while(ras.sweep_scanline(sl)) + { + //render_scanline_bin_solid(sl, ren, ren_color); + + // This code is equivalent to the above call (copy/paste). + // It's just a "manual" optimization for old compilers, + // like Microsoft Visual C++ v6.0 + //------------------------------- + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + for(;;) + { + ren.blend_hline(span->x, + sl.y(), + span->x - 1 + ((span->len < 0) ? + -span->len : + span->len), + ren_color, + cover_full); + if(--num_spans == 0) break; + ++span; + } + } + } + } + + //=============================================renderer_scanline_bin_solid + template class renderer_scanline_bin_solid + { + public: + typedef BaseRenderer base_ren_type; + typedef typename base_ren_type::color_type color_type; + + //-------------------------------------------------------------------- + renderer_scanline_bin_solid() : m_ren(0) {} + explicit renderer_scanline_bin_solid(base_ren_type& ren) : m_ren(&ren) {} + void attach(base_ren_type& ren) + { + m_ren = &ren; + } + + //-------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + template void render(const Scanline& sl) + { + render_scanline_bin_solid(sl, *m_ren, m_color); + } + + private: + base_ren_type* m_ren; + color_type m_color; + }; + + + + + + + + + //======================================================render_scanline_bin + template + void render_scanline_bin(const Scanline& sl, BaseRenderer& ren, + SpanAllocator& alloc, SpanGenerator& span_gen) + { + int y = sl.y(); + + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + for(;;) + { + int x = span->x; + int len = span->len; + if(len < 0) len = -len; + typename BaseRenderer::color_type* colors = alloc.allocate(len); + span_gen.generate(colors, x, y, len); + ren.blend_color_hspan(x, y, len, colors, 0, cover_full); + if(--num_spans == 0) break; + ++span; + } + } + + //=====================================================render_scanlines_bin + template + void render_scanlines_bin(Rasterizer& ras, Scanline& sl, BaseRenderer& ren, + SpanAllocator& alloc, SpanGenerator& span_gen) + { + if(ras.rewind_scanlines()) + { + sl.reset(ras.min_x(), ras.max_x()); + span_gen.prepare(); + while(ras.sweep_scanline(sl)) + { + render_scanline_bin(sl, ren, alloc, span_gen); + } + } + } + + //====================================================renderer_scanline_bin + template + class renderer_scanline_bin + { + public: + typedef BaseRenderer base_ren_type; + typedef SpanAllocator alloc_type; + typedef SpanGenerator span_gen_type; + + //-------------------------------------------------------------------- + renderer_scanline_bin() : m_ren(0), m_alloc(0), m_span_gen(0) {} + renderer_scanline_bin(base_ren_type& ren, + alloc_type& alloc, + span_gen_type& span_gen) : + m_ren(&ren), + m_alloc(&alloc), + m_span_gen(&span_gen) + {} + void attach(base_ren_type& ren, + alloc_type& alloc, + span_gen_type& span_gen) + { + m_ren = &ren; + m_alloc = &alloc; + m_span_gen = &span_gen; + } + + //-------------------------------------------------------------------- + void prepare() { m_span_gen->prepare(); } + + //-------------------------------------------------------------------- + template void render(const Scanline& sl) + { + render_scanline_bin(sl, *m_ren, *m_alloc, *m_span_gen); + } + + private: + base_ren_type* m_ren; + alloc_type* m_alloc; + span_gen_type* m_span_gen; + }; + + + + + + + + + + + //========================================================render_scanlines + template + void render_scanlines(Rasterizer& ras, Scanline& sl, Renderer& ren) + { + if(ras.rewind_scanlines()) + { + sl.reset(ras.min_x(), ras.max_x()); + ren.prepare(); + while(ras.sweep_scanline(sl)) + { + ren.render(sl); + } + } + } + + //========================================================render_all_paths + template + void render_all_paths(Rasterizer& ras, + Scanline& sl, + Renderer& r, + VertexSource& vs, + const ColorStorage& as, + const PathId& path_id, + unsigned num_paths) + { + for(unsigned i = 0; i < num_paths; i++) + { + ras.reset(); + ras.add_path(vs, path_id[i]); + r.color(as[i]); + render_scanlines(ras, sl, r); + } + } + + + + + + + //=============================================render_scanlines_compound + template + void render_scanlines_compound(Rasterizer& ras, + ScanlineAA& sl_aa, + ScanlineBin& sl_bin, + BaseRenderer& ren, + SpanAllocator& alloc, + StyleHandler& sh) + { + if(ras.rewind_scanlines()) + { + int min_x = ras.min_x(); + int len = ras.max_x() - min_x + 2; + sl_aa.reset(min_x, ras.max_x()); + sl_bin.reset(min_x, ras.max_x()); + + typedef typename BaseRenderer::color_type color_type; + color_type* color_span = alloc.allocate(len * 2); + color_type* mix_buffer = color_span + len; + unsigned num_spans; + + unsigned num_styles; + unsigned style; + bool solid; + while((num_styles = ras.sweep_styles()) > 0) + { + typename ScanlineAA::const_iterator span_aa; + if(num_styles == 1) + { + // Optimization for a single style. Happens often + //------------------------- + if(ras.sweep_scanline(sl_aa, 0)) + { + style = ras.style(0); + if(sh.is_solid(style)) + { + // Just solid fill + //----------------------- + render_scanline_aa_solid(sl_aa, ren, sh.color(style)); + } + else + { + // Arbitrary span generator + //----------------------- + span_aa = sl_aa.begin(); + num_spans = sl_aa.num_spans(); + for(;;) + { + len = span_aa->len; + sh.generate_span(color_span, + span_aa->x, + sl_aa.y(), + len, + style); + + ren.blend_color_hspan(span_aa->x, + sl_aa.y(), + span_aa->len, + color_span, + span_aa->covers); + if(--num_spans == 0) break; + ++span_aa; + } + } + } + } + else + { + if(ras.sweep_scanline(sl_bin, -1)) + { + // Clear the spans of the mix_buffer + //-------------------- + typename ScanlineBin::const_iterator span_bin = sl_bin.begin(); + num_spans = sl_bin.num_spans(); + for(;;) + { + std::memset(mix_buffer + span_bin->x - min_x, + 0, + span_bin->len * sizeof(color_type)); + + if(--num_spans == 0) break; + ++span_bin; + } + + unsigned i; + for(i = 0; i < num_styles; i++) + { + style = ras.style(i); + solid = sh.is_solid(style); + + if(ras.sweep_scanline(sl_aa, i)) + { + color_type* colors; + color_type* cspan; + typename ScanlineAA::cover_type* covers; + span_aa = sl_aa.begin(); + num_spans = sl_aa.num_spans(); + if(solid) + { + // Just solid fill + //----------------------- + for(;;) + { + color_type c = sh.color(style); + len = span_aa->len; + colors = mix_buffer + span_aa->x - min_x; + covers = span_aa->covers; + do + { + if(*covers == cover_full) + { + *colors = c; + } + else + { + colors->add(c, *covers); + } + ++colors; + ++covers; + } + while(--len); + if(--num_spans == 0) break; + ++span_aa; + } + } + else + { + // Arbitrary span generator + //----------------------- + for(;;) + { + len = span_aa->len; + colors = mix_buffer + span_aa->x - min_x; + cspan = color_span; + sh.generate_span(cspan, + span_aa->x, + sl_aa.y(), + len, + style); + covers = span_aa->covers; + do + { + if(*covers == cover_full) + { + *colors = *cspan; + } + else + { + colors->add(*cspan, *covers); + } + ++cspan; + ++colors; + ++covers; + } + while(--len); + if(--num_spans == 0) break; + ++span_aa; + } + } + } + } + + // Emit the blended result as a color hspan + //------------------------- + span_bin = sl_bin.begin(); + num_spans = sl_bin.num_spans(); + for(;;) + { + ren.blend_color_hspan(span_bin->x, + sl_bin.y(), + span_bin->len, + mix_buffer + span_bin->x - min_x, + 0, + cover_full); + if(--num_spans == 0) break; + ++span_bin; + } + } // if(ras.sweep_scanline(sl_bin, -1)) + } // if(num_styles == 1) ... else + } // while((num_styles = ras.sweep_styles()) > 0) + } // if(ras.rewind_scanlines()) + } + + //=======================================render_scanlines_compound_layered + template + void render_scanlines_compound_layered(Rasterizer& ras, + ScanlineAA& sl_aa, + BaseRenderer& ren, + SpanAllocator& alloc, + StyleHandler& sh) + { + if(ras.rewind_scanlines()) + { + int min_x = ras.min_x(); + int len = ras.max_x() - min_x + 2; + sl_aa.reset(min_x, ras.max_x()); + + typedef typename BaseRenderer::color_type color_type; + color_type* color_span = alloc.allocate(len * 2); + color_type* mix_buffer = color_span + len; + cover_type* cover_buffer = ras.allocate_cover_buffer(len); + unsigned num_spans; + + unsigned num_styles; + unsigned style; + bool solid; + while((num_styles = ras.sweep_styles()) > 0) + { + typename ScanlineAA::const_iterator span_aa; + if(num_styles == 1) + { + // Optimization for a single style. Happens often + //------------------------- + if(ras.sweep_scanline(sl_aa, 0)) + { + style = ras.style(0); + if(sh.is_solid(style)) + { + // Just solid fill + //----------------------- + render_scanline_aa_solid(sl_aa, ren, sh.color(style)); + } + else + { + // Arbitrary span generator + //----------------------- + span_aa = sl_aa.begin(); + num_spans = sl_aa.num_spans(); + for(;;) + { + len = span_aa->len; + sh.generate_span(color_span, + span_aa->x, + sl_aa.y(), + len, + style); + + ren.blend_color_hspan(span_aa->x, + sl_aa.y(), + span_aa->len, + color_span, + span_aa->covers); + if(--num_spans == 0) break; + ++span_aa; + } + } + } + } + else + { + int sl_start = ras.scanline_start(); + unsigned sl_len = ras.scanline_length(); + + if(sl_len) + { + std::memset(mix_buffer + sl_start - min_x, + 0, + sl_len * sizeof(color_type)); + + std::memset(cover_buffer + sl_start - min_x, + 0, + sl_len * sizeof(cover_type)); + + int sl_y = std::numeric_limits::max(); + unsigned i; + for(i = 0; i < num_styles; i++) + { + style = ras.style(i); + solid = sh.is_solid(style); + + if(ras.sweep_scanline(sl_aa, i)) + { + unsigned cover; + color_type* colors; + color_type* cspan; + cover_type* src_covers; + cover_type* dst_covers; + span_aa = sl_aa.begin(); + num_spans = sl_aa.num_spans(); + sl_y = sl_aa.y(); + if(solid) + { + // Just solid fill + //----------------------- + for(;;) + { + color_type c = sh.color(style); + len = span_aa->len; + colors = mix_buffer + span_aa->x - min_x; + src_covers = span_aa->covers; + dst_covers = cover_buffer + span_aa->x - min_x; + do + { + cover = *src_covers; + if(*dst_covers + cover > cover_full) + { + cover = cover_full - *dst_covers; + } + if(cover) + { + colors->add(c, cover); + *dst_covers += cover; + } + ++colors; + ++src_covers; + ++dst_covers; + } + while(--len); + if(--num_spans == 0) break; + ++span_aa; + } + } + else + { + // Arbitrary span generator + //----------------------- + for(;;) + { + len = span_aa->len; + colors = mix_buffer + span_aa->x - min_x; + cspan = color_span; + sh.generate_span(cspan, + span_aa->x, + sl_aa.y(), + len, + style); + src_covers = span_aa->covers; + dst_covers = cover_buffer + span_aa->x - min_x; + do + { + cover = *src_covers; + if(*dst_covers + cover > cover_full) + { + cover = cover_full - *dst_covers; + } + if(cover) + { + colors->add(*cspan, cover); + *dst_covers += cover; + } + ++cspan; + ++colors; + ++src_covers; + ++dst_covers; + } + while(--len); + if(--num_spans == 0) break; + ++span_aa; + } + } + } + } + ren.blend_color_hspan(sl_start, + sl_y, + sl_len, + mix_buffer + sl_start - min_x, + 0, + cover_full); + } //if(sl_len) + } //if(num_styles == 1) ... else + } //while((num_styles = ras.sweep_styles()) > 0) + } //if(ras.rewind_scanlines()) + } + + +} + +#endif diff --git a/agg/include/agg_rendering_buffer.h b/agg/include/agg_rendering_buffer.h new file mode 100644 index 0000000..175bcd8 --- /dev/null +++ b/agg/include/agg_rendering_buffer.h @@ -0,0 +1,301 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// class rendering_buffer +// +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERING_BUFFER_INCLUDED +#define AGG_RENDERING_BUFFER_INCLUDED + +#include +#include "agg_array.h" + +namespace agg +{ + + //===========================================================row_accessor + template class row_accessor + { + public: + typedef const_row_info row_data; + + //------------------------------------------------------------------- + row_accessor() : + m_buf(0), + m_start(0), + m_width(0), + m_height(0), + m_stride(0) + { + } + + //-------------------------------------------------------------------- + row_accessor(T* buf, unsigned width, unsigned height, int stride) : + m_buf(0), + m_start(0), + m_width(0), + m_height(0), + m_stride(0) + { + attach(buf, width, height, stride); + } + + + //-------------------------------------------------------------------- + void attach(T* buf, unsigned width, unsigned height, int stride) + { + m_buf = m_start = buf; + m_width = width; + m_height = height; + m_stride = stride; + if(stride < 0) + { + m_start = m_buf - (AGG_INT64)(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 * (AGG_INT64)m_stride; + } + AGG_INLINE T* row_ptr(int y) { return m_start + y * (AGG_INT64)m_stride; } + AGG_INLINE const T* row_ptr(int y) const { return m_start + y * (AGG_INT64)m_stride; } + AGG_INLINE row_data row (int y) const + { + return row_data(0, m_width-1, row_ptr(y)); + } + + //-------------------------------------------------------------------- + template + 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++) + { + std::memcpy(row_ptr(0, y, w), src.row_ptr(y), l); + } + } + + //-------------------------------------------------------------------- + void clear(T value) + { + unsigned y; + unsigned w = width(); + unsigned stride = stride_abs(); + for(y = 0; y < height(); y++) + { + T* p = row_ptr(0, y, w); + unsigned x; + for(x = 0; x < stride; x++) + { + *p++ = value; + } + } + } + + private: + //-------------------------------------------------------------------- + T* m_buf; // Pointer to renrdering buffer + T* m_start; // Pointer to first pixel depending on stride + unsigned m_width; // Width in pixels + unsigned m_height; // Height in pixels + int m_stride; // Number of bytes per row. Can be < 0 + }; + + + + + //==========================================================row_ptr_cache + template class row_ptr_cache + { + public: + typedef const_row_info row_data; + + //------------------------------------------------------------------- + row_ptr_cache() : + m_buf(0), + m_rows(), + m_width(0), + m_height(0), + m_stride(0) + { + } + + //-------------------------------------------------------------------- + row_ptr_cache(T* buf, unsigned width, unsigned height, int stride) : + m_buf(0), + m_rows(), + m_width(0), + m_height(0), + m_stride(0) + { + attach(buf, width, height, stride); + } + + //-------------------------------------------------------------------- + void attach(T* buf, unsigned width, unsigned height, int stride) + { + m_buf = buf; + m_width = width; + m_height = height; + m_stride = stride; + if(height > m_rows.size()) + { + m_rows.resize(height); + } + + T* row_ptr = m_buf; + + if(stride < 0) + { + row_ptr = m_buf - (AGG_INT64)(height - 1) * stride; + } + + T** rows = &m_rows[0]; + + while(height--) + { + *rows++ = row_ptr; + row_ptr += stride; + } + } + + //-------------------------------------------------------------------- + AGG_INLINE T* buf() { return m_buf; } + AGG_INLINE const T* buf() const { return m_buf; } + AGG_INLINE unsigned width() const { return m_width; } + AGG_INLINE unsigned height() const { return m_height; } + AGG_INLINE int stride() const { return m_stride; } + AGG_INLINE unsigned stride_abs() const + { + return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride); + } + + //-------------------------------------------------------------------- + AGG_INLINE T* row_ptr(int, int y, unsigned) + { + return m_rows[y]; + } + AGG_INLINE T* row_ptr(int y) { return m_rows[y]; } + AGG_INLINE const T* row_ptr(int y) const { return m_rows[y]; } + AGG_INLINE row_data row (int y) const + { + return row_data(0, m_width-1, m_rows[y]); + } + + //-------------------------------------------------------------------- + T const* const* rows() const { return &m_rows[0]; } + + //-------------------------------------------------------------------- + template + 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++) + { + std::memcpy(row_ptr(0, y, w), src.row_ptr(y), l); + } + } + + //-------------------------------------------------------------------- + void clear(T value) + { + unsigned y; + unsigned w = width(); + unsigned stride = stride_abs(); + for(y = 0; y < height(); y++) + { + T* p = row_ptr(0, y, w); + unsigned x; + for(x = 0; x < stride; x++) + { + *p++ = value; + } + } + } + + private: + //-------------------------------------------------------------------- + T* m_buf; // Pointer to renrdering buffer + pod_array m_rows; // Pointers to each row of the buffer + unsigned m_width; // Width in pixels + unsigned m_height; // Height in pixels + int m_stride; // Number of bytes per row. Can be < 0 + }; + + + + + //========================================================rendering_buffer + // + // The definition of the main type for accessing the rows in the frame + // buffer. It provides functionality to navigate to the rows in a + // rectangular matrix, from top to bottom or from bottom to top depending + // on stride. + // + // row_accessor is cheap to create/destroy, but performs one multiplication + // when calling row_ptr(). + // + // row_ptr_cache creates an array of pointers to rows, so, the access + // via row_ptr() may be faster. But it requires memory allocation + // when creating. For example, on typical Intel Pentium hardware + // row_ptr_cache speeds span_image_filter_rgb_nn up to 10% + // + // It's used only in short hand typedefs like pixfmt_rgba32 and can be + // redefined in agg_config.h + // In real applications you can use both, depending on your needs + //------------------------------------------------------------------------ +#ifdef AGG_RENDERING_BUFFER + typedef AGG_RENDERING_BUFFER rendering_buffer; +#else +// typedef row_ptr_cache rendering_buffer; + typedef row_accessor rendering_buffer; +#endif + +} + + +#endif diff --git a/agg/include/agg_rendering_buffer_dynarow.h b/agg/include/agg_rendering_buffer_dynarow.h new file mode 100644 index 0000000..4ff4b4f --- /dev/null +++ b/agg/include/agg_rendering_buffer_dynarow.h @@ -0,0 +1,138 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// class rendering_buffer_dynarow +// +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERING_BUFFER_DYNAROW_INCLUDED +#define AGG_RENDERING_BUFFER_DYNAROW_INCLUDED + +#include +#include "agg_array.h" + +namespace agg +{ + + //===============================================rendering_buffer_dynarow + // Rendering buffer class with dynamic allocation of the rows. + // The rows are allocated as needed when requesting for span_ptr(). + // The class automatically calculates min_x and max_x for each row. + // Generally it's more efficient to use this class as a temporary buffer + // for rendering a few lines and then to blend it with another buffer. + // + class rendering_buffer_dynarow + { + public: + typedef row_info row_data; + + //------------------------------------------------------------------- + ~rendering_buffer_dynarow() + { + init(0,0,0); + } + + //------------------------------------------------------------------- + rendering_buffer_dynarow() : + m_rows(), + m_width(0), + m_height(0), + m_byte_width(0) + { + } + + // Allocate and clear the buffer + //-------------------------------------------------------------------- + rendering_buffer_dynarow(unsigned width, unsigned height, + unsigned byte_width) : + m_rows(height), + m_width(width), + m_height(height), + m_byte_width(byte_width) + { + std::memset(&m_rows[0], 0, sizeof(row_data) * height); + } + + // Allocate and clear the buffer + //-------------------------------------------------------------------- + void init(unsigned width, unsigned height, unsigned byte_width) + { + unsigned i; + for(i = 0; i < m_height; ++i) + { + pod_allocator::deallocate((int8u*)m_rows[i].ptr, m_byte_width); + } + if(width && height) + { + m_width = width; + m_height = height; + m_byte_width = byte_width; + m_rows.resize(height); + std::memset(&m_rows[0], 0, sizeof(row_data) * height); + } + } + + //-------------------------------------------------------------------- + unsigned width() const { return m_width; } + unsigned height() const { return m_height; } + unsigned byte_width() const { return m_byte_width; } + + // The main function used for rendering. Returns pointer to the + // pre-allocated span. Memory for the row is allocated as needed. + //-------------------------------------------------------------------- + int8u* row_ptr(int x, int y, unsigned len) + { + row_data* r = &m_rows[y]; + int x2 = x + len - 1; + if(r->ptr) + { + if(x < r->x1) { r->x1 = x; } + if(x2 > r->x2) { r->x2 = x2; } + } + else + { + int8u* p = pod_allocator::allocate(m_byte_width); + r->ptr = p; + r->x1 = x; + r->x2 = x2; + std::memset(p, 0, m_byte_width); + } + return (int8u*)r->ptr; + } + + //-------------------------------------------------------------------- + const int8u* row_ptr(int y) const { return m_rows[y].ptr; } + int8u* row_ptr(int y) { return row_ptr(0, y, m_width); } + row_data row (int y) const { return m_rows[y]; } + + private: + //-------------------------------------------------------------------- + // Prohibit copying + rendering_buffer_dynarow(const rendering_buffer_dynarow&); + const rendering_buffer_dynarow& operator = (const rendering_buffer_dynarow&); + + private: + //-------------------------------------------------------------------- + pod_array m_rows; // Pointers to each row of the buffer + unsigned m_width; // Width in pixels + unsigned m_height; // Height in pixels + unsigned m_byte_width; // Width in bytes + }; + + +} + + +#endif diff --git a/agg2/include/agg_rounded_rect.h b/agg/include/agg_rounded_rect.h similarity index 85% rename from agg2/include/agg_rounded_rect.h rename to agg/include/agg_rounded_rect.h index 5c089c3..fe8d26f 100644 --- a/agg2/include/agg_rounded_rect.h +++ b/agg/include/agg_rounded_rect.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -22,8 +22,6 @@ #include "agg_basics.h" #include "agg_arc.h" -#include "agg_vertex_iterator.h" - namespace agg { @@ -51,11 +49,6 @@ namespace agg void rewind(unsigned); unsigned vertex(double* x, double* y); - typedef rounded_rect source_type; - typedef vertex_iterator iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: double m_x1; double m_y1; diff --git a/agg/include/agg_scanline_bin.h b/agg/include/agg_scanline_bin.h new file mode 100644 index 0000000..6f9f41e --- /dev/null +++ b/agg/include/agg_scanline_bin.h @@ -0,0 +1,264 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Class scanline_bin - binary scanline. +// +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates (scanline32_bin) has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_SCANLINE_BIN_INCLUDED +#define AGG_SCANLINE_BIN_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + + //=============================================================scanline_bin + // + // This is binary scaline container which supports the interface + // used in the rasterizer::render(). See description of agg_scanline_u8 + // for details. + // + //------------------------------------------------------------------------ + class scanline_bin + { + public: + typedef int32 coord_type; + + struct span + { + int16 x; + int16 len; + }; + + typedef const span* const_iterator; + + //-------------------------------------------------------------------- + scanline_bin() : + m_last_x(0x7FFFFFF0), + m_spans(), + m_cur_span(0) + { + } + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 3; + if(max_len > m_spans.size()) + { + m_spans.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_cur_span = &m_spans[0]; + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned) + { + if(x == m_last_x+1) + { + m_cur_span->len++; + } + else + { + ++m_cur_span; + m_cur_span->x = (int16)x; + m_cur_span->len = 1; + } + m_last_x = x; + } + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned) + { + if(x == m_last_x+1) + { + m_cur_span->len = (int16)(m_cur_span->len + len); + } + else + { + ++m_cur_span; + m_cur_span->x = (int16)x; + m_cur_span->len = (int16)len; + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const void*) + { + add_span(x, len, 0); + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_cur_span = &m_spans[0]; + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } + const_iterator begin() const { return &m_spans[1]; } + + private: + scanline_bin(const scanline_bin&); + const scanline_bin operator = (const scanline_bin&); + + int m_last_x; + int m_y; + pod_array 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_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; + }; + + + + + +} + + +#endif diff --git a/agg2/include/agg_scanline_boolean_algebra.h b/agg/include/agg_scanline_boolean_algebra.h similarity index 90% rename from agg2/include/agg_scanline_boolean_algebra.h rename to agg/include/agg_scanline_boolean_algebra.h index 9edcbdf..572c31c 100644 --- a/agg2/include/agg_scanline_boolean_algebra.h +++ b/agg/include/agg_scanline_boolean_algebra.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -16,8 +16,7 @@ #ifndef AGG_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED #define AGG_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED -#include -#include +#include #include "agg_basics.h" @@ -141,7 +140,7 @@ namespace agg unsigned CoverShift = cover_shift> struct sbool_intersect_spans_aa { - enum + enum cover_scale_e { cover_shift = CoverShift, cover_size = 1 << cover_shift, @@ -253,7 +252,7 @@ namespace agg unsigned CoverShift = cover_shift> struct sbool_unite_spans_aa { - enum + enum cover_scale_e { cover_shift = CoverShift, cover_size = 1 << cover_shift, @@ -358,23 +357,38 @@ namespace agg }; + //---------------------------------------------sbool_xor_formula_linear + template + struct sbool_xor_formula_linear + { + enum cover_scale_e + { + cover_shift = CoverShift, + cover_size = 1 << cover_shift, + cover_mask = cover_size - 1 + }; - - + static AGG_INLINE unsigned calculate(unsigned a, unsigned b) + { + unsigned cover = a + b; + if(cover > cover_mask) cover = cover_mask + cover_mask - cover; + return cover; + } + }; //---------------------------------------------sbool_xor_formula_saddle template struct sbool_xor_formula_saddle { - enum + enum cover_scale_e { cover_shift = CoverShift, cover_size = 1 << cover_shift, cover_mask = cover_size - 1 }; - static unsigned calculate(unsigned a, unsigned b) + static AGG_INLINE unsigned calculate(unsigned a, unsigned b) { unsigned k = a * b; if(k == cover_mask * cover_mask) return 0; @@ -386,23 +400,12 @@ namespace agg }; - - //--------------------------------------------sbool_xor_formula_linear - template - struct sbool_xor_formula_linear + //-------------------------------------------sbool_xor_formula_abs_diff + struct sbool_xor_formula_abs_diff { - enum - { - cover_shift = CoverShift, - cover_size = 1 << cover_shift, - cover_mask = cover_size - 1 - }; - - static unsigned calculate(unsigned a, unsigned b) + static AGG_INLINE unsigned calculate(unsigned a, unsigned b) { - unsigned cover = a + b; - if(cover > cover_mask) cover = cover_mask + cover_mask - cover; - return cover; + return unsigned(std::abs(int(a) - int(b))); } }; @@ -420,7 +423,7 @@ namespace agg unsigned CoverShift = cover_shift> struct sbool_xor_spans_aa { - enum + enum cover_scale_e { cover_shift = CoverShift, cover_size = 1 << cover_shift, @@ -509,7 +512,7 @@ namespace agg unsigned CoverShift = cover_shift> struct sbool_subtract_spans_aa { - enum + enum cover_scale_e { cover_shift = CoverShift, cover_size = 1 << cover_shift, @@ -625,14 +628,14 @@ namespace agg AddSpanFunctor add_span) { sl.reset_spans(); - typename Scanline::const_iterator span = sl1.begin(); + typename Scanline1::const_iterator span = sl1.begin(); unsigned num_spans = sl1.num_spans(); - do + for(;;) { - add_span(span, span->x, abs((int)span->len), sl); + add_span(span, span->x, std::abs((int)span->len), sl); + if(--num_spans == 0) break; ++span; } - while(--num_spans); sl.finalize(sl1.y()); ren.render(sl); } @@ -667,15 +670,15 @@ namespace agg unsigned num2 = sl2.num_spans(); if(num2 == 0) return; - typename Scanline::const_iterator span1 = sl1.begin(); - typename Scanline::const_iterator span2 = sl2.begin(); + typename Scanline1::const_iterator span1 = sl1.begin(); + typename Scanline2::const_iterator span2 = sl2.begin(); while(num1 && num2) { int xb1 = span1->x; int xb2 = span2->x; - int xe1 = xb1 + abs((int)span1->len) - 1; - int xe2 = xb2 + abs((int)span2->len) - 1; + int xe1 = xb1 + std::abs((int)span1->len) - 1; + int xe2 = xb2 + std::abs((int)span2->len) - 1; // Determine what spans we should advance in the next step // The span with the least ending X should be advanced @@ -701,20 +704,20 @@ namespace agg { --num1; --num2; - ++span1; - ++span2; + if(num1) ++span1; + if(num2) ++span2; } else { if(advance_span1) { --num1; - ++span1; + if(num1) ++span1; } else { --num2; - ++span2; + if(num2) ++span2; } } } @@ -761,13 +764,13 @@ namespace agg // Get the bounding boxes //---------------- - rect r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); - rect r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y()); + rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); + rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y()); // Calculate the intersection of the bounding // boxes and return if they don't intersect. //----------------- - rect ir = intersect_rectangles(r1, r2); + rect_i ir = intersect_rectangles(r1, r2); if(!ir.is_valid()) return; // Reset the scanlines and get two first ones @@ -778,7 +781,7 @@ namespace agg if(!sg1.sweep_scanline(sl1)) return; if(!sg2.sweep_scanline(sl2)) return; - ren.prepare(unsigned(ir.x2 - ir.x1 + 2)); + ren.prepare(); // The main loop // Here we synchronize the scanlines with @@ -846,10 +849,14 @@ namespace agg unsigned num1 = sl1.num_spans(); unsigned num2 = sl2.num_spans(); - typename Scanline::const_iterator span1; - typename Scanline::const_iterator span2; + typename Scanline1::const_iterator span1;// = sl1.begin(); + typename Scanline2::const_iterator span2;// = sl2.begin(); - enum { invalid_b = 0x7FFFFFFF, invalid_e = invalid_b - 1 }; + enum invalidation_e + { + invalid_b = 0xFFFFFFF, + invalid_e = invalid_b - 1 + }; // Initialize the spans as invalid //--------------- @@ -864,7 +871,7 @@ namespace agg { span1 = sl1.begin(); xb1 = span1->x; - xe1 = xb1 + abs((int)span1->len) - 1; + xe1 = xb1 + std::abs((int)span1->len) - 1; --num1; } @@ -874,7 +881,7 @@ namespace agg { span2 = sl2.begin(); xb2 = span2->x; - xe2 = xb2 + abs((int)span2->len) - 1; + xe2 = xb2 + std::abs((int)span2->len) - 1; --num2; } @@ -888,7 +895,7 @@ namespace agg --num1; ++span1; xb1 = span1->x; - xe1 = xb1 + abs((int)span1->len) - 1; + xe1 = xb1 + std::abs((int)span1->len) - 1; } // Retrieve a new span2 if it's invalid @@ -898,7 +905,7 @@ namespace agg --num2; ++span2; xb2 = span2->x; - xe2 = xb2 + abs((int)span2->len) - 1; + xe2 = xb2 + std::abs((int)span2->len) - 1; } if(xb1 > xe1 && xb2 > xe2) break; @@ -1033,15 +1040,19 @@ namespace agg // Get the bounding boxes //---------------- - rect r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); - rect r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y()); + rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); + rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y()); // Calculate the union of the bounding boxes //----------------- - rect ur = unite_rectangles(r1, r2); + rect_i ur(1,1,0,0); + if(flag1 && flag2) ur = unite_rectangles(r1, r2); + else if(flag1) ur = r1; + else if(flag2) ur = r2; + if(!ur.is_valid()) return; - ren.prepare(unsigned(ur.x2 - ur.x2 + 2)); + ren.prepare(); // Reset the scanlines and get two first ones //----------------- @@ -1154,7 +1165,7 @@ namespace agg // Get the bounding box //---------------- - rect r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); + rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); // Reset the scanlines and get two first ones //----------------- @@ -1165,10 +1176,10 @@ namespace agg if(flag2) flag2 = sg2.sweep_scanline(sl2); - ren.prepare(unsigned(sg1.max_x() - sg1.min_x() + 2)); + ren.prepare(); // A fake span2 processor - sbool_add_span_empty add_span2; + sbool_add_span_empty add_span2; // The main loop // Here we synchronize the scanlines with @@ -1376,6 +1387,34 @@ namespace agg } + //--------------------------------------sbool_xor_shapes_abs_diff_aa + // Apply eXclusive OR to two anti-aliased scanline shapes. + // There's the absolute difference used to calculate + // Anti-Aliasing values, that is: + // a XOR b : abs(a-b) + // See intersect_shapes_aa for more comments + //---------- + template + void sbool_xor_shapes_abs_diff_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_aa add_functor1; + sbool_add_span_aa add_functor2; + sbool_xor_spans_aa combine_functor; + sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor1, add_functor2, combine_functor); + } + + //--------------------------------------------------sbool_xor_shapes_bin // Apply eXclusive OR to two binary scanline shapes (without anti-aliasing). @@ -1459,6 +1498,7 @@ namespace agg sbool_and, //----sbool_and sbool_xor, //----sbool_xor sbool_xor_saddle, //----sbool_xor_saddle + sbool_xor_abs_diff, //----sbool_xor_abs_diff sbool_a_minus_b, //----sbool_a_minus_b sbool_b_minus_a //----sbool_b_minus_a }; @@ -1482,12 +1522,13 @@ namespace agg { switch(op) { - case sbool_or : sbool_unite_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; - case sbool_and : sbool_intersect_shapes_bin(sg1, sg2, sl1, sl2, sl, ren); break; - case sbool_xor : - case sbool_xor_saddle: sbool_xor_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; - case sbool_a_minus_b : sbool_subtract_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; - case sbool_b_minus_a : sbool_subtract_shapes_bin (sg2, sg1, sl2, sl1, sl, ren); break; + case sbool_or : sbool_unite_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_and : sbool_intersect_shapes_bin(sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_xor : + case sbool_xor_saddle : + case sbool_xor_abs_diff: sbool_xor_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_a_minus_b : sbool_subtract_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_b_minus_a : sbool_subtract_shapes_bin (sg2, sg1, sl2, sl1, sl, ren); break; } } @@ -1508,12 +1549,13 @@ namespace agg { switch(op) { - case sbool_or : sbool_unite_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; - case sbool_and : sbool_intersect_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; - case sbool_xor : sbool_xor_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; - case sbool_xor_saddle: sbool_xor_shapes_saddle_aa(sg1, sg2, sl1, sl2, sl, ren); break; - case sbool_a_minus_b : sbool_subtract_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; - case sbool_b_minus_a : sbool_subtract_shapes_aa (sg2, sg1, sl2, sl1, sl, ren); break; + case sbool_or : sbool_unite_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_and : sbool_intersect_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_xor : sbool_xor_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_xor_saddle : sbool_xor_shapes_saddle_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_xor_abs_diff: sbool_xor_shapes_abs_diff_aa(sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_a_minus_b : sbool_subtract_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_b_minus_a : sbool_subtract_shapes_aa (sg2, sg1, sl2, sl1, sl, ren); break; } } diff --git a/agg/include/agg_scanline_p.h b/agg/include/agg_scanline_p.h new file mode 100644 index 0000000..1ddb8c0 --- /dev/null +++ b/agg/include/agg_scanline_p.h @@ -0,0 +1,330 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Class scanline_p - a general purpose scanline container with packed spans. +// +//---------------------------------------------------------------------------- +// +// 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 +#include "agg_array.h" + +namespace agg +{ + + //=============================================================scanline_p8 + // + // This is a general purpose scaline container which supports the interface + // used in the rasterizer::render(). See description of scanline_u8 + // for details. + // + //------------------------------------------------------------------------ + class scanline_p8 + { + public: + typedef scanline_p8 self_type; + typedef int8u cover_type; + typedef int16 coord_type; + + //-------------------------------------------------------------------- + struct span + { + coord_type x; + coord_type len; // If negative, it's a solid span, covers is valid + const cover_type* covers; + }; + + typedef span* iterator; + typedef const span* const_iterator; + + scanline_p8() : + m_last_x(0x7FFFFFF0), + m_covers(), + m_cover_ptr(0), + m_spans(), + m_cur_span(0) + { + } + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 3; + if(max_len > m_spans.size()) + { + m_spans.resize(max_len); + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_cover_ptr = &m_covers[0]; + m_cur_span = &m_spans[0]; + m_cur_span->len = 0; + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover) + { + *m_cover_ptr = (cover_type)cover; + if(x == m_last_x+1 && m_cur_span->len > 0) + { + m_cur_span->len++; + } + else + { + m_cur_span++; + m_cur_span->covers = m_cover_ptr; + m_cur_span->x = (int16)x; + m_cur_span->len = 1; + } + m_last_x = x; + m_cover_ptr++; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const cover_type* covers) + { + std::memcpy(m_cover_ptr, covers, len * sizeof(cover_type)); + if(x == m_last_x+1 && m_cur_span->len > 0) + { + m_cur_span->len += (int16)len; + } + else + { + m_cur_span++; + m_cur_span->covers = m_cover_ptr; + m_cur_span->x = (int16)x; + m_cur_span->len = (int16)len; + } + m_cover_ptr += len; + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned cover) + { + if(x == m_last_x+1 && + m_cur_span->len < 0 && + cover == *m_cur_span->covers) + { + m_cur_span->len -= (int16)len; + } + else + { + *m_cover_ptr = (cover_type)cover; + m_cur_span++; + m_cur_span->covers = m_cover_ptr++; + m_cur_span->x = (int16)x; + m_cur_span->len = (int16)(-int(len)); + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_cover_ptr = &m_covers[0]; + m_cur_span = &m_spans[0]; + m_cur_span->len = 0; + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } + const_iterator begin() const { return &m_spans[1]; } + + private: + scanline_p8(const self_type&); + const self_type& operator = (const self_type&); + + int m_last_x; + int m_y; + pod_array m_covers; + cover_type* m_cover_ptr; + pod_array m_spans; + span* m_cur_span; + }; + + + + + + + + + //==========================================================scanline32_p8 + class scanline32_p8 + { + public: + typedef scanline32_p8 self_type; + typedef int8u cover_type; + typedef int32 coord_type; + + struct span + { + span() {} + span(coord_type x_, coord_type len_, const cover_type* covers_) : + x(x_), len(len_), covers(covers_) {} + + coord_type x; + coord_type len; // If negative, it's a solid span, covers is valid + const cover_type* covers; + }; + typedef pod_bvector span_array_type; + + + //-------------------------------------------------------------------- + class const_iterator + { + public: + const_iterator(const span_array_type& spans) : + m_spans(spans), + m_span_idx(0) + {} + + const span& operator*() const { return m_spans[m_span_idx]; } + const span* operator->() const { return &m_spans[m_span_idx]; } + + void operator ++ () { ++m_span_idx; } + + private: + const span_array_type& m_spans; + unsigned m_span_idx; + }; + + //-------------------------------------------------------------------- + scanline32_p8() : + m_max_len(0), + m_last_x(0x7FFFFFF0), + m_covers(), + m_cover_ptr(0) + { + } + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 3; + if(max_len > m_covers.size()) + { + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_cover_ptr = &m_covers[0]; + m_spans.remove_all(); + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover) + { + *m_cover_ptr = cover_type(cover); + if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0) + { + m_spans.last().len++; + } + else + { + m_spans.add(span(coord_type(x), 1, m_cover_ptr)); + } + m_last_x = x; + m_cover_ptr++; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const cover_type* covers) + { + std::memcpy(m_cover_ptr, covers, len * sizeof(cover_type)); + if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0) + { + m_spans.last().len += coord_type(len); + } + else + { + m_spans.add(span(coord_type(x), coord_type(len), m_cover_ptr)); + } + m_cover_ptr += len; + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned cover) + { + if(x == m_last_x+1 && + m_spans.size() && + m_spans.last().len < 0 && + cover == *m_spans.last().covers) + { + m_spans.last().len -= coord_type(len); + } + else + { + *m_cover_ptr = cover_type(cover); + m_spans.add(span(coord_type(x), -coord_type(len), m_cover_ptr++)); + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_cover_ptr = &m_covers[0]; + m_spans.remove_all(); + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return m_spans.size(); } + const_iterator begin() const { return const_iterator(m_spans); } + + private: + scanline32_p8(const self_type&); + const self_type& operator = (const self_type&); + + unsigned m_max_len; + int m_last_x; + int m_y; + pod_array m_covers; + cover_type* m_cover_ptr; + span_array_type m_spans; + }; + + +} + + +#endif + diff --git a/agg2/include/agg_scanline_storage_aa.h b/agg/include/agg_scanline_storage_aa.h similarity index 77% rename from agg2/include/agg_scanline_storage_aa.h rename to agg/include/agg_scanline_storage_aa.h index ec70567..6174155 100644 --- a/agg2/include/agg_scanline_storage_aa.h +++ b/agg/include/agg_scanline_storage_aa.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -12,15 +12,22 @@ // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- #ifndef AGG_SCANLINE_STORAGE_AA_INCLUDED #define AGG_SCANLINE_STORAGE_AA_INCLUDED -#include -#include -#include +#include +#include +#include #include "agg_array.h" -#include "agg_render_scanlines.h" namespace agg @@ -76,7 +83,8 @@ namespace agg int i; for(i = m_extra_storage.size()-1; i >= 0; --i) { - delete [] m_extra_storage[(unsigned)i].ptr; + pod_allocator::deallocate(m_extra_storage[i].ptr, + m_extra_storage[i].len); } m_extra_storage.remove_all(); m_cells.remove_all(); @@ -89,13 +97,13 @@ namespace agg if(idx >= 0) { T* ptr = &m_cells[idx]; - memcpy(ptr, cells, sizeof(T) * num_cells); + std::memcpy(ptr, cells, sizeof(T) * num_cells); return idx; } extra_span s; s.len = num_cells; - s.ptr = new T [num_cells]; - memcpy(s.ptr, cells, sizeof(T) * num_cells); + s.ptr = pod_allocator::allocate(num_cells); + std::memcpy(s.ptr, cells, sizeof(T) * num_cells); m_extra_storage.add(s); return -int(m_extra_storage.size()); } @@ -135,14 +143,14 @@ namespace agg const extra_span& src = v.m_extra_storage[i]; extra_span dst; dst.len = src.len; - dst.ptr = new T [dst.len]; - memcpy(dst.ptr, src.ptr, dst.len * sizeof(T)); + dst.ptr = pod_allocator::allocate(dst.len); + std::memcpy(dst.ptr, src.ptr, dst.len * sizeof(T)); m_extra_storage.add(dst); } } - pod_deque m_cells; - pod_deque m_extra_storage; + pod_bvector m_cells; + pod_bvector m_extra_storage; }; @@ -159,8 +167,8 @@ namespace agg //--------------------------------------------------------------- struct span_data { - int16 x; - int16 len; // If negative, it's a solid span, covers is valid + int32 x; + int32 len; // If negative, it's a solid span, covers is valid int covers_id; // The index of the cells in the scanline_cell_storage }; @@ -184,12 +192,13 @@ namespace agg public: struct span { - int16 x; - int16 len; // If negative, it's a solid span, covers is valid + int32 x; + int32 len; // If negative, it's a solid span, covers is valid const T* covers; }; - const_iterator(const embedded_scanline& sl) : + const_iterator() : m_storage(0) {} + const_iterator(embedded_scanline& sl) : m_storage(sl.m_storage), m_span_idx(sl.m_scanline.start_span) { @@ -214,7 +223,7 @@ namespace agg m_span.covers = m_storage->covers_by_index(s.covers_id); } - const scanline_storage_aa* m_storage; + scanline_storage_aa* m_storage; unsigned m_span_idx; span m_span; }; @@ -254,10 +263,10 @@ namespace agg m_covers(), m_spans(256-2), // Block increment size m_scanlines(), - m_min_x( 0x7FFFFFFF), - m_min_y( 0x7FFFFFFF), - m_max_x(-0x7FFFFFFF), - m_max_y(-0x7FFFFFFF), + m_min_x(std::numeric_limits::max()), + m_min_y(std::numeric_limits::max()), + m_max_x(std::numeric_limits::min()), + m_max_y(std::numeric_limits::min()), m_cur_scanline(0) { m_fake_scanline.y = 0; @@ -270,15 +279,15 @@ namespace agg // Renderer Interface //--------------------------------------------------------------- - void prepare(unsigned) + void prepare() { m_covers.remove_all(); m_scanlines.remove_all(); m_spans.remove_all(); - m_min_x = 0x7FFFFFFF; - m_min_y = 0x7FFFFFFF; - m_max_x = -0x7FFFFFFF; - m_max_y = -0x7FFFFFFF; + m_min_x = std::numeric_limits::max(); + m_min_y = std::numeric_limits::max(); + m_max_x = std::numeric_limits::min(); + m_max_y = std::numeric_limits::min(); m_cur_scanline = 0; } @@ -297,23 +306,24 @@ namespace agg typename Scanline::const_iterator span_iterator = sl.begin(); unsigned num_spans = sl_this.num_spans; - do + for(;;) { span_data sp; sp.x = span_iterator->x; sp.len = span_iterator->len; + int len = std::abs(int(sp.len)); sp.covers_id = m_covers.add_cells(span_iterator->covers, - unsigned(abs(int(sp.len)))); + unsigned(len)); m_spans.add(sp); int x1 = sp.x; - int x2 = sp.x + sp.len - 1; + int x2 = sp.x + len - 1; if(x1 < m_min_x) m_min_x = x1; if(x2 > m_max_x) m_max_x = x2; + if(--num_spans == 0) break; ++span_iterator; } - while(--num_spans); m_scanlines.add(sl_this); } @@ -387,11 +397,11 @@ namespace agg unsigned byte_size() const { unsigned i; - unsigned size = sizeof(int16) * 4; // min_x, min_y, max_x, max_y + unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y for(i = 0; i < m_scanlines.size(); ++i) { - size += sizeof(int16) * 3; // scanline size in bytes, Y, num_spans + size += sizeof(int32) * 3; // scanline size in bytes, Y, num_spans const scanline_data& sl_this = m_scanlines[i]; @@ -401,7 +411,7 @@ namespace agg { const span_data& sp = m_spans[span_idx++]; - size += sizeof(int16) * 2; // X, span_len + size += sizeof(int32) * 2; // X, span_len if(sp.len < 0) { size += sizeof(T); // cover @@ -418,10 +428,12 @@ namespace agg //--------------------------------------------------------------- - static void write_int16(int8u* dst, int16 val) + static void write_int32(int8u* dst, int32 val) { dst[0] = ((const int8u*)&val)[0]; dst[1] = ((const int8u*)&val)[1]; + dst[2] = ((const int8u*)&val)[2]; + dst[3] = ((const int8u*)&val)[3]; } @@ -430,27 +442,27 @@ namespace agg { unsigned i; - write_int16(data, int16u(min_x())); // min_x - data += sizeof(int16u); - write_int16(data, int16u(min_y())); // min_y - data += sizeof(int16u); - write_int16(data, int16u(max_x())); // max_x - data += sizeof(int16u); - write_int16(data, int16u(max_y())); // max_y - data += sizeof(int16u); + write_int32(data, min_x()); // min_x + data += sizeof(int32); + write_int32(data, min_y()); // min_y + data += sizeof(int32); + write_int32(data, max_x()); // max_x + data += sizeof(int32); + write_int32(data, max_y()); // max_y + data += sizeof(int32); for(i = 0; i < m_scanlines.size(); ++i) { const scanline_data& sl_this = m_scanlines[i]; int8u* size_ptr = data; - data += sizeof(int16); // Reserve space for scanline size in bytes + data += sizeof(int32); // Reserve space for scanline size in bytes - write_int16(data, int16(sl_this.y)); // Y - data += sizeof(int16); + write_int32(data, sl_this.y); // Y + data += sizeof(int32); - write_int16(data, int16(sl_this.num_spans)); // num_spans - data += sizeof(int16); + write_int32(data, sl_this.num_spans); // num_spans + data += sizeof(int32); unsigned num_spans = sl_this.num_spans; unsigned span_idx = sl_this.start_span; @@ -459,25 +471,25 @@ namespace agg const span_data& sp = m_spans[span_idx++]; const T* covers = covers_by_index(sp.covers_id); - write_int16(data, int16(sp.x)); // X - data += sizeof(int16); + write_int32(data, sp.x); // X + data += sizeof(int32); - write_int16(data, int16(sp.len)); // span_len - data += sizeof(int16); + write_int32(data, sp.len); // span_len + data += sizeof(int32); if(sp.len < 0) { - memcpy(data, covers, sizeof(T)); + std::memcpy(data, covers, sizeof(T)); data += sizeof(T); } else { - memcpy(data, covers, unsigned(sp.len) * sizeof(T)); + std::memcpy(data, covers, unsigned(sp.len) * sizeof(T)); data += sizeof(T) * unsigned(sp.len); } } while(--num_spans); - write_int16(size_ptr, int16(unsigned(data - size_ptr))); + write_int32(size_ptr, int32(unsigned(data - size_ptr))); } } @@ -501,9 +513,9 @@ namespace agg } private: - scanline_cell_storage m_covers; - pod_deque m_spans; - pod_deque m_scanlines; + scanline_cell_storage m_covers; + pod_bvector m_spans; + pod_bvector m_scanlines; span_data m_fake_span; scanline_data m_fake_scanline; int m_min_x; @@ -539,14 +551,15 @@ namespace agg public: struct span { - int16 x; - int16 len; // If negative, it's a solid span, "covers" is valid + int32 x; + int32 len; // If negative, it's a solid span, "covers" is valid const T* covers; }; - const_iterator(const embedded_scanline& sl) : - m_ptr(sl.m_ptr), - m_dx(sl.m_dx) + const_iterator() : m_ptr(0) {} + const_iterator(const embedded_scanline* sl) : + m_ptr(sl->m_ptr), + m_dx(sl->m_dx) { init_span(); } @@ -568,18 +581,20 @@ namespace agg } private: - int read_int16() + int read_int32() { - int16 val; + int32 val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; return val; } void init_span() { - m_span.x = read_int16() + m_dx; - m_span.len = read_int16(); + m_span.x = read_int32() + m_dx; + m_span.len = read_int32(); m_span.covers = m_ptr; } @@ -598,16 +613,18 @@ namespace agg void reset(int, int) {} unsigned num_spans() const { return m_num_spans; } int y() const { return m_y; } - const_iterator begin() const { return const_iterator(*this); } + const_iterator begin() const { return const_iterator(this); } private: //----------------------------------------------------------------- - int read_int16() + int read_int32() { - int16 val; + int32 val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; return val; } @@ -616,8 +633,8 @@ namespace agg void init(const int8u* ptr, int dx, int dy) { m_ptr = ptr; - m_y = read_int16() + dy; - m_num_spans = unsigned(read_int16()); + m_y = read_int32() + dy; + m_num_spans = unsigned(read_int32()); m_dx = dx; } @@ -638,10 +655,10 @@ namespace agg m_ptr(0), m_dx(0), m_dy(0), - m_min_x(0x7FFFFFFF), - m_min_y(0x7FFFFFFF), - m_max_x(-0x7FFFFFFF), - m_max_y(-0x7FFFFFFF) + m_min_x(std::numeric_limits::max()), + m_min_y(std::numeric_limits::max()), + m_max_x(std::numeric_limits::min()), + m_max_y(std::numeric_limits::min()) {} //-------------------------------------------------------------------- @@ -650,12 +667,12 @@ namespace agg m_data(data), m_end(data + size), m_ptr(data), - m_dx(int(floor(dx + 0.5))), - m_dy(int(floor(dy + 0.5))), - m_min_x(0x7FFFFFFF), - m_min_y(0x7FFFFFFF), - m_max_x(-0x7FFFFFFF), - m_max_y(-0x7FFFFFFF) + m_dx(iround(dx)), + m_dy(iround(dy)), + m_min_x(std::numeric_limits::max()), + m_min_y(std::numeric_limits::max()), + m_max_x(std::numeric_limits::min()), + m_max_y(std::numeric_limits::min()) {} //-------------------------------------------------------------------- @@ -664,30 +681,34 @@ namespace agg m_data = data; m_end = data + size; m_ptr = data; - m_dx = int(floor(dx + 0.5)); - m_dy = int(floor(dy + 0.5)); - m_min_x = 0x7FFFFFFF; - m_min_y = 0x7FFFFFFF; - m_max_x = -0x7FFFFFFF; - m_max_y = -0x7FFFFFFF; + m_dx = iround(dx); + m_dy = iround(dy); + m_min_x = std::numeric_limits::max(); + m_min_y = std::numeric_limits::max(); + m_max_x = std::numeric_limits::min(); + m_max_y = std::numeric_limits::min(); } private: //-------------------------------------------------------------------- - int read_int16() + int read_int32() { - int16 val; + int32 val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; return val; } //-------------------------------------------------------------------- - unsigned read_int16u() + unsigned read_int32u() { - int16u val; + int32u val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; return val; } @@ -699,13 +720,12 @@ namespace agg m_ptr = m_data; if(m_ptr < m_end) { - m_min_x = read_int16() + m_dx; - m_min_y = read_int16() + m_dy; - m_max_x = read_int16() + m_dx; - m_max_y = read_int16() + m_dy; - return true; + m_min_x = read_int32() + m_dx; + m_min_y = read_int32() + m_dy; + m_max_x = read_int32() + m_dx; + m_max_y = read_int32() + m_dy; } - return false; + return m_ptr < m_end; } //-------------------------------------------------------------------- @@ -722,14 +742,14 @@ namespace agg { if(m_ptr >= m_end) return false; - read_int16(); // Skip scanline size in bytes - int y = read_int16() + m_dy; - unsigned num_spans = read_int16(); + read_int32(); // Skip scanline size in bytes + int y = read_int32() + m_dy; + unsigned num_spans = read_int32(); do { - int x = read_int16() + m_dx; - int len = read_int16(); + int x = read_int32() + m_dx; + int len = read_int32(); if(len < 0) { @@ -762,9 +782,9 @@ namespace agg { if(m_ptr >= m_end) return false; - unsigned byte_size = read_int16u(); + unsigned byte_size = read_int32u(); sl.init(m_ptr, m_dx, m_dy); - m_ptr += byte_size - sizeof(int16); + m_ptr += byte_size - sizeof(int32); } while(sl.num_spans() == 0); return true; diff --git a/agg2/include/agg_scanline_storage_bin.h b/agg/include/agg_scanline_storage_bin.h similarity index 72% rename from agg2/include/agg_scanline_storage_bin.h rename to agg/include/agg_scanline_storage_bin.h index 1014d04..265df0d 100644 --- a/agg2/include/agg_scanline_storage_bin.h +++ b/agg/include/agg_scanline_storage_bin.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -12,15 +12,22 @@ // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + #ifndef AGG_SCANLINE_STORAGE_BIN_INCLUDED #define AGG_SCANLINE_STORAGE_BIN_INCLUDED -#include -#include -#include +#include +#include #include "agg_array.h" -#include "agg_render_scanlines.h" namespace agg @@ -33,8 +40,8 @@ namespace agg //--------------------------------------------------------------- struct span_data { - int16 x; - int16 len; + int32 x; + int32 len; }; //--------------------------------------------------------------- @@ -55,9 +62,10 @@ namespace agg class const_iterator { public: - const_iterator(const embedded_scanline& sl) : - m_storage(sl.m_storage), - m_span_idx(sl.m_scanline.start_span) + const_iterator() : m_storage(0) {} + const_iterator(const embedded_scanline* sl) : + m_storage(sl->m_storage), + m_span_idx(sl->m_scanline.start_span) { m_span = m_storage->span_by_index(m_span_idx); } @@ -81,7 +89,7 @@ namespace agg //----------------------------------------------------------- - embedded_scanline(const scanline_storage_bin& storage) : + embedded_scanline(scanline_storage_bin& storage) : m_storage(&storage) { setup(0); @@ -91,7 +99,7 @@ namespace agg void reset(int, int) {} unsigned num_spans() const { return m_scanline.num_spans; } int y() const { return m_scanline.y; } - const_iterator begin() const { return const_iterator(*this); } + const_iterator begin() const { return const_iterator(this); } //----------------------------------------------------------- void setup(unsigned scanline_idx) @@ -101,7 +109,7 @@ namespace agg } private: - const scanline_storage_bin* m_storage; + scanline_storage_bin* m_storage; scanline_data m_scanline; unsigned m_scanline_idx; }; @@ -111,10 +119,10 @@ namespace agg scanline_storage_bin() : m_spans(256-2), // Block increment size m_scanlines(), - m_min_x( 0x7FFFFFFF), - m_min_y( 0x7FFFFFFF), - m_max_x(-0x7FFFFFFF), - m_max_y(-0x7FFFFFFF), + m_min_x(std::numeric_limits::max()), + m_min_y(std::numeric_limits::max()), + m_max_x(std::numeric_limits::min()), + m_max_y(std::numeric_limits::min()), m_cur_scanline(0) { m_fake_scanline.y = 0; @@ -126,14 +134,14 @@ namespace agg // Renderer Interface //--------------------------------------------------------------- - void prepare(unsigned) + void prepare() { m_scanlines.remove_all(); m_spans.remove_all(); - m_min_x = 0x7FFFFFFF; - m_min_y = 0x7FFFFFFF; - m_max_x = -0x7FFFFFFF; - m_max_y = -0x7FFFFFFF; + m_min_x = std::numeric_limits::max(); + m_min_y = std::numeric_limits::max(); + m_max_x = std::numeric_limits::min(); + m_max_y = std::numeric_limits::min(); m_cur_scanline = 0; } @@ -152,19 +160,19 @@ namespace agg typename Scanline::const_iterator span_iterator = sl.begin(); unsigned num_spans = sl_this.num_spans; - do + for(;;) { span_data sp; sp.x = span_iterator->x; - sp.len = (int16)abs((int)(span_iterator->len)); + sp.len = (int32)std::abs((int)(span_iterator->len)); m_spans.add(sp); int x1 = sp.x; int x2 = sp.x + sp.len - 1; if(x1 < m_min_x) m_min_x = x1; if(x2 > m_max_x) m_max_x = x2; + if(--num_spans == 0) break; ++span_iterator; } - while(--num_spans); m_scanlines.add(sl_this); } @@ -232,32 +240,24 @@ namespace agg unsigned byte_size() const { unsigned i; - unsigned size = sizeof(int16) * 4; // min_x, min_y, max_x, max_y + unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y for(i = 0; i < m_scanlines.size(); ++i) { - size += sizeof(int16) * 2; // Y, num_spans - - const scanline_data& sl_this = m_scanlines[i]; - - unsigned num_spans = sl_this.num_spans; - unsigned span_idx = sl_this.start_span; - do - { - const span_data& sp = m_spans[span_idx++]; - size += sizeof(int16) * 2; // X, span_len - } - while(--num_spans); + size += sizeof(int32) * 2 + // Y, num_spans + unsigned(m_scanlines[i].num_spans) * sizeof(int32) * 2; // X, span_len } return size; } //--------------------------------------------------------------- - static void write_int16(int8u* dst, int16 val) + static void write_int32(int8u* dst, int32 val) { dst[0] = ((const int8u*)&val)[0]; dst[1] = ((const int8u*)&val)[1]; + dst[2] = ((const int8u*)&val)[2]; + dst[3] = ((const int8u*)&val)[3]; } @@ -266,24 +266,24 @@ namespace agg { unsigned i; - write_int16(data, int16u(min_x())); // min_x - data += sizeof(int16u); - write_int16(data, int16u(min_y())); // min_y - data += sizeof(int16u); - write_int16(data, int16u(max_x())); // max_x - data += sizeof(int16u); - write_int16(data, int16u(max_y())); // max_y - data += sizeof(int16u); + write_int32(data, min_x()); // min_x + data += sizeof(int32); + write_int32(data, min_y()); // min_y + data += sizeof(int32); + write_int32(data, max_x()); // max_x + data += sizeof(int32); + write_int32(data, max_y()); // max_y + data += sizeof(int32); for(i = 0; i < m_scanlines.size(); ++i) { const scanline_data& sl_this = m_scanlines[i]; - write_int16(data, int16(sl_this.y)); // Y - data += sizeof(int16); + write_int32(data, sl_this.y); // Y + data += sizeof(int32); - write_int16(data, int16(sl_this.num_spans)); // num_spans - data += sizeof(int16); + write_int32(data, sl_this.num_spans); // num_spans + data += sizeof(int32); unsigned num_spans = sl_this.num_spans; unsigned span_idx = sl_this.start_span; @@ -291,11 +291,11 @@ namespace agg { const span_data& sp = m_spans[span_idx++]; - write_int16(data, int16(sp.x)); // X - data += sizeof(int16); + write_int32(data, sp.x); // X + data += sizeof(int32); - write_int16(data, int16(sp.len)); // len - data += sizeof(int16); + write_int32(data, sp.len); // len + data += sizeof(int32); } while(--num_spans); } @@ -316,8 +316,8 @@ namespace agg private: - pod_deque m_spans; - pod_deque m_scanlines; + pod_bvector m_spans; + pod_bvector m_scanlines; span_data m_fake_span; scanline_data m_fake_scanline; int m_min_x; @@ -356,16 +356,17 @@ namespace agg public: struct span { - int16 x; - int16 len; + int32 x; + int32 len; }; - const_iterator(const embedded_scanline& sl) : - m_ptr(sl.m_ptr), - m_dx(sl.m_dx) + const_iterator() : m_ptr(0) {} + const_iterator(const embedded_scanline* sl) : + m_ptr(sl->m_ptr), + m_dx(sl->m_dx) { - m_span.x = read_int16() + m_dx; - m_span.len = read_int16(); + m_span.x = read_int32() + m_dx; + m_span.len = read_int32(); } const span& operator*() const { return m_span; } @@ -373,16 +374,18 @@ namespace agg void operator ++ () { - m_span.x = read_int16() + m_dx; - m_span.len = read_int16(); + m_span.x = read_int32() + m_dx; + m_span.len = read_int32(); } private: - int read_int16() + int read_int32() { - int16 val; + int32 val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; return val; } @@ -401,16 +404,18 @@ namespace agg void reset(int, int) {} unsigned num_spans() const { return m_num_spans; } int y() const { return m_y; } - const_iterator begin() const { return const_iterator(*this); } + const_iterator begin() const { return const_iterator(this); } private: //---------------------------------------------------------------- - int read_int16() + int read_int32() { - int16 val; + int32 val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; return val; } @@ -419,8 +424,8 @@ namespace agg void init(const int8u* ptr, int dx, int dy) { m_ptr = ptr; - m_y = read_int16() + dy; - m_num_spans = unsigned(read_int16()); + m_y = read_int32() + dy; + m_num_spans = unsigned(read_int32()); m_dx = dx; } @@ -441,10 +446,10 @@ namespace agg m_ptr(0), m_dx(0), m_dy(0), - m_min_x(0x7FFFFFFF), - m_min_y(0x7FFFFFFF), - m_max_x(-0x7FFFFFFF), - m_max_y(-0x7FFFFFFF) + m_min_x(std::numeric_limits::max()), + m_min_y(std::numeric_limits::max()), + m_max_x(std::numeric_limits::min()), + m_max_y(std::numeric_limits::min()) {} //-------------------------------------------------------------------- @@ -453,12 +458,12 @@ namespace agg m_data(data), m_end(data + size), m_ptr(data), - m_dx(int(floor(dx + 0.5))), - m_dy(int(floor(dy + 0.5))), - m_min_x(0x7FFFFFFF), - m_min_y(0x7FFFFFFF), - m_max_x(-0x7FFFFFFF), - m_max_y(-0x7FFFFFFF) + m_dx(iround(dx)), + m_dy(iround(dy)), + m_min_x(std::numeric_limits::max()), + m_min_y(std::numeric_limits::max()), + m_max_x(std::numeric_limits::min()), + m_max_y(std::numeric_limits::min()) {} //-------------------------------------------------------------------- @@ -467,21 +472,23 @@ namespace agg m_data = data; m_end = data + size; m_ptr = data; - m_dx = int(floor(dx + 0.5)); - m_dy = int(floor(dy + 0.5)); - m_min_x = 0x7FFFFFFF; - m_min_y = 0x7FFFFFFF; - m_max_x = -0x7FFFFFFF; - m_max_y = -0x7FFFFFFF; + m_dx = iround(dx); + m_dy = iround(dy); + m_min_x = std::numeric_limits::max(); + m_min_y = std::numeric_limits::max(); + m_max_x = std::numeric_limits::min(); + m_max_y = std::numeric_limits::min(); } private: //-------------------------------------------------------------------- - int read_int16() + int read_int32() { - int16 val; + int32 val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; return val; } @@ -493,13 +500,12 @@ namespace agg m_ptr = m_data; if(m_ptr < m_end) { - m_min_x = read_int16() + m_dx; - m_min_y = read_int16() + m_dy; - m_max_x = read_int16() + m_dx; - m_max_y = read_int16() + m_dy; - return true; + m_min_x = read_int32() + m_dx; + m_min_y = read_int32() + m_dy; + m_max_x = read_int32() + m_dx; + m_max_y = read_int32() + m_dy; } - return false; + return m_ptr < m_end; } //-------------------------------------------------------------------- @@ -516,13 +522,13 @@ namespace agg { if(m_ptr >= m_end) return false; - int y = read_int16() + m_dy; - unsigned num_spans = read_int16(); + int y = read_int32() + m_dy; + unsigned num_spans = read_int32(); do { - int x = read_int16() + m_dx; - int len = read_int16(); + int x = read_int32() + m_dx; + int len = read_int32(); if(len < 0) len = -len; sl.add_span(x, unsigned(len), cover_full); @@ -551,9 +557,9 @@ namespace agg // Jump to the next scanline //-------------------------- - read_int16(); // Y - int num_spans = read_int16(); // num_spans - m_ptr += num_spans * sizeof(int16) * 2; + read_int32(); // Y + int num_spans = read_int32(); // num_spans + m_ptr += num_spans * sizeof(int32) * 2; } while(sl.num_spans() == 0); return true; diff --git a/agg/include/agg_scanline_u.h b/agg/include/agg_scanline_u.h new file mode 100644 index 0000000..0ca9c68 --- /dev/null +++ b/agg/include/agg_scanline_u.h @@ -0,0 +1,500 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates (scanline32_u) has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_SCANLINE_U_INCLUDED +#define AGG_SCANLINE_U_INCLUDED + +#include +#include "agg_array.h" + +namespace agg +{ + //=============================================================scanline_u8 + // + // Unpacked scanline container class + // + // This class is used to transfer data from a scanline rasterizer + // to the rendering buffer. It's organized very simple. The class stores + // information of horizontal spans to render it into a pixel-map buffer. + // Each span has staring X, length, and an array of bytes that determine the + // cover-values for each pixel. + // Before using this class you should know the minimal and maximal pixel + // coordinates of your scanline. The protocol of using is: + // 1. reset(min_x, max_x) + // 2. add_cell() / add_span() - accumulate scanline. + // When forming one scanline the next X coordinate must be always greater + // than the last stored one, i.e. it works only with ordered coordinates. + // 3. Call finalize(y) and render the scanline. + // 3. Call reset_spans() to prepare for the new scanline. + // + // 4. Rendering: + // + // Scanline provides an iterator class that allows you to extract + // the spans and the cover values for each pixel. Be aware that clipping + // has not been done yet, so you should perform it yourself. + // Use scanline_u8::iterator to render spans: + //------------------------------------------------------------------------- + // + // int y = sl.y(); // Y-coordinate of the scanline + // + // ************************************ + // ...Perform vertical clipping here... + // ************************************ + // + // scanline_u8::const_iterator span = sl.begin(); + // + // unsigned char* row = m_rbuf->row(y); // The address of the beginning + // // of the current row + // + // unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that + // // num_spans is always greater than 0. + // + // do + // { + // const scanline_u8::cover_type* covers = + // span->covers; // The array of the cover values + // + // int num_pix = span->len; // Number of pixels of the span. + // // Always greater than 0, still it's + // // better to use "int" instead of + // // "unsigned" because it's more + // // convenient for clipping + // int x = span->x; + // + // ************************************** + // ...Perform horizontal clipping here... + // ...you have x, covers, and pix_count.. + // ************************************** + // + // unsigned char* dst = row + x; // Calculate the start address of the row. + // // In this case we assume a simple + // // grayscale image 1-byte per pixel. + // do + // { + // *dst++ = *covers++; // Hypotetical rendering. + // } + // while(--num_pix); + // + // ++span; + // } + // while(--num_spans); // num_spans cannot be 0, so this loop is quite safe + //------------------------------------------------------------------------ + // + // The question is: why should we accumulate the whole scanline when we + // could render just separate spans when they're ready? + // That's because using the scanline is generally faster. When is consists + // of more than one span the conditions for the processor cash system + // are better, because switching between two different areas of memory + // (that can be very large) occurs less frequently. + //------------------------------------------------------------------------ + class scanline_u8 + { + public: + typedef scanline_u8 self_type; + typedef int8u cover_type; + typedef int16 coord_type; + + //-------------------------------------------------------------------- + struct span + { + coord_type x; + coord_type len; + cover_type* covers; + }; + + typedef span* iterator; + typedef const span* const_iterator; + + //-------------------------------------------------------------------- + scanline_u8() : + m_min_x(0), + m_last_x(0x7FFFFFF0), + m_cur_span(0) + {} + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 2; + if(max_len > m_spans.size()) + { + m_spans.resize(max_len); + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_min_x = min_x; + m_cur_span = &m_spans[0]; + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover) + { + x -= m_min_x; + m_covers[x] = (cover_type)cover; + if(x == m_last_x+1) + { + m_cur_span->len++; + } + else + { + m_cur_span++; + m_cur_span->x = (coord_type)(x + m_min_x); + m_cur_span->len = 1; + m_cur_span->covers = &m_covers[x]; + } + m_last_x = x; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const cover_type* covers) + { + x -= m_min_x; + std::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; + std::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 m_covers; + pod_array m_spans; + span* m_cur_span; + }; + + + + + //==========================================================scanline_u8_am + // + // The scanline container with alpha-masking + // + //------------------------------------------------------------------------ + template + 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(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: + 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_array_type; + + //-------------------------------------------------------------------- + class const_iterator + { + public: + const_iterator(const span_array_type& spans) : + m_spans(spans), + m_span_idx(0) + {} + + const span& operator*() const { return m_spans[m_span_idx]; } + const span* operator->() const { return &m_spans[m_span_idx]; } + + void operator ++ () { ++m_span_idx; } + + private: + const span_array_type& m_spans; + unsigned m_span_idx; + }; + + //-------------------------------------------------------------------- + class iterator + { + public: + iterator(span_array_type& spans) : + m_spans(spans), + m_span_idx(0) + {} + + span& operator*() { return m_spans[m_span_idx]; } + span* operator->() { return &m_spans[m_span_idx]; } + + void operator ++ () { ++m_span_idx; } + + private: + span_array_type& m_spans; + unsigned m_span_idx; + }; + + + + //-------------------------------------------------------------------- + scanline32_u8() : + m_min_x(0), + m_last_x(0x7FFFFFF0), + m_covers() + {} + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 2; + if(max_len > m_covers.size()) + { + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_min_x = min_x; + m_spans.remove_all(); + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover) + { + x -= m_min_x; + m_covers[x] = cover_type(cover); + if(x == m_last_x+1) + { + m_spans.last().len++; + } + else + { + m_spans.add(span(coord_type(x + m_min_x), 1, &m_covers[x])); + } + m_last_x = x; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const cover_type* covers) + { + x -= m_min_x; + std::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; + std::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 m_covers; + span_array_type m_spans; + }; + + + + + //========================================================scanline32_u8_am + // + // The scanline container with alpha-masking + // + //------------------------------------------------------------------------ + template + 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(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: + AlphaMask* m_alpha_mask; + }; + + + +} + +#endif + diff --git a/agg2/include/agg_shorten_path.h b/agg/include/agg_shorten_path.h similarity index 95% rename from agg2/include/agg_shorten_path.h rename to agg/include/agg_shorten_path.h index 31fa3a8..dd9929f 100644 --- a/agg2/include/agg_shorten_path.h +++ b/agg/include/agg_shorten_path.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. diff --git a/agg2/include/agg_simul_eq.h b/agg/include/agg_simul_eq.h similarity index 95% rename from agg2/include/agg_simul_eq.h rename to agg/include/agg_simul_eq.h index 6c86d4a..f7bfafd 100644 --- a/agg2/include/agg_simul_eq.h +++ b/agg/include/agg_simul_eq.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -19,7 +19,7 @@ #ifndef AGG_SIMUL_EQ_INCLUDED #define AGG_SIMUL_EQ_INCLUDED -#include +#include #include "agg_basics.h" namespace agg @@ -51,7 +51,7 @@ namespace agg unsigned i; for(i = row; i < Rows; i++) { - if((tmp = fabs(m[i][row])) > max_val && tmp != 0.0) + if((tmp = std::fabs(m[i][row])) > max_val && tmp != 0.0) { max_val = tmp; k = i; diff --git a/agg/include/agg_span_allocator.h b/agg/include/agg_span_allocator.h new file mode 100644 index 0000000..201b69b --- /dev/null +++ b/agg/include/agg_span_allocator.h @@ -0,0 +1,54 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_ALLOCATOR_INCLUDED +#define AGG_SPAN_ALLOCATOR_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + //----------------------------------------------------------span_allocator + template class span_allocator + { + public: + typedef ColorT color_type; + + //-------------------------------------------------------------------- + AGG_INLINE color_type* allocate(unsigned span_len) + { + if(span_len > m_span.size()) + { + // To reduce the number of reallocs we align the + // span_len to 256 color elements. + // Well, I just like this number and it looks reasonable. + //----------------------- + m_span.resize(((span_len + 255) >> 8) << 8); + } + return &m_span[0]; + } + + AGG_INLINE color_type* span() { return &m_span[0]; } + AGG_INLINE unsigned max_span_len() const { return m_span.size(); } + + private: + pod_array m_span; + }; +} + + +#endif + + diff --git a/agg2/include/agg_span_converter.h b/agg/include/agg_span_converter.h similarity index 59% rename from agg2/include/agg_span_converter.h rename to agg/include/agg_span_converter.h index efe4cf3..91d0f87 100644 --- a/agg2/include/agg_span_converter.h +++ b/agg/include/agg_span_converter.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -21,31 +21,34 @@ namespace agg { //----------------------------------------------------------span_converter - template class span_converter + template class span_converter { public: typedef typename SpanGenerator::color_type color_type; - span_converter(SpanGenerator& span_gen, Conv& conv) : - m_span_gen(&span_gen), m_conv(&conv) {} + 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(unsigned max_span_len) - { - m_span_gen->prepare(max_span_len); + void prepare() + { + m_span_gen->prepare(); + m_span_cnv->prepare(); } //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void generate(color_type* span, int x, int y, unsigned len) { - color_type* span = m_span_gen->generate(x, y, len); - m_conv->convert(span, len); - return span; + m_span_gen->generate(span, x, y, len); + m_span_cnv->generate(span, x, y, len); } private: SpanGenerator* m_span_gen; - Conv* m_conv; + SpanConverter* m_span_cnv; }; } diff --git a/agg2/include/agg_span_gouraud.h b/agg/include/agg_span_gouraud.h similarity index 91% rename from agg2/include/agg_span_gouraud.h rename to agg/include/agg_span_gouraud.h index 2f7c7ae..2986c88 100644 --- a/agg2/include/agg_span_gouraud.h +++ b/agg/include/agg_span_gouraud.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -18,18 +18,15 @@ #include "agg_basics.h" #include "agg_math.h" -#include "agg_span_generator.h" namespace agg { //============================================================span_gouraud - template - class span_gouraud : public span_generator + template class span_gouraud { public: typedef ColorT color_type; - typedef Allocator alloc_type; struct coord_type { @@ -39,23 +36,21 @@ namespace agg }; //-------------------------------------------------------------------- - span_gouraud(alloc_type& alloc) : - span_generator(alloc), + span_gouraud() : m_vertex(0) { m_cmd[0] = path_cmd_stop; } //-------------------------------------------------------------------- - span_gouraud(alloc_type& alloc, - const color_type& c1, + 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) : - span_generator(alloc) + m_vertex(0) { colors(c1, c2, c3); triangle(x1, y1, x2, y2, x3, y3, d); @@ -132,8 +127,6 @@ namespace agg return m_cmd[m_vertex++]; } - - protected: //-------------------------------------------------------------------- void arrange_vertices(coord_type* coord) const @@ -164,7 +157,6 @@ namespace agg } } - private: //-------------------------------------------------------------------- coord_type m_coord[3]; diff --git a/agg/include/agg_span_gouraud_gray.h b/agg/include/agg_span_gouraud_gray.h new file mode 100644 index 0000000..aa73e5b --- /dev/null +++ b/agg/include/agg_span_gouraud_gray.h @@ -0,0 +1,243 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// 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 +#define AGG_SPAN_GOURAUD_GRAY_INCLUDED + +#include +#include +#include "agg_basics.h" +#include "agg_color_gray.h" +#include "agg_dda_line.h" +#include "agg_span_gouraud.h" + +namespace agg +{ + + //=======================================================span_gouraud_gray + template class span_gouraud_gray : public span_gouraud + { + public: + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + typedef span_gouraud 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) + { + 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]); + } + + //-------------------------------------------------------------------- + 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; + }; + + +} + +#endif diff --git a/agg/include/agg_span_gouraud_rgba.h b/agg/include/agg_span_gouraud_rgba.h new file mode 100644 index 0000000..887a334 --- /dev/null +++ b/agg/include/agg_span_gouraud_rgba.h @@ -0,0 +1,278 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// 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_RGBA_INCLUDED +#define AGG_SPAN_GOURAUD_RGBA_INCLUDED + +#include +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_dda_line.h" +#include "agg_span_gouraud.h" + +namespace agg +{ + + //=======================================================span_gouraud_rgba + template class span_gouraud_rgba : public span_gouraud + { + public: + typedef ColorT color_type; + typedef typename ColorT::value_type value_type; + typedef span_gouraud base_type; + typedef typename base_type::coord_type coord_type; + enum subpixel_scale_e + { + subpixel_shift = 4, + subpixel_scale = 1 << subpixel_shift + }; + + private: + //-------------------------------------------------------------------- + struct rgba_calc + { + 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 = (dy < 1e-5) ? 1e5 : 1.0 / dy; + m_r1 = c1.color.r; + m_g1 = c1.color.g; + m_b1 = c1.color.b; + m_a1 = c1.color.a; + m_dr = c2.color.r - m_r1; + m_dg = c2.color.g - m_g1; + m_db = c2.color.b - m_b1; + 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_r = m_r1 + iround(m_dr * k); + m_g = m_g1 + iround(m_dg * k); + m_b = m_b1 + iround(m_db * 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_r1; + int m_g1; + int m_b1; + int m_a1; + int m_dr; + int m_dg; + int m_db; + int m_da; + int m_r; + int m_g; + int m_b; + int m_a; + int m_x; + }; + + public: + + //-------------------------------------------------------------------- + span_gouraud_rgba() {} + span_gouraud_rgba(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_rgba1.init(coord[0], coord[2]); + m_rgba2.init(coord[0], coord[1]); + m_rgba3.init(coord[1], coord[2]); + } + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + m_rgba1.calc(y);//(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y); + const rgba_calc* pc1 = &m_rgba1; + const rgba_calc* pc2 = &m_rgba2; + + if(y <= m_y2) + { + // Bottom part of the triangle (first subtriangle) + //------------------------- + m_rgba2.calc(y + m_rgba2.m_1dy); + } + else + { + // Upper part (second subtriangle) + m_rgba3.calc(y - m_rgba3.m_1dy); + //------------------------- + pc2 = &m_rgba3; + } + + if(m_swap) + { + // It means that the triangle is oriented clockwise, + // so that we need to swap the controlling structures + //------------------------- + const rgba_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> r(pc1->m_r, pc2->m_r, nlen); + dda_line_interpolator<14> g(pc1->m_g, pc2->m_g, nlen); + dda_line_interpolator<14> b(pc1->m_b, pc2->m_b, 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); + r -= start; + g -= start; + b -= start; + a -= start; + nlen += start; + + int vr, vg, vb, 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) + { + vr = r.y(); + vg = g.y(); + vb = b.y(); + va = a.y(); + if(vr < 0) { vr = 0; } if(vr > lim) { vr = lim; } + if(vg < 0) { vg = 0; } if(vg > lim) { vg = lim; } + if(vb < 0) { vb = 0; } if(vb > lim) { vb = lim; } + if(va < 0) { va = 0; } if(va > lim) { va = lim; } + span->r = (value_type)vr; + span->g = (value_type)vg; + span->b = (value_type)vb; + span->a = (value_type)va; + r += subpixel_scale; + g += subpixel_scale; + b += 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->r = (value_type)r.y(); + span->g = (value_type)g.y(); + span->b = (value_type)b.y(); + span->a = (value_type)a.y(); + r += subpixel_scale; + g += subpixel_scale; + b += 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) + { + vr = r.y(); + vg = g.y(); + vb = b.y(); + va = a.y(); + if(vr < 0) { vr = 0; } if(vr > lim) { vr = lim; } + if(vg < 0) { vg = 0; } if(vg > lim) { vg = lim; } + if(vb < 0) { vb = 0; } if(vb > lim) { vb = lim; } + if(va < 0) { va = 0; } if(va > lim) { va = lim; } + span->r = (value_type)vr; + span->g = (value_type)vg; + span->b = (value_type)vb; + span->a = (value_type)va; + r += subpixel_scale; + g += subpixel_scale; + b += subpixel_scale; + a += subpixel_scale; + ++span; + --len; + } + } + + private: + bool m_swap; + int m_y2; + rgba_calc m_rgba1; + rgba_calc m_rgba2; + rgba_calc m_rgba3; + }; + + + +} + +#endif diff --git a/agg/include/agg_span_gradient.h b/agg/include/agg_span_gradient.h new file mode 100644 index 0000000..8cedbda --- /dev/null +++ b/agg/include/agg_span_gradient.h @@ -0,0 +1,376 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_GRADIENT_INCLUDED +#define AGG_SPAN_GRADIENT_INCLUDED + +#include +#include +#include "agg_basics.h" +#include "agg_math.h" +#include "agg_array.h" + + +namespace agg +{ + + enum gradient_subpixel_scale_e + { + gradient_subpixel_shift = 4, //-----gradient_subpixel_shift + gradient_subpixel_scale = 1 << gradient_subpixel_shift, //-----gradient_subpixel_scale + gradient_subpixel_mask = gradient_subpixel_scale - 1 //-----gradient_subpixel_mask + }; + + + + //==========================================================span_gradient + template + class span_gradient + { + public: + typedef Interpolator interpolator_type; + typedef ColorT color_type; + + enum downscale_shift_e + { + downscale_shift = interpolator_type::subpixel_shift - + gradient_subpixel_shift + }; + + //-------------------------------------------------------------------- + span_gradient() {} + + //-------------------------------------------------------------------- + span_gradient(interpolator_type& inter, + GradientF& gradient_function, + ColorF& color_function, + double d1, double d2) : + m_interpolator(&inter), + m_gradient_function(&gradient_function), + m_color_function(&color_function), + m_d1(iround(d1 * gradient_subpixel_scale)), + m_d2(iround(d2 * gradient_subpixel_scale)) + {} + + //-------------------------------------------------------------------- + interpolator_type& interpolator() { return *m_interpolator; } + const GradientF& gradient_function() const { return *m_gradient_function; } + const ColorF& color_function() const { return *m_color_function; } + double d1() const { return double(m_d1) / gradient_subpixel_scale; } + double d2() const { return double(m_d2) / gradient_subpixel_scale; } + + //-------------------------------------------------------------------- + void interpolator(interpolator_type& i) { m_interpolator = &i; } + void gradient_function(GradientF& gf) { m_gradient_function = &gf; } + void color_function(ColorF& cf) { m_color_function = &cf; } + void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); } + void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + int dd = m_d2 - m_d1; + if(dd < 1) dd = 1; + m_interpolator->begin(x+0.5, y+0.5, len); + do + { + m_interpolator->coordinates(&x, &y); + int d = m_gradient_function->calculate(x >> downscale_shift, + y >> downscale_shift, m_d2); + d = ((d - m_d1) * (int)m_color_function->size()) / dd; + if(d < 0) d = 0; + if(d >= (int)m_color_function->size()) d = m_color_function->size() - 1; + *span++ = (*m_color_function)[d]; + ++(*m_interpolator); + } + while(--len); + } + + private: + interpolator_type* m_interpolator; + GradientF* m_gradient_function; + ColorF* m_color_function; + int m_d1; + int m_d2; + }; + + + + + //=====================================================gradient_linear_color + template + struct gradient_linear_color + { + typedef ColorT color_type; + + gradient_linear_color() {} + gradient_linear_color(const color_type& c1, const color_type& c2, + unsigned size = 256) : + m_c1(c1), m_c2(c2), m_size(size) + // VFALCO 4/28/09 + ,m_mult(1/(double(size)-1)) + // VFALCO + {} + + unsigned size() const { return m_size; } + color_type operator [] (unsigned v) const + { + // VFALCO 4/28/09 + //return m_c1.gradient(m_c2, double(v) / double(m_size - 1)); + return m_c1.gradient(m_c2, double(v) * m_mult ); + // VFALCO + } + + void colors(const color_type& c1, const color_type& c2, unsigned size = 256) + { + m_c1 = c1; + m_c2 = c2; + m_size = size; + // VFALCO 4/28/09 + m_mult=1/(double(size)-1); + // VFALCO + } + + color_type m_c1; + color_type m_c2; + unsigned m_size; + // VFALCO 4/28/09 + double m_mult; + // VFALCO + }; + + + + + + + //==========================================================gradient_circle + class gradient_circle + { + // Actually the same as radial. Just for compatibility + public: + static AGG_INLINE int calculate(int x, int y, int) + { + return int(fast_sqrt(x*x + y*y)); + } + }; + + + //==========================================================gradient_radial + class gradient_radial + { + public: + static AGG_INLINE int calculate(int x, int y, int) + { + return int(fast_sqrt(x*x + y*y)); + } + }; + + //========================================================gradient_radial_d + class gradient_radial_d + { + public: + static AGG_INLINE int calculate(int x, int y, int) + { + return uround(std::sqrt(double(x)*double(x) + double(y)*double(y))); + } + }; + + //====================================================gradient_radial_focus + class gradient_radial_focus + { + public: + //--------------------------------------------------------------------- + gradient_radial_focus() : + m_r(100 * gradient_subpixel_scale), + m_fx(0), + m_fy(0) + { + update_values(); + } + + //--------------------------------------------------------------------- + gradient_radial_focus(double r, double fx, double fy) : + m_r (iround(r * gradient_subpixel_scale)), + m_fx(iround(fx * gradient_subpixel_scale)), + m_fy(iround(fy * gradient_subpixel_scale)) + { + update_values(); + } + + //--------------------------------------------------------------------- + void init(double r, double fx, double fy) + { + m_r = iround(r * gradient_subpixel_scale); + m_fx = iround(fx * gradient_subpixel_scale); + m_fy = iround(fy * gradient_subpixel_scale); + update_values(); + } + + //--------------------------------------------------------------------- + double radius() const { return double(m_r) / gradient_subpixel_scale; } + double focus_x() const { return double(m_fx) / gradient_subpixel_scale; } + double focus_y() const { return double(m_fy) / gradient_subpixel_scale; } + + //--------------------------------------------------------------------- + int calculate(int x, int y, int) const + { + double dx = x - m_fx; + double dy = y - m_fy; + double d2 = dx * m_fy - dy * m_fx; + double d3 = m_r2 * (dx * dx + dy * dy) - d2 * d2; + return iround((dx * m_fx + dy * m_fy + std::sqrt(std::fabs(d3))) * m_mul); + } + + private: + //--------------------------------------------------------------------- + void update_values() + { + // Calculate the invariant values. In case the focal center + // lies exactly on the gradient circle the divisor degenerates + // into zero. In this case we just move the focal center by + // one subpixel unit possibly in the direction to the origin (0,0) + // and calculate the values again. + //------------------------- + m_r2 = double(m_r) * double(m_r); + m_fx2 = double(m_fx) * double(m_fx); + m_fy2 = double(m_fy) * double(m_fy); + double d = (m_r2 - (m_fx2 + m_fy2)); + if(d == 0) + { + if(m_fx) { if(m_fx < 0) ++m_fx; else --m_fx; } + if(m_fy) { if(m_fy < 0) ++m_fy; else --m_fy; } + m_fx2 = double(m_fx) * double(m_fx); + m_fy2 = double(m_fy) * double(m_fy); + d = (m_r2 - (m_fx2 + m_fy2)); + } + m_mul = m_r / d; + } + + int m_r; + int m_fx; + int m_fy; + double m_r2; + double m_fx2; + double m_fy2; + double m_mul; + }; + + + //==============================================================gradient_x + class gradient_x + { + public: + static int calculate(int x, int, int) { return x; } + }; + + + //==============================================================gradient_y + class gradient_y + { + public: + static int calculate(int, int y, int) { return y; } + }; + + //========================================================gradient_diamond + class gradient_diamond + { + public: + static AGG_INLINE int calculate(int x, int y, int) + { + int ax = std::abs(x); + int ay = std::abs(y); + return ax > ay ? ax : ay; + } + }; + + //=============================================================gradient_xy + class gradient_xy + { + public: + static AGG_INLINE int calculate(int x, int y, int d) + { + return std::abs(x) * std::abs(y) / d; + } + }; + + //========================================================gradient_sqrt_xy + class gradient_sqrt_xy + { + public: + static AGG_INLINE int calculate(int x, int y, int) + { + return fast_sqrt(std::abs(x) * std::abs(y)); + } + }; + + //==========================================================gradient_conic + class gradient_conic + { + public: + static AGG_INLINE int calculate(int x, int y, int d) + { + return uround(std::fabs(std::atan2(double(y), double(x))) * double(d) / pi); + } + }; + + //=================================================gradient_repeat_adaptor + template class gradient_repeat_adaptor + { + public: + gradient_repeat_adaptor(const GradientF& gradient) : + m_gradient(&gradient) {} + + AGG_INLINE int calculate(int x, int y, int d) const + { + int ret = m_gradient->calculate(x, y, d) % d; + if(ret < 0) ret += d; + return ret; + } + + private: + const GradientF* m_gradient; + }; + + //================================================gradient_reflect_adaptor + template class gradient_reflect_adaptor + { + public: + gradient_reflect_adaptor(const GradientF& gradient) : + m_gradient(&gradient) {} + + AGG_INLINE int calculate(int x, int y, int d) const + { + int d2 = d << 1; + int ret = m_gradient->calculate(x, y, d) % d2; + if(ret < 0) ret += d2; + if(ret >= d) ret = d2 - ret; + return ret; + } + + private: + const GradientF* m_gradient; + }; + + +} + +#endif diff --git a/agg/include/agg_span_gradient_alpha.h b/agg/include/agg_span_gradient_alpha.h new file mode 100644 index 0000000..2ec040e --- /dev/null +++ b/agg/include/agg_span_gradient_alpha.h @@ -0,0 +1,126 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_GRADIENT_ALPHA_INCLUDED +#define AGG_SPAN_GRADIENT_ALPHA_INCLUDED + +#include "agg_span_gradient.h" + +namespace agg +{ + //======================================================span_gradient_alpha + template + class span_gradient_alpha + { + public: + typedef Interpolator interpolator_type; + typedef ColorT color_type; + typedef typename color_type::value_type alpha_type; + + enum downscale_shift_e + { + downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift + }; + + + //-------------------------------------------------------------------- + span_gradient_alpha() {} + + //-------------------------------------------------------------------- + span_gradient_alpha(interpolator_type& inter, + GradientF& gradient_function, + AlphaF& alpha_function, + double d1, double d2) : + m_interpolator(&inter), + m_gradient_function(&gradient_function), + m_alpha_function(&alpha_function), + m_d1(iround(d1 * gradient_subpixel_scale)), + m_d2(iround(d2 * gradient_subpixel_scale)) + {} + + //-------------------------------------------------------------------- + interpolator_type& interpolator() { return *m_interpolator; } + const GradientF& gradient_function() const { return *m_gradient_function; } + const AlphaF& alpha_function() const { return *m_alpha_function; } + double d1() const { return double(m_d1) / gradient_subpixel_scale; } + double d2() const { return double(m_d2) / gradient_subpixel_scale; } + + //-------------------------------------------------------------------- + void interpolator(interpolator_type& i) { m_interpolator = &i; } + void gradient_function(const GradientF& gf) { m_gradient_function = &gf; } + void alpha_function(const AlphaF& af) { m_alpha_function = ⁡ } + void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); } + void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + int dd = m_d2 - m_d1; + if(dd < 1) dd = 1; + m_interpolator->begin(x+0.5, y+0.5, len); + do + { + m_interpolator->coordinates(&x, &y); + int d = m_gradient_function->calculate(x >> downscale_shift, + y >> downscale_shift, m_d2); + d = ((d - m_d1) * (int)m_alpha_function->size()) / dd; + if(d < 0) d = 0; + if(d >= (int)m_alpha_function->size()) d = m_alpha_function->size() - 1; + span->a = (*m_alpha_function)[d]; + ++span; + ++(*m_interpolator); + } + while(--len); + } + + private: + interpolator_type* m_interpolator; + GradientF* m_gradient_function; + AlphaF* m_alpha_function; + int m_d1; + int m_d2; + }; + + + //=======================================================gradient_alpha_x + template struct gradient_alpha_x + { + typedef typename ColorT::value_type alpha_type; + alpha_type operator [] (alpha_type x) const { return x; } + }; + + //====================================================gradient_alpha_x_u8 + struct gradient_alpha_x_u8 + { + typedef int8u alpha_type; + alpha_type operator [] (alpha_type x) const { return x; } + }; + + //==========================================gradient_alpha_one_munus_x_u8 + struct gradient_alpha_one_munus_x_u8 + { + typedef int8u alpha_type; + alpha_type operator [] (alpha_type x) const { return 255-x; } + }; + +} + +#endif diff --git a/agg/include/agg_span_gradient_contour.h b/agg/include/agg_span_gradient_contour.h new file mode 100644 index 0000000..8defb1a --- /dev/null +++ b/agg/include/agg_span_gradient_contour.h @@ -0,0 +1,364 @@ +//---------------------------------------------------------------------------- +// AGG Contribution Pack - Gradients 1 (AGG CP - Gradients 1) +// http://milan.marusinec.sk/aggcp +// +// For Anti-Grain Geometry - Version 2.4 +// http://www.antigrain.org +// +// Contribution Created By: +// Milan Marusinec alias Milano +// milan@marusinec.sk +// Copyright (c) 2007-2008 +// +// 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. +// +// [History] ----------------------------------------------------------------- +// +// 02.02.2008-Milano: Ported from Object Pascal code of AggPas +// +#ifndef AGG_SPAN_GRADIENT_CONTOUR_INCLUDED +#define AGG_SPAN_GRADIENT_CONTOUR_INCLUDED + +#include "agg_basics.h" +#include "agg_trans_affine.h" +#include "agg_path_storage.h" +#include "agg_pixfmt_gray.h" +#include "agg_conv_transform.h" +#include "agg_conv_curve.h" +#include "agg_bounding_rect.h" +#include "agg_renderer_base.h" +#include "agg_renderer_primitives.h" +#include "agg_rasterizer_outline.h" +#include "agg_span_gradient.h" + +#include +#include +#include + +namespace agg +{ + + //==========================================================gradient_contour + class gradient_contour + { + private: + int8u* m_buffer; + int m_width; + int m_height; + int m_frame; + + double m_d1; + double m_d2; + + public: + gradient_contour() : + m_buffer(NULL), + m_width(0), + m_height(0), + m_frame(10), + m_d1(0), + m_d2(100) + { + } + + gradient_contour(double d1, double d2) : + m_buffer(NULL), + m_width(0), + m_height(0), + m_frame(10), + m_d1(d1), + m_d2(d2) + { + } + + ~gradient_contour() + { + if (m_buffer) + { + delete [] m_buffer; + } + } + + int8u* contour_create(path_storage* ps ); + + int contour_width() { return m_width; } + int contour_height() { return m_height; } + + void d1(double d ) { m_d1 = d; } + void d2(double d ) { m_d2 = d; } + + void frame(int f ) { m_frame = f; } + int frame() { return m_frame; } + + int calculate(int x, int y, int d) const + { + if (m_buffer) + { + int px = x >> agg::gradient_subpixel_shift; + int py = y >> agg::gradient_subpixel_shift; + + px %= m_width; + + if (px < 0) + { + px += m_width; + } + + py %= m_height; + + if (py < 0 ) + { + py += m_height; + } + + return iround(m_buffer[py * m_width + px ] * (m_d2 / 256 ) + m_d1 ) << gradient_subpixel_shift; + + } + else + { + return 0; + } + } + + }; + + static AGG_INLINE int square(int x ) { return x * x; } + + // DT algorithm by: Pedro Felzenszwalb + void dt(float* spanf, float* spang, float* spanr, int* spann ,int length ) + { + int k = 0; + float s; + + spann[0 ] = 0; + spang[0 ] = -FLT_MAX; + spang[1 ] = FLT_MAX; + + for (int q = 1; q <= length - 1; q++) + { + s = ((spanf[q ] + square(q ) ) - (spanf[spann[k ] ] + square(spann[k ] ) ) ) / (2 * q - 2 * spann[k ] ); + + while (s <= spang[k ]) + { + k--; + s = ((spanf[q ] + square(q ) ) - (spanf[spann[k ] ] + square(spann[k ] ) ) ) / (2 * q - 2 * spann[k ] ); + } + + k++; + spann[k ] = q; + spang[k ] = s; + spang[k + 1 ] = FLT_MAX; + + } + + k = 0; + + for (int q = 0; q <= length - 1; q++) + { + while (spang[k + 1 ] < q ) + { + k++; + } + + spanr[q ] = square(q - spann[k ] ) + spanf[spann[k ] ]; + } + } + + // DT algorithm by: Pedro Felzenszwalb + int8u* gradient_contour::contour_create(path_storage* ps ) + { + int8u* result = NULL; + + if (ps) + { + // I. Render Black And White NonAA Stroke of the Path + // Path Bounding Box + Some Frame Space Around [configurable] + agg::conv_curve conv(*ps); + + double x1, y1, x2, y2; + + if (agg::bounding_rect_single(conv ,0 ,&x1 ,&y1 ,&x2 ,&y2 )) + { + // Create BW Rendering Surface + int width = int(ceil(x2 - x1 ) ) + m_frame * 2 + 1; + int height = int(ceil(y2 - y1 ) ) + m_frame * 2 + 1; + + int8u* buffer = new int8u[width * height]; + + if (buffer) + { + std::memset(buffer ,255 ,width * height ); + + // Setup VG Engine & Render + agg::rendering_buffer rb; + rb.attach(buffer ,width ,height ,width ); + + agg::pixfmt_gray8 pf(rb); + agg::renderer_base renb(pf ); + + agg::renderer_primitives > prim(renb ); + agg::rasterizer_outline > > ras(prim ); + + agg::trans_affine mtx; + mtx *= agg::trans_affine_translation(-x1 + m_frame, -y1 + m_frame ); + + agg::conv_transform > trans(conv ,mtx ); + + prim.line_color(agg::rgba8(0 ,0 ,0 ,255 ) ); + ras.add_path(trans ); + + // II. Distance Transform + // Create Float Buffer + 0 vs infinity assignment + float* image = new float[width * height]; + + if (image) + { + for (int y = 0, l = 0; y < height; y++ ) + { + for (int x = 0; x < width; x++, l++ ) + { + if (buffer[l ] == 0) + { + image[l ] = 0.0; + } + else + { + image[l ] = FLT_MAX; + } + } + + } + + // DT of 2d + // SubBuff max width,height + int length = width; + + if (height > length) + { + length = height; + } + + float* spanf = new float[length]; + float* spang = new float[length + 1]; + float* spanr = new float[length]; + int* spann = new int[length]; + + if ((spanf) && (spang) && (spanr) && (spann)) + { + // Transform along columns + for (int x = 0; x < width; x++ ) + { + for (int y = 0; y < height; y++ ) + { + spanf[y] = image[y * width + x]; + } + + // DT of 1d + dt(spanf ,spang ,spanr ,spann ,height ); + + for (int y = 0; y < height; y++ ) + { + image[y * width + x] = spanr[y]; + } + } + + // Transform along rows + for (int y = 0; y < height; y++ ) + { + for (int x = 0; x < width; x++ ) + { + spanf[x] = image[y * width + x]; + } + + // DT of 1d + dt(spanf ,spang ,spanr ,spann ,width ); + + for (int x = 0; x < width; x++ ) + { + image[y * width + x] = spanr[x]; + } + } + + // Take Square Roots, Min & Max + float min = std::sqrt(image[0] ); + float max = min; + + for (int y = 0, l = 0; y < height; y++ ) + { + for (int x = 0; x < width; x++, l++ ) + { + image[l] = std::sqrt(image[l]); + + if (min > image[l]) + { + min = image[l]; + } + + if (max < image[l]) + { + max = image[l]; + } + + } + } + + // III. Convert To Grayscale + if (min == max) + { + std::memset(buffer ,0 ,width * height ); + } + else + { + float scale = 255 / (max - min ); + + for (int y = 0, l = 0; y < height; y++ ) + { + for (int x = 0; x < width; x++ ,l++ ) + { + buffer[l] = int8u(int((image[l] - min ) * scale )); + } + } + } + + // OK + if (m_buffer) + { + delete [] m_buffer; + } + + m_buffer = buffer; + m_width = width; + m_height = height; + + buffer = NULL; + result = m_buffer; + + } + + if (spanf) { delete [] spanf; } + if (spang) { delete [] spang; } + if (spanr) { delete [] spanr; } + if (spann) { delete [] spann; } + + delete [] image; + + } + } + + if (buffer) + { + delete [] buffer; + } + + } + + } + return result; + } + +} + +#endif diff --git a/agg/include/agg_span_gradient_image.h b/agg/include/agg_span_gradient_image.h new file mode 100644 index 0000000..67f5c80 --- /dev/null +++ b/agg/include/agg_span_gradient_image.h @@ -0,0 +1,189 @@ +//---------------------------------------------------------------------------- +// AGG Contribution Pack - Gradients 1 (AGG CP - Gradients 1) +// http://milan.marusinec.sk/aggcp +// +// For Anti-Grain Geometry - Version 2.4 +// http://www.antigrain.org +// +// Contribution Created By: +// Milan Marusinec alias Milano +// milan@marusinec.sk +// Copyright (c) 2007-2008 +// +// 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. +// +// [History] ----------------------------------------------------------------- +// +// 03.02.2008-Milano: Ported from Object Pascal code of AggPas +// +#ifndef AGG_SPAN_GRADIENT_IMAGE_INCLUDED +#define AGG_SPAN_GRADIENT_IMAGE_INCLUDED + +#include +#include "agg_basics.h" +#include "agg_span_gradient.h" +#include "agg_color_rgba.h" +#include "agg_rendering_buffer.h" +#include "agg_pixfmt_rgba.h" + +namespace agg +{ + + //==========================================================one_color_function + template class one_color_function + { + public: + typedef ColorT color_type; + + color_type m_color; + + one_color_function() : + m_color() + { + } + + static unsigned size() { return 1; } + + const color_type& operator [] (unsigned i) const + { + return m_color; + } + + color_type* operator [] (unsigned i) + { + return &m_color; + } + }; + + //==========================================================gradient_image + template class gradient_image + { + private: + //------------ fields + typedef ColorT color_type; + typedef agg::pixfmt_rgba32 pixfmt_type; + + agg::rgba8* m_buffer; + + int m_alocdx; + int m_alocdy; + int m_width; + int m_height; + + color_type* m_color; + + one_color_function m_color_function; + + public: + gradient_image() : + m_color_function(), + m_buffer(NULL), + m_alocdx(0), + m_alocdy(0), + m_width(0), + m_height(0) + { + m_color = m_color_function[0 ]; + } + + ~gradient_image() + { + if (m_buffer) { delete [] m_buffer; } + } + + void* image_create(int width, int height ) + { + void* result = NULL; + + if (width > m_alocdx || height > m_alocdy) + { + if (m_buffer) { delete [] m_buffer; } + + m_buffer = NULL; + m_buffer = new agg::rgba8[width * height]; + + if (m_buffer) + { + m_alocdx = width; + m_alocdy = height; + } + else + { + m_alocdx = 0; + m_alocdy = 0; + }; + }; + + if (m_buffer) + { + m_width = width; + m_height = height; + + for (int rows = 0; rows < height; rows++) + { + agg::rgba8* row = &m_buffer[rows * m_alocdx ]; + std::memset(row ,0 ,m_width * 4 ); + }; + + result = m_buffer; + }; + return result; + } + + void* image_buffer() { return m_buffer; } + int image_width() { return m_width; } + int image_height() { return m_height; } + int image_stride() { return m_alocdx * 4; } + + int calculate(int x, int y, int d) const + { + if (m_buffer) + { + int px = x >> agg::gradient_subpixel_shift; + int py = y >> agg::gradient_subpixel_shift; + + px %= m_width; + + if (px < 0) + { + px += m_width; + } + + py %= m_height; + + if (py < 0 ) + { + py += m_height; + } + + rgba8* pixel = &m_buffer[py * m_alocdx + px ]; + + m_color->r = pixel->r; + m_color->g = pixel->g; + m_color->b = pixel->b; + m_color->a = pixel->a; + + } + else + { + m_color->r = 0; + m_color->g = 0; + m_color->b = 0; + m_color->a = 0; + } + return 0; + } + + const one_color_function& color_function() const + { + return m_color_function; + } + + }; + +} + +#endif diff --git a/agg/include/agg_span_image_filter.h b/agg/include/agg_span_image_filter.h new file mode 100644 index 0000000..9d0a10a --- /dev/null +++ b/agg/include/agg_span_image_filter.h @@ -0,0 +1,247 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Image transformations with filtering. Span generator base class +// +//---------------------------------------------------------------------------- +#ifndef AGG_SPAN_IMAGE_FILTER_INCLUDED +#define AGG_SPAN_IMAGE_FILTER_INCLUDED + +#include "agg_basics.h" +#include "agg_image_filters.h" +#include "agg_span_interpolator_linear.h" + +namespace agg +{ + + //-------------------------------------------------------span_image_filter + template class span_image_filter + { + public: + typedef Source source_type; + typedef Interpolator interpolator_type; + + //-------------------------------------------------------------------- + span_image_filter() {} + span_image_filter(source_type& src, + interpolator_type& interpolator, + image_filter_lut* filter) : + m_src(&src), + m_interpolator(&interpolator), + m_filter(filter), + m_dx_dbl(0.5), + m_dy_dbl(0.5), + m_dx_int(image_subpixel_scale / 2), + m_dy_int(image_subpixel_scale / 2) + {} + void attach(source_type& v) { m_src = &v; } + + //-------------------------------------------------------------------- + source_type& source() { return *m_src; } + const source_type& source() const { return *m_src; } + const image_filter_lut& filter() const { return *m_filter; } + int filter_dx_int() const { return m_dx_int; } + int filter_dy_int() const { return m_dy_int; } + double filter_dx_dbl() const { return m_dx_dbl; } + double filter_dy_dbl() const { return m_dy_dbl; } + + //-------------------------------------------------------------------- + void interpolator(interpolator_type& v) { m_interpolator = &v; } + void filter(image_filter_lut& v) { m_filter = &v; } + void filter_offset(double dx, double dy) + { + m_dx_dbl = dx; + m_dy_dbl = dy; + m_dx_int = iround(dx * image_subpixel_scale); + m_dy_int = iround(dy * image_subpixel_scale); + } + void filter_offset(double d) { filter_offset(d, d); } + + //-------------------------------------------------------------------- + interpolator_type& interpolator() { return *m_interpolator; } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + private: + source_type* m_src; + interpolator_type* m_interpolator; + image_filter_lut* m_filter; + double m_dx_dbl; + double m_dy_dbl; + unsigned m_dx_int; + unsigned m_dy_int; + }; + + + + + //==============================================span_image_resample_affine + template + class span_image_resample_affine : + public span_image_filter > + { + public: + typedef Source source_type; + typedef span_interpolator_linear interpolator_type; + typedef span_image_filter base_type; + + //-------------------------------------------------------------------- + span_image_resample_affine() : + m_scale_limit(200.0), + m_blur_x(1.0), + m_blur_y(1.0) + {} + + //-------------------------------------------------------------------- + span_image_resample_affine(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, &filter), + m_scale_limit(200.0), + m_blur_x(1.0), + m_blur_y(1.0) + {} + + + //-------------------------------------------------------------------- + int scale_limit() const { return uround(m_scale_limit); } + void scale_limit(int v) { m_scale_limit = v; } + + //-------------------------------------------------------------------- + double blur_x() const { return m_blur_x; } + double blur_y() const { return m_blur_y; } + void blur_x(double v) { m_blur_x = v; } + void blur_y(double v) { m_blur_y = v; } + void blur(double v) { m_blur_x = m_blur_y = v; } + + //-------------------------------------------------------------------- + void prepare() + { + double scale_x; + double scale_y; + + base_type::interpolator().transformer().scaling_abs(&scale_x, &scale_y); + + double scale_xy = scale_x * scale_y; + if (scale_xy > m_scale_limit) + { + scale_x = scale_x * m_scale_limit / scale_xy; + scale_y = scale_y * m_scale_limit / scale_xy; + } + + if(scale_x < 1) scale_x = 1; + if(scale_y < 1) scale_y = 1; + + if(scale_x > m_scale_limit) scale_x = m_scale_limit; + if(scale_y > m_scale_limit) scale_y = m_scale_limit; + + scale_x *= m_blur_x; + scale_y *= m_blur_y; + + if(scale_x < 1) scale_x = 1; + if(scale_y < 1) scale_y = 1; + + m_rx = uround( scale_x * double(image_subpixel_scale)); + m_rx_inv = uround(1.0/scale_x * double(image_subpixel_scale)); + + m_ry = uround( scale_y * double(image_subpixel_scale)); + m_ry_inv = uround(1.0/scale_y * double(image_subpixel_scale)); + } + + protected: + int m_rx; + int m_ry; + int m_rx_inv; + int m_ry_inv; + + private: + double m_scale_limit; + double m_blur_x; + double m_blur_y; + }; + + + + //=====================================================span_image_resample + template + class span_image_resample : + public span_image_filter + { + public: + typedef Source source_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + + //-------------------------------------------------------------------- + span_image_resample() : + m_scale_limit(20), + m_blur_x(image_subpixel_scale), + m_blur_y(image_subpixel_scale) + {} + + //-------------------------------------------------------------------- + span_image_resample(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, &filter), + m_scale_limit(20), + m_blur_x(image_subpixel_scale), + m_blur_y(image_subpixel_scale) + {} + + //-------------------------------------------------------------------- + int scale_limit() const { return m_scale_limit; } + void scale_limit(int v) { m_scale_limit = v; } + + //-------------------------------------------------------------------- + double blur_x() const { return double(m_blur_x) / double(image_subpixel_scale); } + double blur_y() const { return double(m_blur_y) / double(image_subpixel_scale); } + void blur_x(double v) { m_blur_x = uround(v * double(image_subpixel_scale)); } + void blur_y(double v) { m_blur_y = uround(v * double(image_subpixel_scale)); } + void blur(double v) { m_blur_x = + m_blur_y = uround(v * double(image_subpixel_scale)); } + + protected: + AGG_INLINE void adjust_scale(int* rx, int* ry) + { + if(*rx < image_subpixel_scale) *rx = image_subpixel_scale; + if(*ry < image_subpixel_scale) *ry = image_subpixel_scale; + if(*rx > image_subpixel_scale * m_scale_limit) + { + *rx = image_subpixel_scale * m_scale_limit; + } + if(*ry > image_subpixel_scale * m_scale_limit) + { + *ry = image_subpixel_scale * m_scale_limit; + } + *rx = (*rx * m_blur_x) >> image_subpixel_shift; + *ry = (*ry * m_blur_y) >> image_subpixel_shift; + if(*rx < image_subpixel_scale) *rx = image_subpixel_scale; + if(*ry < image_subpixel_scale) *ry = image_subpixel_scale; + } + + int m_scale_limit; + int m_blur_x; + int m_blur_y; + }; + + + + +} + +#endif diff --git a/agg/include/agg_span_image_filter_gray.h b/agg/include/agg_span_image_filter_gray.h new file mode 100644 index 0000000..e2c688e --- /dev/null +++ b/agg/include/agg_span_image_filter_gray.h @@ -0,0 +1,723 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// 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_IMAGE_FILTER_GRAY_INCLUDED +#define AGG_SPAN_IMAGE_FILTER_GRAY_INCLUDED + +#include "agg_basics.h" +#include "agg_color_gray.h" +#include "agg_span_image_filter.h" + + +namespace agg +{ + + //==============================================span_image_filter_gray_nn + template + class span_image_filter_gray_nn : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_gray_nn() {} + span_image_filter_gray_nn(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + do + { + base_type::interpolator().coordinates(&x, &y); + span->v = *(const value_type*) + base_type::source().span(x >> image_subpixel_shift, + y >> image_subpixel_shift, + 1); + span->a = color_type::full_value(); + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + + + //=========================================span_image_filter_gray_bilinear + template + class span_image_filter_gray_bilinear : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_gray_bilinear() {} + span_image_filter_gray_bilinear(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg; + const value_type *fg_ptr; + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + fg = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + fg += *fg_ptr * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); + + fg_ptr = (const value_type*)base_type::source().next_x(); + fg += *fg_ptr * x_hr * (image_subpixel_scale - y_hr); + + fg_ptr = (const value_type*)base_type::source().next_y(); + fg += *fg_ptr * (image_subpixel_scale - x_hr) * y_hr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + fg += *fg_ptr * x_hr * y_hr; + + span->v = color_type::downshift(fg, image_subpixel_shift * 2); + span->a = color_type::full_value(); + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + //====================================span_image_filter_gray_bilinear_clip + template + class span_image_filter_gray_bilinear_clip : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_gray_bilinear_clip() {} + span_image_filter_gray_bilinear_clip(source_type& src, + const color_type& back_color, + interpolator_type& inter) : + base_type(src, inter, 0), + m_back_color(back_color) + {} + const color_type& background_color() const { return m_back_color; } + void background_color(const color_type& v) { m_back_color = v; } + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg; + long_type src_alpha; + value_type back_v = m_back_color.v; + value_type back_a = m_back_color.a; + + const value_type *fg_ptr; + + int maxx = base_type::source().width() - 1; + int maxy = base_type::source().height() - 1; + + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + if(x_lr >= 0 && y_lr >= 0 && + x_lr < maxx && y_lr < maxy) + { + fg = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr; + + fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); + fg += *fg_ptr++ * (image_subpixel_scale - y_hr) * x_hr; + + ++y_lr; + fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr; + + fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * y_hr; + fg += *fg_ptr++ * x_hr * y_hr; + + fg = color_type::downshift(fg, image_subpixel_shift * 2); + src_alpha = color_type::full_value(); + } + else + { + unsigned weight; + if(x_lr < -1 || y_lr < -1 || + x_lr > maxx || y_lr > maxy) + { + fg = back_v; + src_alpha = back_a; + } + else + { + fg = src_alpha = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg += weight * + *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); + src_alpha += weight * color_type::full_value(); + } + else + { + fg += back_v * weight; + src_alpha += back_a * weight; + } + + x_lr++; + + weight = x_hr * (image_subpixel_scale - y_hr); + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg += weight * + *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); + src_alpha += weight * color_type::full_value(); + } + else + { + fg += back_v * weight; + src_alpha += back_a * weight; + } + + x_lr--; + y_lr++; + + weight = (image_subpixel_scale - x_hr) * y_hr; + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg += weight * + *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); + src_alpha += weight * color_type::full_value(); + } + else + { + fg += back_v * weight; + src_alpha += back_a * weight; + } + + x_lr++; + + weight = x_hr * y_hr; + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg += weight * + *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); + src_alpha += weight * color_type::full_value(); + } + else + { + fg += back_v * weight; + src_alpha += back_a * weight; + } + + fg = color_type::downshift(fg, image_subpixel_shift * 2); + src_alpha = color_type::downshift(src_alpha, image_subpixel_shift * 2); + } + } + + span->v = (value_type)fg; + span->a = (value_type)src_alpha; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + private: + color_type m_back_color; + }; + + + + //==============================================span_image_filter_gray_2x2 + template + class span_image_filter_gray_2x2 : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_gray_2x2() {} + span_image_filter_gray_2x2(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, &filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg; + + const value_type *fg_ptr; + const int16* weight_array = base_type::filter().weight_array() + + ((base_type::filter().diameter()/2 - 1) << + image_subpixel_shift); + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + fg = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg += weight * *fg_ptr; + + fg >>= image_filter_shift; + if(fg > color_type::full_value()) fg = color_type::full_value(); + + span->v = (value_type)fg; + span->a = color_type::full_value(); + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + + + //==================================================span_image_filter_gray + template + class span_image_filter_gray : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_gray() {} + span_image_filter_gray(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, &filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg; + const value_type *fg_ptr; + + unsigned diameter = base_type::filter().diameter(); + int start = base_type::filter().start(); + const int16* weight_array = base_type::filter().weight_array(); + + int x_count; + int weight_y; + + do + { + base_type::interpolator().coordinates(&x, &y); + + x -= base_type::filter_dx_int(); + y -= base_type::filter_dy_int(); + + int x_hr = x; + int y_hr = y; + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + fg = 0; + + int x_fract = x_hr & image_subpixel_mask; + unsigned y_count = diameter; + + y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); + fg_ptr = (const value_type*)base_type::source().span(x_lr + start, + y_lr + start, + diameter); + for(;;) + { + x_count = diameter; + weight_y = weight_array[y_hr]; + x_hr = image_subpixel_mask - x_fract; + for(;;) + { + fg += *fg_ptr * + ((weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + image_filter_shift); + if(--x_count == 0) break; + x_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + + if(--y_count == 0) break; + y_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg = color_type::downshift(fg, image_filter_shift); + if(fg < 0) fg = 0; + if(fg > color_type::full_value()) fg = color_type::full_value(); + span->v = (value_type)fg; + span->a = color_type::full_value(); + + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //=========================================span_image_resample_gray_affine + template + class span_image_resample_gray_affine : + public span_image_resample_affine + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef span_image_resample_affine base_type; + typedef typename base_type::interpolator_type interpolator_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_gray_affine() {} + span_image_resample_gray_affine(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + int radius_x = (diameter * base_type::m_rx) >> 1; + int radius_y = (diameter * base_type::m_ry) >> 1; + int len_x_lr = + (diameter * base_type::m_rx + image_subpixel_mask) >> + image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + + do + { + base_type::interpolator().coordinates(&x, &y); + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg = 0; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + base_type::m_ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + base_type::m_rx_inv) >> + image_subpixel_shift; + + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + + fg += *fg_ptr * weight; + total_weight += weight; + x_hr += base_type::m_rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + y_hr += base_type::m_ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg /= total_weight; + if(fg < 0) fg = 0; + if(fg > color_type::full_value()) fg = color_type::full_value(); + + span->v = (value_type)fg; + span->a = color_type::full_value(); + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + + + //================================================span_image_resample_gray + template + class span_image_resample_gray : + public span_image_resample + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_resample base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_gray() {} + span_image_resample_gray(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + do + { + int rx; + int ry; + int rx_inv = image_subpixel_scale; + int ry_inv = image_subpixel_scale; + base_type::interpolator().coordinates(&x, &y); + base_type::interpolator().local_scale(&rx, &ry); + base_type::adjust_scale(&rx, &ry); + + rx_inv = image_subpixel_scale * image_subpixel_scale / rx; + ry_inv = image_subpixel_scale * image_subpixel_scale / ry; + + int radius_x = (diameter * rx) >> 1; + int radius_y = (diameter * ry) >> 1; + int len_x_lr = + (diameter * rx + image_subpixel_mask) >> + image_subpixel_shift; + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg = 0; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + rx_inv) >> + image_subpixel_shift; + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + fg += *fg_ptr * weight; + total_weight += weight; + x_hr += rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + y_hr += ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg /= total_weight; + if(fg < 0) fg = 0; + if(fg > color_type::full_value()) fg = color_type::full_value(); + + span->v = (value_type)fg; + span->a = color_type::full_value(); + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + +} + + +#endif + + + diff --git a/agg/include/agg_span_image_filter_rgb.h b/agg/include/agg_span_image_filter_rgb.h new file mode 100644 index 0000000..f78ae19 --- /dev/null +++ b/agg/include/agg_span_image_filter_rgb.h @@ -0,0 +1,861 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// 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_IMAGE_FILTER_RGB_INCLUDED +#define AGG_SPAN_IMAGE_FILTER_RGB_INCLUDED + +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_span_image_filter.h" + + +namespace agg +{ + + //===============================================span_image_filter_rgb_nn + template + class span_image_filter_rgb_nn : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgb_nn() {} + span_image_filter_rgb_nn(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + do + { + base_type::interpolator().coordinates(&x, &y); + const value_type* fg_ptr = (const value_type*) + base_type::source().span(x >> image_subpixel_shift, + y >> image_subpixel_shift, + 1); + span->r = fg_ptr[order_type::R]; + span->g = fg_ptr[order_type::G]; + span->b = fg_ptr[order_type::B]; + span->a = color_type::full_value(); + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //==========================================span_image_filter_rgb_bilinear + template + class span_image_filter_rgb_bilinear : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgb_bilinear() {} + span_image_filter_rgb_bilinear(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg[3]; + const value_type *fg_ptr; + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + + fg[0] = fg[1] = fg[2] = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = x_hr * (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (image_subpixel_scale - x_hr) * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = x_hr * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + span->r = color_type::downshift(fg[order_type::R], image_subpixel_shift * 2); + span->g = color_type::downshift(fg[order_type::G], image_subpixel_shift * 2); + span->b = color_type::downshift(fg[order_type::B], image_subpixel_shift * 2); + span->a = color_type::full_value(); + + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //=====================================span_image_filter_rgb_bilinear_clip + template + class span_image_filter_rgb_bilinear_clip : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgb_bilinear_clip() {} + span_image_filter_rgb_bilinear_clip(source_type& src, + const color_type& back_color, + interpolator_type& inter) : + base_type(src, inter, 0), + m_back_color(back_color) + {} + const color_type& background_color() const { return m_back_color; } + void background_color(const color_type& v) { m_back_color = v; } + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg[3]; + long_type src_alpha; + value_type back_r = m_back_color.r; + value_type back_g = m_back_color.g; + value_type back_b = m_back_color.b; + value_type back_a = m_back_color.a; + + const value_type *fg_ptr; + + int maxx = base_type::source().width() - 1; + int maxy = base_type::source().height() - 1; + + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + unsigned weight; + + if(x_lr >= 0 && y_lr >= 0 && + x_lr < maxx && y_lr < maxy) + { + fg[0] = fg[1] = fg[2] = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + + weight = x_hr * (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + + ++y_lr; + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + + weight = (image_subpixel_scale - x_hr) * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + + weight = x_hr * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + + fg[0] = color_type::downshift(fg[0], image_subpixel_shift * 2); + fg[1] = color_type::downshift(fg[1], image_subpixel_shift * 2); + fg[2] = color_type::downshift(fg[2], image_subpixel_shift * 2); + src_alpha = color_type::full_value(); + } + else + { + if(x_lr < -1 || y_lr < -1 || + x_lr > maxx || y_lr > maxy) + { + fg[order_type::R] = back_r; + fg[order_type::G] = back_g; + fg[order_type::B] = back_b; + src_alpha = back_a; + } + else + { + fg[0] = fg[1] = fg[2] = src_alpha = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + src_alpha += weight * color_type::full_value(); + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + src_alpha += back_a * weight; + } + + x_lr++; + + weight = x_hr * (image_subpixel_scale - y_hr); + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + src_alpha += weight * color_type::full_value(); + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + src_alpha += back_a * weight; + } + + x_lr--; + y_lr++; + + weight = (image_subpixel_scale - x_hr) * y_hr; + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + src_alpha += weight * color_type::full_value(); + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + src_alpha += back_a * weight; + } + + x_lr++; + + weight = x_hr * y_hr; + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + src_alpha += weight * color_type::full_value(); + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + src_alpha += back_a * weight; + } + + fg[0] = color_type::downshift(fg[0], image_subpixel_shift * 2); + fg[1] = color_type::downshift(fg[1], image_subpixel_shift * 2); + fg[2] = color_type::downshift(fg[2], image_subpixel_shift * 2); + src_alpha = color_type::downshift(src_alpha, image_subpixel_shift * 2); + } + } + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)src_alpha; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + private: + color_type m_back_color; + }; + + + + //===============================================span_image_filter_rgb_2x2 + template + class span_image_filter_rgb_2x2 : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgb_2x2() {} + span_image_filter_rgb_2x2(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, &filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[3]; + + const value_type *fg_ptr; + const int16* weight_array = base_type::filter().weight_array() + + ((base_type::filter().diameter()/2 - 1) << + image_subpixel_shift); + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + fg[0] = fg[1] = fg[2] = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg[0] = color_type::downshift(fg[0], image_filter_shift); + fg[1] = color_type::downshift(fg[1], image_filter_shift); + fg[2] = color_type::downshift(fg[2], image_filter_shift); + + if(fg[order_type::R] > color_type::full_value()) fg[order_type::R] = color_type::full_value(); + if(fg[order_type::G] > color_type::full_value()) fg[order_type::G] = color_type::full_value(); + if(fg[order_type::B] > color_type::full_value()) fg[order_type::B] = color_type::full_value(); + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = color_type::full_value(); + + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //===================================================span_image_filter_rgb + template + class span_image_filter_rgb : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgb() {} + span_image_filter_rgb(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, &filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[3]; + const value_type *fg_ptr; + + unsigned diameter = base_type::filter().diameter(); + int start = base_type::filter().start(); + const int16* weight_array = base_type::filter().weight_array(); + + int x_count; + int weight_y; + + do + { + base_type::interpolator().coordinates(&x, &y); + + x -= base_type::filter_dx_int(); + y -= base_type::filter_dy_int(); + + int x_hr = x; + int y_hr = y; + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + fg[0] = fg[1] = fg[2] = 0; + + int x_fract = x_hr & image_subpixel_mask; + unsigned y_count = diameter; + + y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); + fg_ptr = (const value_type*)base_type::source().span(x_lr + start, + y_lr + start, + diameter); + for(;;) + { + x_count = diameter; + weight_y = weight_array[y_hr]; + x_hr = image_subpixel_mask - x_fract; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + image_filter_shift; + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + if(--x_count == 0) break; + x_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + + if(--y_count == 0) break; + y_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg[0] = color_type::downshift(fg[0], image_filter_shift); + fg[1] = color_type::downshift(fg[1], image_filter_shift); + fg[2] = color_type::downshift(fg[2], image_filter_shift); + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + + if(fg[order_type::R] > color_type::full_value()) fg[order_type::R] = color_type::full_value(); + if(fg[order_type::G] > color_type::full_value()) fg[order_type::G] = color_type::full_value(); + if(fg[order_type::B] > color_type::full_value()) fg[order_type::B] = color_type::full_value(); + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = color_type::full_value(); + + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //==========================================span_image_resample_rgb_affine + template + class span_image_resample_rgb_affine : + public span_image_resample_affine + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef span_image_resample_affine base_type; + typedef typename base_type::interpolator_type interpolator_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_rgb_affine() {} + span_image_resample_rgb_affine(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[3]; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + int radius_x = (diameter * base_type::m_rx) >> 1; + int radius_y = (diameter * base_type::m_ry) >> 1; + int len_x_lr = + (diameter * base_type::m_rx + image_subpixel_mask) >> + image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + + do + { + base_type::interpolator().coordinates(&x, &y); + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg[0] = fg[1] = fg[2] = 0; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + base_type::m_ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + base_type::m_rx_inv) >> + image_subpixel_shift; + + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + + fg[0] += *fg_ptr++ * weight; + fg[1] += *fg_ptr++ * weight; + fg[2] += *fg_ptr * weight; + total_weight += weight; + x_hr += base_type::m_rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + y_hr += base_type::m_ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg[0] /= total_weight; + fg[1] /= total_weight; + fg[2] /= total_weight; + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + + if(fg[order_type::R] > color_type::full_value()) fg[order_type::R] = color_type::full_value(); + if(fg[order_type::G] > color_type::full_value()) fg[order_type::G] = color_type::full_value(); + if(fg[order_type::B] > color_type::full_value()) fg[order_type::B] = color_type::full_value(); + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = color_type::full_value(); + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + + + //=================================================span_image_resample_rgb + template + class span_image_resample_rgb : + public span_image_resample + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_resample base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_rgb() {} + span_image_resample_rgb(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg[3]; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + do + { + int rx; + int ry; + int rx_inv = image_subpixel_scale; + int ry_inv = image_subpixel_scale; + base_type::interpolator().coordinates(&x, &y); + base_type::interpolator().local_scale(&rx, &ry); + base_type::adjust_scale(&rx, &ry); + + rx_inv = image_subpixel_scale * image_subpixel_scale / rx; + ry_inv = image_subpixel_scale * image_subpixel_scale / ry; + + int radius_x = (diameter * rx) >> 1; + int radius_y = (diameter * ry) >> 1; + int len_x_lr = + (diameter * rx + image_subpixel_mask) >> + image_subpixel_shift; + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg[0] = fg[1] = fg[2] = 0; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + rx_inv) >> + image_subpixel_shift; + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + fg[0] += *fg_ptr++ * weight; + fg[1] += *fg_ptr++ * weight; + fg[2] += *fg_ptr * weight; + total_weight += weight; + x_hr += rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + y_hr += ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg[0] /= total_weight; + fg[1] /= total_weight; + fg[2] /= total_weight; + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + + if(fg[order_type::R] > color_type::full_value()) fg[order_type::R] = color_type::full_value(); + if(fg[order_type::G] > color_type::full_value()) fg[order_type::G] = color_type::full_value(); + if(fg[order_type::B] > color_type::full_value()) fg[order_type::B] = color_type::full_value(); + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = color_type::full_value(); + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + +} + + +#endif + + + diff --git a/agg/include/agg_span_image_filter_rgba.h b/agg/include/agg_span_image_filter_rgba.h new file mode 100644 index 0000000..af7a1a2 --- /dev/null +++ b/agg/include/agg_span_image_filter_rgba.h @@ -0,0 +1,890 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// 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_IMAGE_FILTER_RGBA_INCLUDED +#define AGG_SPAN_IMAGE_FILTER_RGBA_INCLUDED + +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_span_image_filter.h" + + +namespace agg +{ + + //==============================================span_image_filter_rgba_nn + template + class span_image_filter_rgba_nn : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgba_nn() {} + span_image_filter_rgba_nn(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + do + { + base_type::interpolator().coordinates(&x, &y); + const value_type* fg_ptr = (const value_type*) + base_type::source().span(x >> image_subpixel_shift, + y >> image_subpixel_shift, + 1); + span->r = fg_ptr[order_type::R]; + span->g = fg_ptr[order_type::G]; + span->b = fg_ptr[order_type::B]; + span->a = fg_ptr[order_type::A]; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //=========================================span_image_filter_rgba_bilinear + template + class span_image_filter_rgba_bilinear : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgba_bilinear() {} + span_image_filter_rgba_bilinear(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[4]; + const value_type *fg_ptr; + + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + + fg[0] = + fg[1] = + fg[2] = + fg[3] = image_subpixel_scale * image_subpixel_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = x_hr * (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (image_subpixel_scale - x_hr) * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = x_hr * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + span->r = value_type(color_type::downshift(fg[order_type::R], image_subpixel_shift * 2)); + span->g = value_type(color_type::downshift(fg[order_type::G], image_subpixel_shift * 2)); + span->b = value_type(color_type::downshift(fg[order_type::B], image_subpixel_shift * 2)); + span->a = value_type(color_type::downshift(fg[order_type::A], image_subpixel_shift * 2)); + + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + //====================================span_image_filter_rgba_bilinear_clip + template + class span_image_filter_rgba_bilinear_clip : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgba_bilinear_clip() {} + span_image_filter_rgba_bilinear_clip(source_type& src, + const color_type& back_color, + interpolator_type& inter) : + base_type(src, inter, 0), + m_back_color(back_color) + {} + const color_type& background_color() const { return m_back_color; } + void background_color(const color_type& v) { m_back_color = v; } + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[4]; + value_type back_r = m_back_color.r; + value_type back_g = m_back_color.g; + value_type back_b = m_back_color.b; + value_type back_a = m_back_color.a; + + const value_type *fg_ptr; + int maxx = base_type::source().width() - 1; + int maxy = base_type::source().height() - 1; + + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + + if(x_lr >= 0 && y_lr >= 0 && + x_lr < maxx && y_lr < maxy) + { + fg[0] = fg[1] = fg[2] = fg[3] = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + + weight = x_hr * (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + + ++y_lr; + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + + weight = (image_subpixel_scale - x_hr) * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + + weight = x_hr * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + + fg[0] = color_type::downshift(fg[0], image_subpixel_shift * 2); + fg[1] = color_type::downshift(fg[1], image_subpixel_shift * 2); + fg[2] = color_type::downshift(fg[2], image_subpixel_shift * 2); + fg[3] = color_type::downshift(fg[3], image_subpixel_shift * 2); + } + else + { + if(x_lr < -1 || y_lr < -1 || + x_lr > maxx || y_lr > maxy) + { + fg[order_type::R] = back_r; + fg[order_type::G] = back_g; + fg[order_type::B] = back_b; + fg[order_type::A] = back_a; + } + else + { + fg[0] = fg[1] = fg[2] = fg[3] = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + fg[order_type::A] += back_a * weight; + } + + x_lr++; + + weight = x_hr * (image_subpixel_scale - y_hr); + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + fg[order_type::A] += back_a * weight; + } + + x_lr--; + y_lr++; + + weight = (image_subpixel_scale - x_hr) * y_hr; + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + fg[order_type::A] += back_a * weight; + } + + x_lr++; + + weight = x_hr * y_hr; + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + fg[order_type::A] += back_a * weight; + } + + fg[0] = color_type::downshift(fg[0], image_subpixel_shift * 2); + fg[1] = color_type::downshift(fg[1], image_subpixel_shift * 2); + fg[2] = color_type::downshift(fg[2], image_subpixel_shift * 2); + fg[3] = color_type::downshift(fg[3], image_subpixel_shift * 2); + } + } + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)fg[order_type::A]; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + private: + color_type m_back_color; + }; + + + //==============================================span_image_filter_rgba_2x2 + template + class span_image_filter_rgba_2x2 : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgba_2x2() {} + span_image_filter_rgba_2x2(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, &filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[4]; + + const value_type *fg_ptr; + const int16* weight_array = base_type::filter().weight_array() + + ((base_type::filter().diameter()/2 - 1) << + image_subpixel_shift); + + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + fg[0] = fg[1] = fg[2] = fg[3] = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg[0] = color_type::downshift(fg[0], image_filter_shift); + fg[1] = color_type::downshift(fg[1], image_filter_shift); + fg[2] = color_type::downshift(fg[2], image_filter_shift); + fg[3] = color_type::downshift(fg[3], image_filter_shift); + + if(fg[order_type::A] > color_type::full_value()) fg[order_type::A] = color_type::full_value(); + if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; + if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; + if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)fg[order_type::A]; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //==================================================span_image_filter_rgba + template + class span_image_filter_rgba : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgba() {} + span_image_filter_rgba(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, &filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[4]; + const value_type *fg_ptr; + + unsigned diameter = base_type::filter().diameter(); + int start = base_type::filter().start(); + const int16* weight_array = base_type::filter().weight_array(); + + int x_count; + int weight_y; + + do + { + base_type::interpolator().coordinates(&x, &y); + + x -= base_type::filter_dx_int(); + y -= base_type::filter_dy_int(); + + int x_hr = x; + int y_hr = y; + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + fg[0] = fg[1] = fg[2] = fg[3] = 0; + + int x_fract = x_hr & image_subpixel_mask; + unsigned y_count = diameter; + + y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); + fg_ptr = (const value_type*)base_type::source().span(x_lr + start, + y_lr + start, + diameter); + for(;;) + { + x_count = diameter; + weight_y = weight_array[y_hr]; + x_hr = image_subpixel_mask - x_fract; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + image_filter_shift; + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + if(--x_count == 0) break; + x_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + + if(--y_count == 0) break; + y_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg[0] = color_type::downshift(fg[0], image_filter_shift); + fg[1] = color_type::downshift(fg[1], image_filter_shift); + fg[2] = color_type::downshift(fg[2], image_filter_shift); + fg[3] = color_type::downshift(fg[3], image_filter_shift); + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + if(fg[3] < 0) fg[3] = 0; + + if(fg[order_type::A] > color_type::full_value()) fg[order_type::A] = color_type::full_value(); + if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; + if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; + if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)fg[order_type::A]; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //========================================span_image_resample_rgba_affine + template + class span_image_resample_rgba_affine : + public span_image_resample_affine + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef span_image_resample_affine base_type; + typedef typename base_type::interpolator_type interpolator_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_rgba_affine() {} + span_image_resample_rgba_affine(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[4]; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + int radius_x = (diameter * base_type::m_rx) >> 1; + int radius_y = (diameter * base_type::m_ry) >> 1; + int len_x_lr = + (diameter * base_type::m_rx + image_subpixel_mask) >> + image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + + do + { + base_type::interpolator().coordinates(&x, &y); + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg[0] = fg[1] = fg[2] = fg[3] = 0; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + base_type::m_ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + base_type::m_rx_inv) >> + image_subpixel_shift; + + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + + fg[0] += *fg_ptr++ * weight; + fg[1] += *fg_ptr++ * weight; + fg[2] += *fg_ptr++ * weight; + fg[3] += *fg_ptr++ * weight; + total_weight += weight; + x_hr += base_type::m_rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + y_hr += base_type::m_ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg[0] /= total_weight; + fg[1] /= total_weight; + fg[2] /= total_weight; + fg[3] /= total_weight; + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + if(fg[3] < 0) fg[3] = 0; + + if(fg[order_type::A] > color_type::full_value()) fg[order_type::A] = color_type::full_value(); + if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; + if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; + if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)fg[order_type::A]; + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + + + //==============================================span_image_resample_rgba + template + class span_image_resample_rgba : + public span_image_resample + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_resample base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_rgba() {} + span_image_resample_rgba(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg[4]; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + do + { + int rx; + int ry; + int rx_inv = image_subpixel_scale; + int ry_inv = image_subpixel_scale; + base_type::interpolator().coordinates(&x, &y); + base_type::interpolator().local_scale(&rx, &ry); + base_type::adjust_scale(&rx, &ry); + + rx_inv = image_subpixel_scale * image_subpixel_scale / rx; + ry_inv = image_subpixel_scale * image_subpixel_scale / ry; + + int radius_x = (diameter * rx) >> 1; + int radius_y = (diameter * ry) >> 1; + int len_x_lr = + (diameter * rx + image_subpixel_mask) >> + image_subpixel_shift; + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg[0] = fg[1] = fg[2] = fg[3] = 0; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + rx_inv) >> + image_subpixel_shift; + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + fg[0] += *fg_ptr++ * weight; + fg[1] += *fg_ptr++ * weight; + fg[2] += *fg_ptr++ * weight; + fg[3] += *fg_ptr++ * weight; + total_weight += weight; + x_hr += rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + y_hr += ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg[0] /= total_weight; + fg[1] /= total_weight; + fg[2] /= total_weight; + fg[3] /= total_weight; + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + if(fg[3] < 0) fg[3] = 0; + + if(fg[order_type::A] > color_type::full_value()) fg[order_type::A] = color_type::full_value(); + if(fg[order_type::R] > fg[order_type::R]) fg[order_type::R] = fg[order_type::R]; + if(fg[order_type::G] > fg[order_type::G]) fg[order_type::G] = fg[order_type::G]; + if(fg[order_type::B] > fg[order_type::B]) fg[order_type::B] = fg[order_type::B]; + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)fg[order_type::A]; + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + +} + + +#endif + + + diff --git a/agg2/include/agg_span_interpolator_adaptor.h b/agg/include/agg_span_interpolator_adaptor.h similarity index 81% rename from agg2/include/agg_span_interpolator_adaptor.h rename to agg/include/agg_span_interpolator_adaptor.h index b66e899..0fdfa77 100644 --- a/agg2/include/agg_span_interpolator_adaptor.h +++ b/agg/include/agg_span_interpolator_adaptor.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -32,16 +32,16 @@ namespace agg //-------------------------------------------------------------------- span_interpolator_adaptor() {} - span_interpolator_adaptor(const trans_type& trans, - const distortion_type& dist) : + span_interpolator_adaptor(trans_type& trans, + distortion_type& dist) : base_type(trans), m_distortion(&dist) { } //-------------------------------------------------------------------- - span_interpolator_adaptor(const trans_type& trans, - const distortion_type& dist, + span_interpolator_adaptor(trans_type& trans, + distortion_type& dist, double x, double y, unsigned len) : base_type(trans, x, y, len), m_distortion(&dist) @@ -49,13 +49,13 @@ namespace agg } //-------------------------------------------------------------------- - const distortion_type& distortion() const + distortion_type& distortion() const { return *m_distortion; } //-------------------------------------------------------------------- - void distortion(const distortion_type& dist) + void distortion(distortion_type& dist) { m_distortion = dist; } @@ -69,7 +69,7 @@ namespace agg private: //-------------------------------------------------------------------- - const distortion_type* m_distortion; + distortion_type* m_distortion; }; } diff --git a/agg/include/agg_span_interpolator_linear.h b/agg/include/agg_span_interpolator_linear.h new file mode 100644 index 0000000..ef10505 --- /dev/null +++ b/agg/include/agg_span_interpolator_linear.h @@ -0,0 +1,232 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED +#define AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED + +#include "agg_basics.h" +#include "agg_dda_line.h" +#include "agg_trans_affine.h" + +namespace agg +{ + + //================================================span_interpolator_linear + template + class span_interpolator_linear + { + public: + typedef Transformer trans_type; + + enum subpixel_scale_e + { + subpixel_shift = SubpixelShift, + subpixel_scale = 1 << subpixel_shift + }; + + //-------------------------------------------------------------------- + span_interpolator_linear() {} + span_interpolator_linear(trans_type& trans) : m_trans(&trans) {} + span_interpolator_linear(trans_type& trans, + double x, double y, unsigned len) : + m_trans(&trans) + { + begin(x, y, len); + } + + //---------------------------------------------------------------- + const trans_type& transformer() const { return *m_trans; } + void transformer(trans_type& trans) { m_trans = &trans; } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + double tx; + double ty; + + tx = x; + ty = y; + m_trans->transform(&tx, &ty); + int x1 = iround(tx * subpixel_scale); + int y1 = iround(ty * subpixel_scale); + + tx = x + len; + ty = y; + m_trans->transform(&tx, &ty); + int x2 = iround(tx * subpixel_scale); + int y2 = iround(ty * subpixel_scale); + + m_li_x = dda2_line_interpolator(x1, x2, len); + m_li_y = dda2_line_interpolator(y1, y2, len); + } + + //---------------------------------------------------------------- + void resynchronize(double xe, double ye, unsigned len) + { + m_trans->transform(&xe, &ye); + m_li_x = dda2_line_interpolator(m_li_x.y(), iround(xe * subpixel_scale), len); + m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ye * subpixel_scale), len); + } + + //---------------------------------------------------------------- + void operator++() + { + ++m_li_x; + ++m_li_y; + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + *x = m_li_x.y(); + *y = m_li_y.y(); + } + + private: + trans_type* m_trans; + dda2_line_interpolator m_li_x; + dda2_line_interpolator m_li_y; + }; + + + + + + + //=====================================span_interpolator_linear_subdiv + template + class span_interpolator_linear_subdiv + { + public: + typedef Transformer trans_type; + + enum subpixel_scale_e + { + subpixel_shift = SubpixelShift, + subpixel_scale = 1 << subpixel_shift + }; + + + //---------------------------------------------------------------- + span_interpolator_linear_subdiv() : + m_subdiv_shift(4), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1) {} + + span_interpolator_linear_subdiv(trans_type& trans, + unsigned subdiv_shift = 4) : + m_subdiv_shift(subdiv_shift), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1), + m_trans(&trans) {} + + span_interpolator_linear_subdiv(trans_type& trans, + double x, double y, unsigned len, + unsigned subdiv_shift = 4) : + m_subdiv_shift(subdiv_shift), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1), + m_trans(&trans) + { + begin(x, y, len); + } + + //---------------------------------------------------------------- + const trans_type& transformer() const { return *m_trans; } + void transformer(const trans_type& trans) { m_trans = &trans; } + + //---------------------------------------------------------------- + unsigned subdiv_shift() const { return m_subdiv_shift; } + void subdiv_shift(unsigned shift) + { + m_subdiv_shift = shift; + m_subdiv_size = 1 << m_subdiv_shift; + m_subdiv_mask = m_subdiv_size - 1; + } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + double tx; + double ty; + m_pos = 1; + m_src_x = iround(x * subpixel_scale) + subpixel_scale; + m_src_y = y; + m_len = len; + + if(len > m_subdiv_size) len = m_subdiv_size; + tx = x; + ty = y; + m_trans->transform(&tx, &ty); + int x1 = iround(tx * subpixel_scale); + int y1 = iround(ty * subpixel_scale); + + tx = x + len; + ty = y; + m_trans->transform(&tx, &ty); + + m_li_x = dda2_line_interpolator(x1, iround(tx * subpixel_scale), len); + m_li_y = dda2_line_interpolator(y1, iround(ty * subpixel_scale), len); + } + + //---------------------------------------------------------------- + void operator++() + { + ++m_li_x; + ++m_li_y; + if(m_pos >= m_subdiv_size) + { + unsigned len = m_len; + if(len > m_subdiv_size) len = m_subdiv_size; + double tx = double(m_src_x) / double(subpixel_scale) + len; + double ty = m_src_y; + m_trans->transform(&tx, &ty); + m_li_x = dda2_line_interpolator(m_li_x.y(), iround(tx * subpixel_scale), len); + m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ty * subpixel_scale), len); + m_pos = 0; + } + m_src_x += subpixel_scale; + ++m_pos; + --m_len; + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + *x = m_li_x.y(); + *y = m_li_y.y(); + } + + private: + unsigned m_subdiv_shift; + unsigned m_subdiv_size; + unsigned m_subdiv_mask; + trans_type* m_trans; + dda2_line_interpolator m_li_x; + dda2_line_interpolator m_li_y; + int m_src_x; + double m_src_y; + unsigned m_pos; + unsigned m_len; + }; + + +} + + + +#endif + + diff --git a/agg/include/agg_span_interpolator_persp.h b/agg/include/agg_span_interpolator_persp.h new file mode 100644 index 0000000..15d33ba --- /dev/null +++ b/agg/include/agg_span_interpolator_persp.h @@ -0,0 +1,463 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +#ifndef AGG_SPAN_INTERPOLATOR_PERSP_INCLUDED +#define AGG_SPAN_INTERPOLATOR_PERSP_INCLUDED + +#include +#include "agg_trans_perspective.h" +#include "agg_dda_line.h" + +namespace agg +{ + + + + //===========================================span_interpolator_persp_exact + template + class span_interpolator_persp_exact + { + public: + typedef trans_perspective trans_type; + typedef trans_perspective::iterator_x iterator_type; + enum subpixel_scale_e + { + subpixel_shift = SubpixelShift, + subpixel_scale = 1 << subpixel_shift + }; + + //-------------------------------------------------------------------- + span_interpolator_persp_exact() {} + + //-------------------------------------------------------------------- + // Arbitrary quadrangle transformations + span_interpolator_persp_exact(const double* src, const double* dst) + { + quad_to_quad(src, dst); + } + + //-------------------------------------------------------------------- + // Direct transformations + span_interpolator_persp_exact(double x1, double y1, + double x2, double y2, + const double* quad) + { + rect_to_quad(x1, y1, x2, y2, quad); + } + + //-------------------------------------------------------------------- + // Reverse transformations + span_interpolator_persp_exact(const double* quad, + double x1, double y1, + double x2, double y2) + { + quad_to_rect(quad, x1, y1, x2, y2); + } + + //-------------------------------------------------------------------- + // Set the transformations using two arbitrary quadrangles. + void quad_to_quad(const double* src, const double* dst) + { + m_trans_dir.quad_to_quad(src, dst); + m_trans_inv.quad_to_quad(dst, src); + } + + //-------------------------------------------------------------------- + // Set the direct transformations, i.e., rectangle -> quadrangle + void rect_to_quad(double x1, double y1, double x2, double y2, + const double* quad) + { + double src[8]; + src[0] = src[6] = x1; + src[2] = src[4] = x2; + src[1] = src[3] = y1; + src[5] = src[7] = y2; + quad_to_quad(src, quad); + } + + + //-------------------------------------------------------------------- + // Set the reverse transformations, i.e., quadrangle -> rectangle + void quad_to_rect(const double* quad, + double x1, double y1, double x2, double y2) + { + double dst[8]; + dst[0] = dst[6] = x1; + dst[2] = dst[4] = x2; + dst[1] = dst[3] = y1; + dst[5] = dst[7] = y2; + quad_to_quad(quad, dst); + } + + //-------------------------------------------------------------------- + // Check if the equations were solved successfully + bool is_valid() const { return m_trans_dir.is_valid(); } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + m_iterator = m_trans_dir.begin(x, y, 1.0); + double xt = m_iterator.x; + double yt = m_iterator.y; + + double dx; + double dy; + const double delta = 1/double(subpixel_scale); + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sx1 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift; + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sy1 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + x += len; + xt = x; + yt = y; + m_trans_dir.transform(&xt, &yt); + + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sx2 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift; + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sy2 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + m_scale_x = dda2_line_interpolator(sx1, sx2, len); + m_scale_y = dda2_line_interpolator(sy1, sy2, len); + } + + + //---------------------------------------------------------------- + void resynchronize(double xe, double ye, unsigned len) + { + // Assume x1,y1 are equal to the ones at the previous end point + int sx1 = m_scale_x.y(); + int sy1 = m_scale_y.y(); + + // Calculate transformed coordinates at x2,y2 + double xt = xe; + double yt = ye; + m_trans_dir.transform(&xt, &yt); + + const double delta = 1/double(subpixel_scale); + double dx; + double dy; + + // Calculate scale by X at x2,y2 + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= xe; + dy -= ye; + int sx2 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Calculate scale by Y at x2,y2 + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= xe; + dy -= ye; + int sy2 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Initialize the interpolators + m_scale_x = dda2_line_interpolator(sx1, sx2, len); + m_scale_y = dda2_line_interpolator(sy1, sy2, len); + } + + + + //---------------------------------------------------------------- + void operator++() + { + ++m_iterator; + ++m_scale_x; + ++m_scale_y; + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + *x = iround(m_iterator.x * subpixel_scale); + *y = iround(m_iterator.y * subpixel_scale); + } + + //---------------------------------------------------------------- + void local_scale(int* x, int* y) + { + *x = m_scale_x.y(); + *y = m_scale_y.y(); + } + + //---------------------------------------------------------------- + void transform(double* x, double* y) const + { + m_trans_dir.transform(x, y); + } + + private: + trans_type m_trans_dir; + trans_type m_trans_inv; + iterator_type m_iterator; + dda2_line_interpolator m_scale_x; + dda2_line_interpolator m_scale_y; + }; + + + + + + + + + + + + //============================================span_interpolator_persp_lerp + template + class span_interpolator_persp_lerp + { + public: + typedef trans_perspective trans_type; + enum subpixel_scale_e + { + subpixel_shift = SubpixelShift, + subpixel_scale = 1 << subpixel_shift + }; + + //-------------------------------------------------------------------- + span_interpolator_persp_lerp() {} + + //-------------------------------------------------------------------- + // Arbitrary quadrangle transformations + span_interpolator_persp_lerp(const double* src, const double* dst) + { + quad_to_quad(src, dst); + } + + //-------------------------------------------------------------------- + // Direct transformations + span_interpolator_persp_lerp(double x1, double y1, + double x2, double y2, + const double* quad) + { + rect_to_quad(x1, y1, x2, y2, quad); + } + + //-------------------------------------------------------------------- + // Reverse transformations + span_interpolator_persp_lerp(const double* quad, + double x1, double y1, + double x2, double y2) + { + quad_to_rect(quad, x1, y1, x2, y2); + } + + //-------------------------------------------------------------------- + // Set the transformations using two arbitrary quadrangles. + void quad_to_quad(const double* src, const double* dst) + { + m_trans_dir.quad_to_quad(src, dst); + m_trans_inv.quad_to_quad(dst, src); + } + + //-------------------------------------------------------------------- + // Set the direct transformations, i.e., rectangle -> quadrangle + void rect_to_quad(double x1, double y1, double x2, double y2, + const double* quad) + { + double src[8]; + src[0] = src[6] = x1; + src[2] = src[4] = x2; + src[1] = src[3] = y1; + src[5] = src[7] = y2; + quad_to_quad(src, quad); + } + + + //-------------------------------------------------------------------- + // Set the reverse transformations, i.e., quadrangle -> rectangle + void quad_to_rect(const double* quad, + double x1, double y1, double x2, double y2) + { + double dst[8]; + dst[0] = dst[6] = x1; + dst[2] = dst[4] = x2; + dst[1] = dst[3] = y1; + dst[5] = dst[7] = y2; + quad_to_quad(quad, dst); + } + + //-------------------------------------------------------------------- + // Check if the equations were solved successfully + bool is_valid() const { return m_trans_dir.is_valid(); } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + // Calculate transformed coordinates at x1,y1 + double xt = x; + double yt = y; + m_trans_dir.transform(&xt, &yt); + int x1 = iround(xt * subpixel_scale); + int y1 = iround(yt * subpixel_scale); + + double dx; + double dy; + const double delta = 1/double(subpixel_scale); + + // Calculate scale by X at x1,y1 + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sx1 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Calculate scale by Y at x1,y1 + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sy1 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Calculate transformed coordinates at x2,y2 + x += len; + xt = x; + yt = y; + m_trans_dir.transform(&xt, &yt); + int x2 = iround(xt * subpixel_scale); + int y2 = iround(yt * subpixel_scale); + + // Calculate scale by X at x2,y2 + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sx2 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Calculate scale by Y at x2,y2 + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sy2 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Initialize the interpolators + m_coord_x = dda2_line_interpolator(x1, x2, len); + m_coord_y = dda2_line_interpolator(y1, y2, len); + m_scale_x = dda2_line_interpolator(sx1, sx2, len); + m_scale_y = dda2_line_interpolator(sy1, sy2, len); + } + + + //---------------------------------------------------------------- + void resynchronize(double xe, double ye, unsigned len) + { + // Assume x1,y1 are equal to the ones at the previous end point + int x1 = m_coord_x.y(); + int y1 = m_coord_y.y(); + int sx1 = m_scale_x.y(); + int sy1 = m_scale_y.y(); + + // Calculate transformed coordinates at x2,y2 + double xt = xe; + double yt = ye; + m_trans_dir.transform(&xt, &yt); + int x2 = iround(xt * subpixel_scale); + int y2 = iround(yt * subpixel_scale); + + const double delta = 1/double(subpixel_scale); + double dx; + double dy; + + // Calculate scale by X at x2,y2 + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= xe; + dy -= ye; + int sx2 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Calculate scale by Y at x2,y2 + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= xe; + dy -= ye; + int sy2 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Initialize the interpolators + m_coord_x = dda2_line_interpolator(x1, x2, len); + m_coord_y = dda2_line_interpolator(y1, y2, len); + m_scale_x = dda2_line_interpolator(sx1, sx2, len); + m_scale_y = dda2_line_interpolator(sy1, sy2, len); + } + + + //---------------------------------------------------------------- + void operator++() + { + ++m_coord_x; + ++m_coord_y; + ++m_scale_x; + ++m_scale_y; + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + *x = m_coord_x.y(); + *y = m_coord_y.y(); + } + + //---------------------------------------------------------------- + void local_scale(int* x, int* y) + { + *x = m_scale_x.y(); + *y = m_scale_y.y(); + } + + //---------------------------------------------------------------- + void transform(double* x, double* y) const + { + m_trans_dir.transform(x, y); + } + + private: + trans_type m_trans_dir; + trans_type m_trans_inv; + dda2_line_interpolator m_coord_x; + dda2_line_interpolator m_coord_y; + dda2_line_interpolator m_scale_x; + dda2_line_interpolator m_scale_y; + }; + +} + +#endif diff --git a/agg2/include/agg_span_interpolator_trans.h b/agg/include/agg_span_interpolator_trans.h similarity index 80% rename from agg2/include/agg_span_interpolator_trans.h rename to agg/include/agg_span_interpolator_trans.h index 717cc9f..32bc678 100644 --- a/agg2/include/agg_span_interpolator_trans.h +++ b/agg/include/agg_span_interpolator_trans.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -31,17 +31,16 @@ namespace agg { public: typedef Transformer trans_type; - - enum + enum subpixel_scale_e { subpixel_shift = SubpixelShift, - subpixel_size = 1 << subpixel_shift + subpixel_scale = 1 << subpixel_shift }; //-------------------------------------------------------------------- span_interpolator_trans() {} - span_interpolator_trans(const trans_type& trans) : m_trans(&trans) {} - span_interpolator_trans(const trans_type& trans, + span_interpolator_trans(trans_type& trans) : m_trans(&trans) {} + span_interpolator_trans(trans_type& trans, double x, double y, unsigned) : m_trans(&trans) { @@ -57,14 +56,20 @@ namespace agg { m_x = x; m_y = y; - transform(); + m_trans->transform(&x, &y); + m_ix = iround(x * subpixel_scale); + m_iy = iround(y * subpixel_scale); } //---------------------------------------------------------------- void operator++() { m_x += 1.0; - transform(); + double x = m_x; + double y = m_y; + m_trans->transform(&x, &y); + m_ix = iround(x * subpixel_scale); + m_iy = iround(y * subpixel_scale); } //---------------------------------------------------------------- @@ -75,17 +80,7 @@ namespace agg } private: - //---------------------------------------------------------------- - void transform() - { - double x = m_x; - double y = m_y; - m_trans->transform(&x, &y); - m_ix = int(x * subpixel_size); - m_iy = int(y * subpixel_size); - } - - const trans_type* m_trans; + trans_type* m_trans; double m_x; double m_y; int m_ix; diff --git a/agg/include/agg_span_pattern_gray.h b/agg/include/agg_span_pattern_gray.h new file mode 100644 index 0000000..ae1a49f --- /dev/null +++ b/agg/include/agg_span_pattern_gray.h @@ -0,0 +1,93 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// 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_PATTERN_GRAY_INCLUDED +#define AGG_SPAN_PATTERN_GRAY_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //=======================================================span_pattern_gray + template class span_pattern_gray + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + + //-------------------------------------------------------------------- + span_pattern_gray() {} + span_pattern_gray(source_type& src, + unsigned offset_x, unsigned offset_y) : + m_src(&src), + m_offset_x(offset_x), + m_offset_y(offset_y), + m_alpha(color_type::base_mask) + {} + + //-------------------------------------------------------------------- + void attach(source_type& v) { m_src = &v; } + source_type& source() { return *m_src; } + const source_type& source() const { return *m_src; } + + //-------------------------------------------------------------------- + void offset_x(unsigned v) { m_offset_x = v; } + void offset_y(unsigned v) { m_offset_y = v; } + unsigned offset_x() const { return m_offset_x; } + unsigned offset_y() const { return m_offset_y; } + void alpha(value_type v) { m_alpha = v; } + value_type alpha() const { return m_alpha; } + + //-------------------------------------------------------------------- + void prepare() {} + void generate(color_type* span, int x, int y, unsigned len) + { + x += m_offset_x; + y += m_offset_y; + const value_type* p = (const value_type*)m_src->span(x, y, len); + do + { + span->v = *p; + span->a = m_alpha; + p = m_src->next_x(); + ++span; + } + while(--len); + } + + private: + source_type* m_src; + unsigned m_offset_x; + unsigned m_offset_y; + value_type m_alpha; + + }; + +} + +#endif + diff --git a/agg/include/agg_span_pattern_rgb.h b/agg/include/agg_span_pattern_rgb.h new file mode 100644 index 0000000..4850508 --- /dev/null +++ b/agg/include/agg_span_pattern_rgb.h @@ -0,0 +1,96 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// 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_PATTERN_RGB_INCLUDED +#define AGG_SPAN_PATTERN_RGB_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //========================================================span_pattern_rgb + template class span_pattern_rgb + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + + //-------------------------------------------------------------------- + span_pattern_rgb() {} + span_pattern_rgb(source_type& src, + unsigned offset_x, unsigned offset_y) : + m_src(&src), + m_offset_x(offset_x), + m_offset_y(offset_y), + m_alpha(color_type::base_mask) + {} + + //-------------------------------------------------------------------- + void attach(source_type& v) { m_src = &v; } + source_type& source() { return *m_src; } + const source_type& source() const { return *m_src; } + + //-------------------------------------------------------------------- + void offset_x(unsigned v) { m_offset_x = v; } + void offset_y(unsigned v) { m_offset_y = v; } + unsigned offset_x() const { return m_offset_x; } + unsigned offset_y() const { return m_offset_y; } + void alpha(value_type v) { m_alpha = v; } + value_type alpha() const { return m_alpha; } + + //-------------------------------------------------------------------- + void prepare() {} + void generate(color_type* span, int x, int y, unsigned len) + { + x += m_offset_x; + y += m_offset_y; + const value_type* p = (const value_type*)m_src->span(x, y, len); + do + { + span->r = p[order_type::R]; + span->g = p[order_type::G]; + span->b = p[order_type::B]; + span->a = m_alpha; + p = m_src->next_x(); + ++span; + } + while(--len); + } + + private: + source_type* m_src; + unsigned m_offset_x; + unsigned m_offset_y; + value_type m_alpha; + + }; + +} + +#endif + diff --git a/agg/include/agg_span_pattern_rgba.h b/agg/include/agg_span_pattern_rgba.h new file mode 100644 index 0000000..d47d2a6 --- /dev/null +++ b/agg/include/agg_span_pattern_rgba.h @@ -0,0 +1,94 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// 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_PATTERN_RGBA_INCLUDED +#define AGG_SPAN_PATTERN_RGBA_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //======================================================span_pattern_rgba + template class span_pattern_rgba + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + + //-------------------------------------------------------------------- + span_pattern_rgba() {} + span_pattern_rgba(source_type& src, + unsigned offset_x, unsigned offset_y) : + m_src(&src), + m_offset_x(offset_x), + m_offset_y(offset_y) + {} + + //-------------------------------------------------------------------- + void attach(source_type& v) { m_src = &v; } + source_type& source() { return *m_src; } + const source_type& source() const { return *m_src; } + + //-------------------------------------------------------------------- + void offset_x(unsigned v) { m_offset_x = v; } + void offset_y(unsigned v) { m_offset_y = v; } + unsigned offset_x() const { return m_offset_x; } + unsigned offset_y() const { return m_offset_y; } + void alpha(value_type) {} + value_type alpha() const { return 0; } + + //-------------------------------------------------------------------- + void prepare() {} + void generate(color_type* span, int x, int y, unsigned len) + { + x += m_offset_x; + y += m_offset_y; + const value_type* p = (const value_type*)m_src->span(x, y, len); + do + { + span->r = p[order_type::R]; + span->g = p[order_type::G]; + span->b = p[order_type::B]; + span->a = p[order_type::A]; + p = (const value_type*)m_src->next_x(); + ++span; + } + while(--len); + } + + private: + source_type* m_src; + unsigned m_offset_x; + unsigned m_offset_y; + + }; + +} + +#endif + diff --git a/agg2/include/agg_span_solid.h b/agg/include/agg_span_solid.h similarity index 66% rename from agg2/include/agg_span_solid.h rename to agg/include/agg_span_solid.h index fe84bd7..ee46df9 100644 --- a/agg2/include/agg_span_solid.h +++ b/agg/include/agg_span_solid.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -21,36 +21,26 @@ #define AGG_SPAN_SOLID_INCLUDED #include "agg_basics.h" -#include "agg_span_generator.h" namespace agg { //--------------------------------------------------------------span_solid - template > - class span_solid : public span_generator + template class span_solid { public: - typedef Allocator alloc_type; typedef ColorT color_type; - typedef span_generator base_type; - - //-------------------------------------------------------------------- - span_solid(alloc_type& alloc) : base_type(alloc) {} //-------------------------------------------------------------------- void color(const color_type& c) { m_color = c; } const color_type& color() const { return m_color; } //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void prepare() {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) { - color_type* span = base_type::allocator().span(); - do - { - *span++ = m_color; - } - while(--len); - return base_type::allocator().span(); + do { *span++ = m_color; } while(--len); } private: diff --git a/agg/include/agg_span_subdiv_adaptor.h b/agg/include/agg_span_subdiv_adaptor.h new file mode 100644 index 0000000..b5b855e --- /dev/null +++ b/agg/include/agg_span_subdiv_adaptor.h @@ -0,0 +1,141 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +#ifndef AGG_SPAN_SUBDIV_ADAPTOR_INCLUDED +#define AGG_SPAN_SUBDIV_ADAPTOR_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //=================================================span_subdiv_adaptor + template + class span_subdiv_adaptor + { + public: + typedef Interpolator interpolator_type; + typedef typename interpolator_type::trans_type trans_type; + + enum sublixel_scale_e + { + subpixel_shift = SubpixelShift, + subpixel_scale = 1 << subpixel_shift + }; + + + //---------------------------------------------------------------- + span_subdiv_adaptor() : + m_subdiv_shift(4), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1) {} + + span_subdiv_adaptor(interpolator_type& interpolator, + unsigned subdiv_shift = 4) : + m_subdiv_shift(subdiv_shift), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1), + m_interpolator(&interpolator) {} + + span_subdiv_adaptor(interpolator_type& interpolator, + double x, double y, unsigned len, + unsigned subdiv_shift = 4) : + m_subdiv_shift(subdiv_shift), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1), + m_interpolator(&interpolator) + { + begin(x, y, len); + } + + + //---------------------------------------------------------------- + const interpolator_type& interpolator() const { return *m_interpolator; } + void interpolator(interpolator_type& intr) { m_interpolator = &intr; } + + //---------------------------------------------------------------- + const trans_type& transformer() const + { + return *m_interpolator->transformer(); + } + void transformer(const trans_type& trans) + { + m_interpolator->transformer(trans); + } + + //---------------------------------------------------------------- + unsigned subdiv_shift() const { return m_subdiv_shift; } + void subdiv_shift(unsigned shift) + { + m_subdiv_shift = shift; + m_subdiv_size = 1 << m_subdiv_shift; + m_subdiv_mask = m_subdiv_size - 1; + } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + m_pos = 1; + m_src_x = iround(x * subpixel_scale) + subpixel_scale; + m_src_y = y; + m_len = len; + if(len > m_subdiv_size) len = m_subdiv_size; + m_interpolator->begin(x, y, len); + } + + //---------------------------------------------------------------- + void operator++() + { + ++(*m_interpolator); + if(m_pos >= m_subdiv_size) + { + unsigned len = m_len; + if(len > m_subdiv_size) len = m_subdiv_size; + m_interpolator->resynchronize(double(m_src_x) / double(subpixel_scale) + len, + m_src_y, + len); + m_pos = 0; + } + m_src_x += subpixel_scale; + ++m_pos; + --m_len; + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + m_interpolator->coordinates(x, y); + } + + //---------------------------------------------------------------- + void local_scale(int* x, int* y) const + { + m_interpolator->local_scale(x, y); + } + + + private: + unsigned m_subdiv_shift; + unsigned m_subdiv_size; + unsigned m_subdiv_mask; + interpolator_type* m_interpolator; + int m_src_x; + double m_src_y; + unsigned m_pos; + unsigned m_len; + }; + +} + +#endif diff --git a/agg2/include/agg_trans_affine.h b/agg/include/agg_trans_affine.h similarity index 50% rename from agg2/include/agg_trans_affine.h rename to agg/include/agg_trans_affine.h index 5965009..90e464b 100644 --- a/agg2/include/agg_trans_affine.h +++ b/agg/include/agg_trans_affine.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -19,12 +19,12 @@ #ifndef AGG_TRANS_AFFINE_INCLUDED #define AGG_TRANS_AFFINE_INCLUDED -#include +#include #include "agg_basics.h" namespace agg { - const double affine_epsilon = 1e-14; // About of precision of doubles + const double affine_epsilon = 1e-14; //============================================================trans_affine // @@ -84,48 +84,58 @@ namespace agg // m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0); // rotate // m *= agg::trans_affine_translation(100.0, 100.0); // move back to (100,100) //---------------------------------------------------------------------- - class trans_affine + struct trans_affine { - public: + double sx, shy, shx, sy, tx, ty; + //------------------------------------------ Construction - // Construct an identity matrix - it does not transform anything + // Identity matrix trans_affine() : - m0(1.0), m1(0.0), m2(0.0), m3(1.0), m4(0.0), m5(0.0) + sx(1.0), shy(0.0), shx(0.0), sy(1.0), tx(0.0), ty(0.0) {} - // Construct a custom matrix. Usually used in derived classes - trans_affine(double v0, double v1, double v2, double v3, double v4, double v5) : - m0(v0), m1(v1), m2(v2), m3(v3), m4(v4), m5(v5) + // Custom matrix. Usually used in derived classes + trans_affine(double v0, double v1, double v2, + double v3, double v4, double v5) : + sx(v0), shy(v1), shx(v2), sy(v3), tx(v4), ty(v5) {} - // Construct a matrix to transform a parallelogram to another one. - trans_affine(const double* rect, const double* parl) - { - parl_to_parl(rect, parl); - } + // Custom matrix from m[6] + explicit trans_affine(const double* m) : + sx(m[0]), shy(m[1]), shx(m[2]), sy(m[3]), tx(m[4]), ty(m[5]) + {} - // Construct a matrix to transform a rectangle to a parallelogram. + // Rectangle to a parallelogram. trans_affine(double x1, double y1, double x2, double y2, const double* parl) { rect_to_parl(x1, y1, x2, y2, parl); } - // Construct a matrix to transform a parallelogram to a rectangle. + // Parallelogram to a rectangle. trans_affine(const double* parl, double x1, double y1, double x2, double y2) { parl_to_rect(parl, x1, y1, x2, y2); } + // Arbitrary parallelogram transformation. + trans_affine(const double* src, const double* dst) + { + parl_to_parl(src, dst); + } //---------------------------------- Parellelogram transformations - // Calculate a matrix to transform a parallelogram to another one. - // src and dst are pointers to arrays of three points - // (double[6], x,y,...) that identify three corners of the - // parallelograms assuming implicit fourth points. - // There are also transformations rectangtle to parallelogram and - // parellelogram to rectangle + // transform a parallelogram to another one. Src and dst are + // pointers to arrays of three points (double[6], x1,y1,...) that + // identify three corners of the parallelograms assuming implicit + // fourth point. The arguments are arrays of double[6] mapped + // to x1,y1, x2,y2, x3,y3 where the coordinates are: + // *-----------------* + // / (x3,y3)/ + // / / + // /(x1,y1) (x2,y2)/ + // *-----------------* const trans_affine& parl_to_parl(const double* src, const double* dst); @@ -139,15 +149,27 @@ namespace agg //------------------------------------------ Operations - // Reset - actually load an identity matrix + // Reset - load an identity matrix const trans_affine& reset(); + // Direct transformations operations + const trans_affine& translate(double x, double y); + const trans_affine& rotate(double a); + const trans_affine& scale(double s); + const trans_affine& scale(double x, double y); + // Multiply matrix to another one const trans_affine& multiply(const trans_affine& m); // Multiply "m" to "this" and assign the result to "this" const trans_affine& premultiply(const trans_affine& m); + // Multiply matrix to inverse of another one + const trans_affine& multiply_inv(const trans_affine& m); + + // Multiply inverse of "m" to "this" and assign the result to "this" + const trans_affine& premultiply_inv(const trans_affine& m); + // Invert matrix. Do not try to invert degenerate matrices, // there's no check for validity. If you set scale to 0 and // then try to invert matrix, expect unpredictable result. @@ -163,31 +185,44 @@ namespace agg // Store matrix to an array [6] of double void store_to(double* m) const { - *m++ = m0; *m++ = m1; *m++ = m2; *m++ = m3; *m++ = m4; *m++ = m5; + *m++ = sx; *m++ = shy; *m++ = shx; *m++ = sy; *m++ = tx; *m++ = ty; } // Load matrix from an array [6] of double const trans_affine& load_from(const double* m) { - m0 = *m++; m1 = *m++; m2 = *m++; m3 = *m++; m4 = *m++; m5 = *m++; + sx = *m++; shy = *m++; shx = *m++; sy = *m++; tx = *m++; ty = *m++; return *this; } //------------------------------------------- Operators - // Multiply current matrix to another one + // Multiply the matrix by another one const trans_affine& operator *= (const trans_affine& m) { return multiply(m); } - // Multiply current matrix to another one and return + // Multiply the matrix by inverse of another one + const trans_affine& operator /= (const trans_affine& m) + { + return multiply_inv(m); + } + + // Multiply the matrix by another one and return // the result in a separete matrix. - trans_affine operator * (const trans_affine& m) + trans_affine operator * (const trans_affine& m) const { return trans_affine(*this).multiply(m); } + // Multiply the matrix by inverse of another one + // and return the result in a separete matrix. + trans_affine operator / (const trans_affine& m) const + { + return trans_affine(*this).multiply_inv(m); + } + // Calculate and return the inverse matrix trans_affine operator ~ () const { @@ -208,19 +243,28 @@ namespace agg } //-------------------------------------------- Transformations - // Direct transformation x and y + // Direct transformation of x and y void transform(double* x, double* y) const; - // Inverse transformation x and y. It works slower than the - // direct transformation, so if the performance is critical - // it's better to invert() the matrix and then use transform() + // Direct transformation of x and y, 2x2 matrix only, no translation + void transform_2x2(double* x, double* y) const; + + // Inverse transformation of x and y. It works slower than the + // direct transformation. For massive operations it's better to + // invert() the matrix and then use direct transformations. void inverse_transform(double* x, double* y) const; //-------------------------------------------- Auxiliary // Calculate the determinant of matrix double determinant() const { - return 1.0 / (m0 * m3 - m1 * m2); + return sx * sy - shy * shx; + } + + // Calculate the reciprocal of the determinant + double determinant_reciprocal() const + { + return 1.0 / (sx * sy - shy * shx); } // Get the average scale (by X and Y). @@ -228,52 +272,108 @@ namespace agg // decomposinting curves into line segments. double scale() const; + // Check to see if the matrix is not degenerate + bool is_valid(double epsilon = affine_epsilon) const; + // Check to see if it's an identity matrix bool is_identity(double epsilon = affine_epsilon) const; // Check to see if two matrices are equal bool is_equal(const trans_affine& m, double epsilon = affine_epsilon) const; - // Determine the major parameters. Use carefully considering degenerate matrices + // Determine the major parameters. Use with caution considering + // possible degenerate cases. double rotation() const; void translation(double* dx, double* dy) const; - void scaling(double* sx, double* sy) const; - - private: - double m0; - double m1; - double m2; - double m3; - double m4; - double m5; + void scaling(double* x, double* y) const; + void scaling_abs(double* x, double* y) const; }; //------------------------------------------------------------------------ inline void trans_affine::transform(double* x, double* y) const { - register double tx = *x; - *x = tx * m0 + *y * m2 + m4; - *y = tx * m1 + *y * m3 + m5; + double tmp = *x; + *x = tmp * sx + *y * shx + tx; + *y = tmp * shy + *y * sy + ty; + } + + //------------------------------------------------------------------------ + inline void trans_affine::transform_2x2(double* x, double* y) const + { + double tmp = *x; + *x = tmp * sx + *y * shx; + *y = tmp * shy + *y * sy; } //------------------------------------------------------------------------ inline void trans_affine::inverse_transform(double* x, double* y) const { - register double d = determinant(); - register double a = (*x - m4) * d; - register double b = (*y - m5) * d; - *x = a * m3 - b * m2; - *y = b * m0 - a * m1; + double d = determinant_reciprocal(); + double a = (*x - tx) * d; + double b = (*y - ty) * d; + *x = a * sy - b * shx; + *y = b * sx - a * shy; } //------------------------------------------------------------------------ inline double trans_affine::scale() const { - double x = 0.707106781 * m0 + 0.707106781 * m2; - double y = 0.707106781 * m1 + 0.707106781 * m3; - return sqrt(x*x + y*y); + double x = 0.707106781 * sx + 0.707106781 * shx; + double y = 0.707106781 * shy + 0.707106781 * sy; + return std::sqrt(x*x + y*y); + } + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::translate(double x, double y) + { + tx += x; + ty += y; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::rotate(double a) + { + double ca = std::cos(a); + double sa = std::sin(a); + double t0 = sx * ca - shy * sa; + double t2 = shx * ca - sy * sa; + double t4 = tx * ca - ty * sa; + shy = sx * sa + shy * ca; + sy = shx * sa + sy * ca; + ty = tx * sa + ty * ca; + sx = t0; + shx = t2; + tx = t4; + return *this; } + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::scale(double x, double y) + { + double mm0 = x; // Possible hint for the optimizer + double mm3 = y; + sx *= mm0; + shx *= mm0; + tx *= mm0; + shy *= mm3; + sy *= mm3; + ty *= mm3; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::scale(double s) + { + double m = s; // Possible hint for the optimizer + sx *= m; + shx *= m; + tx *= m; + shy *= m; + sy *= m; + ty *= m; + return *this; + } //------------------------------------------------------------------------ inline const trans_affine& trans_affine::premultiply(const trans_affine& m) @@ -282,6 +382,31 @@ namespace agg return *this = t.multiply(*this); } + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::multiply_inv(const trans_affine& m) + { + trans_affine t = m; + t.invert(); + return multiply(t); + } + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::premultiply_inv(const trans_affine& m) + { + trans_affine t = m; + t.invert(); + return *this = t.multiply(*this); + } + + //------------------------------------------------------------------------ + inline void trans_affine::scaling_abs(double* x, double* y) const + { + // Used to calculate scaling coefficients in image resampling. + // When there is considerable shear this method gives us much + // better estimation than just sx, sy. + *x = std::sqrt(sx * sx + shx * shx); + *y = std::sqrt(shy * shy + sy * sy); + } //====================================================trans_affine_rotation // Rotation matrix. sin() and cos() are calculated twice for the same angle. @@ -292,17 +417,17 @@ namespace agg { public: trans_affine_rotation(double a) : - trans_affine(cos(a), sin(a), -sin(a), cos(a), 0.0, 0.0) + trans_affine(std::cos(a), std::sin(a), -std::sin(a), std::cos(a), 0.0, 0.0) {} }; //====================================================trans_affine_scaling - // Scaling matrix. sx, sy - scale coefficients by X and Y respectively + // Scaling matrix. x, y - scale coefficients by X and Y respectively class trans_affine_scaling : public trans_affine { public: - trans_affine_scaling(double sx, double sy) : - trans_affine(sx, 0.0, 0.0, sy, 0.0, 0.0) + trans_affine_scaling(double x, double y) : + trans_affine(x, 0.0, 0.0, y, 0.0, 0.0) {} trans_affine_scaling(double s) : @@ -315,8 +440,8 @@ namespace agg class trans_affine_translation : public trans_affine { public: - trans_affine_translation(double tx, double ty) : - trans_affine(1.0, 0.0, 0.0, 1.0, tx, ty) + trans_affine_translation(double x, double y) : + trans_affine(1.0, 0.0, 0.0, 1.0, x, y) {} }; @@ -325,12 +450,66 @@ namespace agg class trans_affine_skewing : public trans_affine { public: - trans_affine_skewing(double sx, double sy) : - trans_affine(1.0, tan(sy), tan(sx), 1.0, 0.0, 0.0) + trans_affine_skewing(double x, double y) : + trans_affine(1.0, std::tan(y), std::tan(x), 1.0, 0.0, 0.0) + {} + }; + + + //===============================================trans_affine_line_segment + // Rotate, Scale and Translate, associating 0...dist with line segment + // x1,y1,x2,y2 + class trans_affine_line_segment : public trans_affine + { + public: + trans_affine_line_segment(double x1, double y1, double x2, double y2, + double dist) + { + double dx = x2 - x1; + double dy = y2 - y1; + if(dist > 0.0) + { + multiply(trans_affine_scaling(std::sqrt(dx * dx + dy * dy) / dist)); + } + multiply(trans_affine_rotation(std::atan2(dy, dx))); + multiply(trans_affine_translation(x1, y1)); + } + }; + + + //============================================trans_affine_reflection_unit + // Reflection matrix. Reflect coordinates across the line through + // the origin containing the unit vector (ux, uy). + // Contributed by John Horigan + class trans_affine_reflection_unit : public trans_affine + { + public: + trans_affine_reflection_unit(double ux, double uy) : + trans_affine(2.0 * ux * ux - 1.0, + 2.0 * ux * uy, + 2.0 * ux * uy, + 2.0 * uy * uy - 1.0, + 0.0, 0.0) {} }; + //=================================================trans_affine_reflection + // Reflection matrix. Reflect coordinates across the line through + // the origin at the angle a or containing the non-unit vector (x, y). + // Contributed by John Horigan + class trans_affine_reflection : public trans_affine_reflection_unit + { + public: + trans_affine_reflection(double a) : + trans_affine_reflection_unit(std::cos(a), std::sin(a)) + {} + + + trans_affine_reflection(double x, double y) : + trans_affine_reflection_unit(x / std::sqrt(x * x + y * y), y / std::sqrt(x * x + y * y)) + {} + }; } diff --git a/agg2/include/agg_trans_bilinear.h b/agg/include/agg_trans_bilinear.h similarity index 81% rename from agg2/include/agg_trans_bilinear.h rename to agg/include/agg_trans_bilinear.h index ea66819..f3ab596 100644 --- a/agg2/include/agg_trans_bilinear.h +++ b/agg/include/agg_trans_bilinear.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -124,6 +124,38 @@ namespace agg *y = m_mtx[0][1] + m_mtx[1][1] * xy + m_mtx[2][1] * tx + m_mtx[3][1] * ty; } + + //-------------------------------------------------------------------- + class iterator_x + { + double inc_x; + double inc_y; + + public: + double x; + double y; + + iterator_x() {} + iterator_x(double tx, double ty, double step, const double m[4][2]) : + inc_x(m[1][0] * step * ty + m[2][0] * step), + inc_y(m[1][1] * step * ty + m[2][1] * step), + x(m[0][0] + m[1][0] * tx * ty + m[2][0] * tx + m[3][0] * ty), + y(m[0][1] + m[1][1] * tx * ty + m[2][1] * tx + m[3][1] * ty) + { + } + + void operator ++ () + { + x += inc_x; + y += inc_y; + } + }; + + iterator_x begin(double x, double y, double step) const + { + return iterator_x(x, y, step, m_mtx); + } + private: double m_mtx[4][2]; bool m_valid; diff --git a/agg2/include/agg_trans_double_path.h b/agg/include/agg_trans_double_path.h similarity index 97% rename from agg2/include/agg_trans_double_path.h rename to agg/include/agg_trans_double_path.h index 52569e6..c645a7f 100644 --- a/agg2/include/agg_trans_double_path.h +++ b/agg/include/agg_trans_double_path.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. diff --git a/agg/include/agg_trans_perspective.h b/agg/include/agg_trans_perspective.h new file mode 100644 index 0000000..1c650aa --- /dev/null +++ b/agg/include/agg_trans_perspective.h @@ -0,0 +1,732 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Perspective 2D transformations +// +//---------------------------------------------------------------------------- +#ifndef AGG_TRANS_PERSPECTIVE_INCLUDED +#define AGG_TRANS_PERSPECTIVE_INCLUDED + +#include +#include "agg_trans_affine.h" + +namespace agg +{ + //=======================================================trans_perspective + struct trans_perspective + { + double sx, shy, w0, shx, sy, w1, tx, ty, w2; + + //------------------------------------------------------- Construction + // Identity matrix + trans_perspective() : + sx (1), shy(0), w0(0), + shx(0), sy (1), w1(0), + tx (0), ty (0), w2(1) {} + + // Custom matrix + trans_perspective(double v0, double v1, double v2, + double v3, double v4, double v5, + double v6, double v7, double v8) : + sx (v0), shy(v1), w0(v2), + shx(v3), sy (v4), w1(v5), + tx (v6), ty (v7), w2(v8) {} + + // Custom matrix from m[9] + explicit trans_perspective(const double* m) : + sx (m[0]), shy(m[1]), w0(m[2]), + shx(m[3]), sy (m[4]), w1(m[5]), + tx (m[6]), ty (m[7]), w2(m[8]) {} + + // From affine + explicit trans_perspective(const trans_affine& a) : + sx (a.sx ), shy(a.shy), w0(0), + shx(a.shx), sy (a.sy ), w1(0), + tx (a.tx ), ty (a.ty ), w2(1) {} + + // Rectangle to quadrilateral + trans_perspective(double x1, double y1, double x2, double y2, + const double* quad); + + // Quadrilateral to rectangle + trans_perspective(const double* quad, + double x1, double y1, double x2, double y2); + + // Arbitrary quadrilateral transformations + trans_perspective(const double* src, const double* dst); + + //-------------------------------------- Quadrilateral transformations + // The arguments are double[8] that are mapped to quadrilaterals: + // x1,y1, x2,y2, x3,y3, x4,y4 + bool quad_to_quad(const double* qs, const double* qd); + + bool rect_to_quad(double x1, double y1, + double x2, double y2, + const double* q); + + bool quad_to_rect(const double* q, + double x1, double y1, + double x2, double y2); + + // Map square (0,0,1,1) to the quadrilateral and vice versa + bool square_to_quad(const double* q); + bool quad_to_square(const double* q); + + + //--------------------------------------------------------- Operations + // Reset - load an identity matrix + const trans_perspective& reset(); + + // Invert matrix. Returns false in degenerate case + bool invert(); + + // Direct transformations operations + const trans_perspective& translate(double x, double y); + const trans_perspective& rotate(double a); + const trans_perspective& scale(double s); + const trans_perspective& scale(double x, double y); + + // Multiply the matrix by another one + const trans_perspective& multiply(const trans_perspective& m); + + // Multiply "m" by "this" and assign the result to "this" + const trans_perspective& premultiply(const trans_perspective& m); + + // Multiply matrix to inverse of another one + const trans_perspective& multiply_inv(const trans_perspective& m); + + // Multiply inverse of "m" by "this" and assign the result to "this" + const trans_perspective& premultiply_inv(const trans_perspective& m); + + // Multiply the matrix by another one + const trans_perspective& multiply(const trans_affine& m); + + // Multiply "m" by "this" and assign the result to "this" + const trans_perspective& premultiply(const trans_affine& m); + + // Multiply the matrix by inverse of another one + const trans_perspective& multiply_inv(const trans_affine& m); + + // Multiply inverse of "m" by "this" and assign the result to "this" + const trans_perspective& premultiply_inv(const trans_affine& m); + + //--------------------------------------------------------- Load/Store + void store_to(double* m) const; + const trans_perspective& load_from(const double* m); + + //---------------------------------------------------------- Operators + // Multiply the matrix by another one + const trans_perspective& operator *= (const trans_perspective& m) + { + return multiply(m); + } + const trans_perspective& operator *= (const trans_affine& m) + { + return multiply(m); + } + + // Multiply the matrix by inverse of another one + const trans_perspective& operator /= (const trans_perspective& m) + { + return multiply_inv(m); + } + const trans_perspective& operator /= (const trans_affine& m) + { + return multiply_inv(m); + } + + // Multiply the matrix by another one and return + // the result in a separete matrix. + trans_perspective operator * (const trans_perspective& m) const + { + return trans_perspective(*this).multiply(m); + } + trans_perspective operator * (const trans_affine& m) const + { + return trans_perspective(*this).multiply(m); + } + + // Multiply the matrix by inverse of another one + // and return the result in a separete matrix. + trans_perspective operator / (const trans_perspective& m) const + { + return trans_perspective(*this).multiply_inv(m); + } + trans_perspective operator / (const trans_affine& m) const + { + return trans_perspective(*this).multiply_inv(m); + } + + // Calculate and return the inverse matrix + trans_perspective operator ~ () const + { + trans_perspective ret = *this; + ret.invert(); + return ret; + } + + // Equal operator with default epsilon + bool operator == (const trans_perspective& m) const + { + return is_equal(m, affine_epsilon); + } + + // Not Equal operator with default epsilon + bool operator != (const trans_perspective& m) const + { + return !is_equal(m, affine_epsilon); + } + + //---------------------------------------------------- Transformations + // Direct transformation of x and y + void transform(double* x, double* y) const; + + // Direct transformation of x and y, affine part only + void transform_affine(double* x, double* y) const; + + // Direct transformation of x and y, 2x2 matrix only, no translation + void transform_2x2(double* x, double* y) const; + + // Inverse transformation of x and y. It works slow because + // it explicitly inverts the matrix on every call. For massive + // operations it's better to invert() the matrix and then use + // direct transformations. + void inverse_transform(double* x, double* y) const; + + + //---------------------------------------------------------- Auxiliary + const trans_perspective& from_affine(const trans_affine& a); + double determinant() const; + double determinant_reciprocal() const; + + bool is_valid(double epsilon = affine_epsilon) const; + bool is_identity(double epsilon = affine_epsilon) const; + bool is_equal(const trans_perspective& m, + double epsilon = affine_epsilon) const; + + // Determine the major affine parameters. Use with caution + // considering possible degenerate cases. + double scale() const; + double rotation() const; + void translation(double* dx, double* dy) const; + void scaling(double* x, double* y) const; + void scaling_abs(double* x, double* y) const; + + + + //-------------------------------------------------------------------- + class iterator_x + { + double den; + double den_step; + double nom_x; + double nom_x_step; + double nom_y; + double nom_y_step; + + public: + double x; + double y; + + iterator_x() {} + iterator_x(double px, double py, double step, const trans_perspective& m) : + den(px * m.w0 + py * m.w1 + m.w2), + den_step(m.w0 * step), + nom_x(px * m.sx + py * m.shx + m.tx), + nom_x_step(step * m.sx), + nom_y(px * m.shy + py * m.sy + m.ty), + nom_y_step(step * m.shy), + x(nom_x / den), + y(nom_y / den) + {} + + void operator ++ () + { + den += den_step; + nom_x += nom_x_step; + nom_y += nom_y_step; + double d = 1.0 / den; + x = nom_x * d; + y = nom_y * d; + } + }; + + //-------------------------------------------------------------------- + iterator_x begin(double x, double y, double step) const + { + return iterator_x(x, y, step, *this); + } + }; + + + + + + + + + + + + + + + //------------------------------------------------------------------------ + inline bool trans_perspective::square_to_quad(const double* q) + { + double dx = q[0] - q[2] + q[4] - q[6]; + double dy = q[1] - q[3] + q[5] - q[7]; + if(dx == 0.0 && dy == 0.0) + { + // Affine case (parallelogram) + //--------------- + sx = q[2] - q[0]; + shy = q[3] - q[1]; + w0 = 0.0; + shx = q[4] - q[2]; + sy = q[5] - q[3]; + w1 = 0.0; + tx = q[0]; + ty = q[1]; + w2 = 1.0; + } + else + { + double dx1 = q[2] - q[4]; + double dy1 = q[3] - q[5]; + double dx2 = q[6] - q[4]; + double dy2 = q[7] - q[5]; + double den = dx1 * dy2 - dx2 * dy1; + if(den == 0.0) + { + // Singular case + //--------------- + sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0; + return false; + } + // General case + //--------------- + double u = (dx * dy2 - dy * dx2) / den; + double v = (dy * dx1 - dx * dy1) / den; + sx = q[2] - q[0] + u * q[2]; + shy = q[3] - q[1] + u * q[3]; + w0 = u; + shx = q[6] - q[0] + v * q[6]; + sy = q[7] - q[1] + v * q[7]; + w1 = v; + tx = q[0]; + ty = q[1]; + w2 = 1.0; + } + return true; + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::invert() + { + double d0 = sy * w2 - w1 * ty; + double d1 = w0 * ty - shy * w2; + double d2 = shy * w1 - w0 * sy; + double d = sx * d0 + shx * d1 + tx * d2; + if(d == 0.0) + { + sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0; + return false; + } + d = 1.0 / d; + trans_perspective a = *this; + sx = d * d0; + shy = d * d1; + w0 = d * d2; + shx = d * (a.w1 *a.tx - a.shx*a.w2); + sy = d * (a.sx *a.w2 - a.w0 *a.tx); + w1 = d * (a.w0 *a.shx - a.sx *a.w1); + tx = d * (a.shx*a.ty - a.sy *a.tx); + ty = d * (a.shy*a.tx - a.sx *a.ty); + w2 = d * (a.sx *a.sy - a.shy*a.shx); + return true; + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::quad_to_square(const double* q) + { + if(!square_to_quad(q)) return false; + invert(); + return true; + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::quad_to_quad(const double* qs, + const double* qd) + { + trans_perspective p; + if(! quad_to_square(qs)) return false; + if(!p.square_to_quad(qd)) return false; + multiply(p); + return true; + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::rect_to_quad(double x1, double y1, + double x2, double y2, + const double* q) + { + double r[8]; + r[0] = r[6] = x1; + r[2] = r[4] = x2; + r[1] = r[3] = y1; + r[5] = r[7] = y2; + return quad_to_quad(r, q); + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::quad_to_rect(const double* q, + double x1, double y1, + double x2, double y2) + { + double r[8]; + r[0] = r[6] = x1; + r[2] = r[4] = x2; + r[1] = r[3] = y1; + r[5] = r[7] = y2; + return quad_to_quad(q, r); + } + + //------------------------------------------------------------------------ + inline trans_perspective::trans_perspective(double x1, double y1, + double x2, double y2, + const double* quad) + { + rect_to_quad(x1, y1, x2, y2, quad); + } + + //------------------------------------------------------------------------ + inline trans_perspective::trans_perspective(const double* quad, + double x1, double y1, + double x2, double y2) + { + quad_to_rect(quad, x1, y1, x2, y2); + } + + //------------------------------------------------------------------------ + inline trans_perspective::trans_perspective(const double* src, + const double* dst) + { + quad_to_quad(src, dst); + } + + //------------------------------------------------------------------------ + inline const trans_perspective& trans_perspective::reset() + { + sx = 1; shy = 0; w0 = 0; + shx = 0; sy = 1; w1 = 0; + tx = 0; ty = 0; w2 = 1; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& + trans_perspective::multiply(const trans_perspective& a) + { + trans_perspective b = *this; + sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0; + shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1; + tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2; + shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0; + sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1; + ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2; + w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0; + w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1; + w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& + trans_perspective::multiply(const trans_affine& a) + { + trans_perspective b = *this; + sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0; + shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1; + tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2; + shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0; + sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1; + ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& + trans_perspective::premultiply(const trans_perspective& b) + { + trans_perspective a = *this; + sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0; + shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1; + tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2; + shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0; + sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1; + ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2; + w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0; + w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1; + w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& + trans_perspective::premultiply(const trans_affine& b) + { + trans_perspective a = *this; + sx = a.sx *b.sx + a.shx*b.shy; + shx = a.sx *b.shx + a.shx*b.sy; + tx = a.sx *b.tx + a.shx*b.ty + a.tx; + shy = a.shy*b.sx + a.sy *b.shy; + sy = a.shy*b.shx + a.sy *b.sy; + ty = a.shy*b.tx + a.sy *b.ty + a.ty; + w0 = a.w0 *b.sx + a.w1 *b.shy; + w1 = a.w0 *b.shx + a.w1 *b.sy; + w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2; + return *this; + } + + //------------------------------------------------------------------------ + const trans_perspective& + trans_perspective::multiply_inv(const trans_perspective& m) + { + trans_perspective t = m; + t.invert(); + return multiply(t); + } + + //------------------------------------------------------------------------ + const trans_perspective& + trans_perspective::multiply_inv(const trans_affine& m) + { + trans_affine t = m; + t.invert(); + return multiply(t); + } + + //------------------------------------------------------------------------ + const trans_perspective& + trans_perspective::premultiply_inv(const trans_perspective& m) + { + trans_perspective t = m; + t.invert(); + return *this = t.multiply(*this); + } + + //------------------------------------------------------------------------ + const trans_perspective& + trans_perspective::premultiply_inv(const trans_affine& m) + { + trans_perspective t(m); + t.invert(); + return *this = t.multiply(*this); + } + + //------------------------------------------------------------------------ + inline const trans_perspective& + trans_perspective::translate(double x, double y) + { + tx += x; + ty += y; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& trans_perspective::rotate(double a) + { + multiply(trans_affine_rotation(a)); + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& trans_perspective::scale(double s) + { + multiply(trans_affine_scaling(s)); + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& trans_perspective::scale(double x, double y) + { + multiply(trans_affine_scaling(x, y)); + return *this; + } + + //------------------------------------------------------------------------ + inline void trans_perspective::transform(double* px, double* py) const + { + double x = *px; + double y = *py; + double m = 1.0 / (x*w0 + y*w1 + w2); + *px = m * (x*sx + y*shx + tx); + *py = m * (x*shy + y*sy + ty); + } + + //------------------------------------------------------------------------ + inline void trans_perspective::transform_affine(double* x, double* y) const + { + double tmp = *x; + *x = tmp * sx + *y * shx + tx; + *y = tmp * shy + *y * sy + ty; + } + + //------------------------------------------------------------------------ + inline void trans_perspective::transform_2x2(double* x, double* y) const + { + double tmp = *x; + *x = tmp * sx + *y * shx; + *y = tmp * shy + *y * sy; + } + + //------------------------------------------------------------------------ + inline void trans_perspective::inverse_transform(double* x, double* y) const + { + trans_perspective t(*this); + if(t.invert()) t.transform(x, y); + } + + //------------------------------------------------------------------------ + inline void trans_perspective::store_to(double* m) const + { + *m++ = sx; *m++ = shy; *m++ = w0; + *m++ = shx; *m++ = sy; *m++ = w1; + *m++ = tx; *m++ = ty; *m++ = w2; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& trans_perspective::load_from(const double* m) + { + sx = *m++; shy = *m++; w0 = *m++; + shx = *m++; sy = *m++; w1 = *m++; + tx = *m++; ty = *m++; w2 = *m++; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& + trans_perspective::from_affine(const trans_affine& a) + { + sx = a.sx; shy = a.shy; w0 = 0; + shx = a.shx; sy = a.sy; w1 = 0; + tx = a.tx; ty = a.ty; w2 = 1; + return *this; + } + + //------------------------------------------------------------------------ + inline double trans_perspective::determinant() const + { + return sx * (sy * w2 - ty * w1) + + shx * (ty * w0 - shy * w2) + + tx * (shy * w1 - sy * w0); + } + + //------------------------------------------------------------------------ + inline double trans_perspective::determinant_reciprocal() const + { + return 1.0 / determinant(); + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::is_valid(double epsilon) const + { + return std::fabs(sx) > epsilon && std::fabs(sy) > epsilon && std::fabs(w2) > epsilon; + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::is_identity(double epsilon) const + { + return is_equal_eps(sx, 1.0, epsilon) && + is_equal_eps(shy, 0.0, epsilon) && + is_equal_eps(w0, 0.0, epsilon) && + is_equal_eps(shx, 0.0, epsilon) && + is_equal_eps(sy, 1.0, epsilon) && + is_equal_eps(w1, 0.0, epsilon) && + is_equal_eps(tx, 0.0, epsilon) && + is_equal_eps(ty, 0.0, epsilon) && + is_equal_eps(w2, 1.0, epsilon); + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::is_equal(const trans_perspective& m, + double epsilon) const + { + return is_equal_eps(sx, m.sx, epsilon) && + is_equal_eps(shy, m.shy, epsilon) && + is_equal_eps(w0, m.w0, epsilon) && + is_equal_eps(shx, m.shx, epsilon) && + is_equal_eps(sy, m.sy, epsilon) && + is_equal_eps(w1, m.w1, epsilon) && + is_equal_eps(tx, m.tx, epsilon) && + is_equal_eps(ty, m.ty, epsilon) && + is_equal_eps(w2, m.w2, epsilon); + } + + //------------------------------------------------------------------------ + inline double trans_perspective::scale() const + { + double x = 0.707106781 * sx + 0.707106781 * shx; + double y = 0.707106781 * shy + 0.707106781 * sy; + return std::sqrt(x*x + y*y); + } + + //------------------------------------------------------------------------ + inline double trans_perspective::rotation() const + { + double x1 = 0.0; + double y1 = 0.0; + double x2 = 1.0; + double y2 = 0.0; + transform(&x1, &y1); + transform(&x2, &y2); + return std::atan2(y2-y1, x2-x1); + } + + //------------------------------------------------------------------------ + void trans_perspective::translation(double* dx, double* dy) const + { + *dx = tx; + *dy = ty; + } + + //------------------------------------------------------------------------ + void trans_perspective::scaling(double* x, double* y) const + { + double x1 = 0.0; + double y1 = 0.0; + double x2 = 1.0; + double y2 = 1.0; + trans_perspective t(*this); + t *= trans_affine_rotation(-rotation()); + t.transform(&x1, &y1); + t.transform(&x2, &y2); + *x = x2 - x1; + *y = y2 - y1; + } + + //------------------------------------------------------------------------ + void trans_perspective::scaling_abs(double* x, double* y) const + { + *x = std::sqrt(sx * sx + shx * shx); + *y = std::sqrt(shy * shy + sy * sy); + } + + +} + +#endif + diff --git a/agg2/include/agg_trans_single_path.h b/agg/include/agg_trans_single_path.h similarity index 96% rename from agg2/include/agg_trans_single_path.h rename to agg/include/agg_trans_single_path.h index ef333d1..9f4bf53 100644 --- a/agg2/include/agg_trans_single_path.h +++ b/agg/include/agg_trans_single_path.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. diff --git a/agg2/include/agg_trans_viewport.h b/agg/include/agg_trans_viewport.h similarity index 63% rename from agg2/include/agg_trans_viewport.h rename to agg/include/agg_trans_viewport.h index 1fba514..551cdf1 100644 --- a/agg2/include/agg_trans_viewport.h +++ b/agg/include/agg_trans_viewport.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -21,8 +21,9 @@ #ifndef AGG_TRANS_VIEWPORT_INCLUDED #define AGG_TRANS_VIEWPORT_INCLUDED -#include -#include "agg_basics.h" +#include +#include +#include "agg_trans_affine.h" namespace agg @@ -51,6 +52,7 @@ namespace agg m_device_x2(1.0), m_device_y2(1.0), m_aspect(aspect_ratio_stretch), + m_is_valid(true), m_align_x(0.5), m_align_y(0.5), m_wx1(0.0), @@ -123,6 +125,7 @@ namespace agg } //------------------------------------------------------------------- + bool is_valid() const { return m_is_valid; } double align_x() const { return m_align_x; } double align_y() const { return m_align_y; } aspect_ratio_e aspect_ratio() const { return m_aspect; } @@ -134,6 +137,13 @@ namespace agg *y = (*y - m_wy1) * m_ky + m_dy1; } + //------------------------------------------------------------------- + void transform_scale_only(double* x, double* y) const + { + *x *= m_kx; + *y *= m_ky; + } + //------------------------------------------------------------------- void inverse_transform(double* x, double* y) const { @@ -141,81 +151,64 @@ namespace agg *y = (*y - m_dy1) / m_ky + m_wy1; } + //------------------------------------------------------------------- + void inverse_transform_scale_only(double* x, double* y) const + { + *x /= m_kx; + *y /= m_ky; + } + + //------------------------------------------------------------------- + double device_dx() const { return m_dx1 - m_wx1 * m_kx; } + double device_dy() const { return m_dy1 - m_wy1 * m_ky; } + + //------------------------------------------------------------------- + double scale_x() const + { + return m_kx; + } + + //------------------------------------------------------------------- + double scale_y() const + { + return m_ky; + } + //------------------------------------------------------------------- double scale() const { return (m_kx + m_ky) * 0.5; } + //------------------------------------------------------------------- + trans_affine to_affine() const + { + trans_affine mtx = trans_affine_translation(-m_wx1, -m_wy1); + mtx *= trans_affine_scaling(m_kx, m_ky); + mtx *= trans_affine_translation(m_dx1, m_dy1); + return mtx; + } + + //------------------------------------------------------------------- + trans_affine to_affine_scale_only() const + { + return trans_affine_scaling(m_kx, m_ky); + } + //------------------------------------------------------------------- unsigned byte_size() const { - return - sizeof(m_world_x1) + - sizeof(m_world_y1) + - sizeof(m_world_x2) + - sizeof(m_world_y2) + - sizeof(m_device_x1) + - sizeof(m_device_y1) + - sizeof(m_device_x2) + - sizeof(m_device_y2) + - sizeof(m_aspect) + - sizeof(m_align_x) + - sizeof(m_align_y) + - sizeof(m_wx1) + - sizeof(m_wy1) + - sizeof(m_wx2) + - sizeof(m_wy2) + - sizeof(m_dx1) + - sizeof(m_dy1) + - sizeof(m_kx) + - sizeof(m_ky); + return sizeof(*this); } void serialize(int8u* ptr) const { - memcpy(ptr, &m_world_x1, sizeof(m_world_x1)); ptr += sizeof(m_world_x1); - memcpy(ptr, &m_world_y1, sizeof(m_world_y1)); ptr += sizeof(m_world_y1); - memcpy(ptr, &m_world_x2, sizeof(m_world_x2)); ptr += sizeof(m_world_x2); - memcpy(ptr, &m_world_y2, sizeof(m_world_y2)); ptr += sizeof(m_world_y2); - memcpy(ptr, &m_device_x1, sizeof(m_device_x1)); ptr += sizeof(m_device_x1); - memcpy(ptr, &m_device_y1, sizeof(m_device_y1)); ptr += sizeof(m_device_y1); - memcpy(ptr, &m_device_x2, sizeof(m_device_x2)); ptr += sizeof(m_device_x2); - memcpy(ptr, &m_device_y2, sizeof(m_device_y2)); ptr += sizeof(m_device_y2); - memcpy(ptr, &m_aspect, sizeof(m_aspect)); ptr += sizeof(m_aspect); - memcpy(ptr, &m_align_x, sizeof(m_align_x)); ptr += sizeof(m_align_x); - memcpy(ptr, &m_align_y, sizeof(m_align_y)); ptr += sizeof(m_align_y); - memcpy(ptr, &m_wx1, sizeof(m_wx1)); ptr += sizeof(m_wx1); - memcpy(ptr, &m_wy1, sizeof(m_wy1)); ptr += sizeof(m_wy1); - memcpy(ptr, &m_wx2, sizeof(m_wx2)); ptr += sizeof(m_wx2); - memcpy(ptr, &m_wy2, sizeof(m_wy2)); ptr += sizeof(m_wy2); - memcpy(ptr, &m_dx1, sizeof(m_dx1)); ptr += sizeof(m_dx1); - memcpy(ptr, &m_dy1, sizeof(m_dy1)); ptr += sizeof(m_dy1); - memcpy(ptr, &m_kx, sizeof(m_kx)); ptr += sizeof(m_kx); - memcpy(ptr, &m_ky, sizeof(m_ky)); ptr += sizeof(m_ky); + std::memcpy(ptr, this, sizeof(*this)); } void deserialize(const int8u* ptr) { - memcpy(&m_world_x1, ptr, sizeof(m_world_x1)); ptr += sizeof(m_world_x1); - memcpy(&m_world_y1, ptr, sizeof(m_world_y1)); ptr += sizeof(m_world_y1); - memcpy(&m_world_x2, ptr, sizeof(m_world_x2)); ptr += sizeof(m_world_x2); - memcpy(&m_world_y2, ptr, sizeof(m_world_y2)); ptr += sizeof(m_world_y2); - memcpy(&m_device_x1, ptr, sizeof(m_device_x1)); ptr += sizeof(m_device_x1); - memcpy(&m_device_y1, ptr, sizeof(m_device_y1)); ptr += sizeof(m_device_y1); - memcpy(&m_device_x2, ptr, sizeof(m_device_x2)); ptr += sizeof(m_device_x2); - memcpy(&m_device_y2, ptr, sizeof(m_device_y2)); ptr += sizeof(m_device_y2); - memcpy(&m_aspect, ptr, sizeof(m_aspect)); ptr += sizeof(m_aspect); - memcpy(&m_align_x, ptr, sizeof(m_align_x)); ptr += sizeof(m_align_x); - memcpy(&m_align_y, ptr, sizeof(m_align_y)); ptr += sizeof(m_align_y); - memcpy(&m_wx1, ptr, sizeof(m_wx1)); ptr += sizeof(m_wx1); - memcpy(&m_wy1, ptr, sizeof(m_wy1)); ptr += sizeof(m_wy1); - memcpy(&m_wx2, ptr, sizeof(m_wx2)); ptr += sizeof(m_wx2); - memcpy(&m_wy2, ptr, sizeof(m_wy2)); ptr += sizeof(m_wy2); - memcpy(&m_dx1, ptr, sizeof(m_dx1)); ptr += sizeof(m_dx1); - memcpy(&m_dy1, ptr, sizeof(m_dy1)); ptr += sizeof(m_dy1); - memcpy(&m_kx, ptr, sizeof(m_kx)); ptr += sizeof(m_kx); - memcpy(&m_ky, ptr, sizeof(m_ky)); ptr += sizeof(m_ky); + std::memcpy(this, ptr, sizeof(*this)); } private: @@ -230,6 +223,7 @@ namespace agg double m_device_x2; double m_device_y2; aspect_ratio_e m_aspect; + bool m_is_valid; double m_align_x; double m_align_y; double m_wx1; @@ -247,6 +241,24 @@ namespace agg //----------------------------------------------------------------------- inline void trans_viewport::update() { + const double epsilon = 1e-30; + if(std::fabs(m_world_x1 - m_world_x2) < epsilon || + std::fabs(m_world_y1 - m_world_y2) < epsilon || + std::fabs(m_device_x1 - m_device_x2) < epsilon || + std::fabs(m_device_y1 - m_device_y2) < epsilon) + { + m_wx1 = m_world_x1; + m_wy1 = m_world_y1; + m_wx2 = m_world_x1 + 1.0; + m_wy2 = m_world_y2 + 1.0; + m_dx1 = m_device_x1; + m_dy1 = m_device_y1; + m_kx = 1.0; + m_ky = 1.0; + m_is_valid = false; + return; + } + double world_x1 = m_world_x1; double world_y1 = m_world_y1; double world_x2 = m_world_x2; @@ -282,6 +294,7 @@ namespace agg m_dy1 = device_y1; m_kx = (device_x2 - device_x1) / (world_x2 - world_x1); m_ky = (device_y2 - device_y1) / (world_y2 - world_y1); + m_is_valid = true; } diff --git a/agg2/include/agg_trans_warp_magnifier.h b/agg/include/agg_trans_warp_magnifier.h similarity index 81% rename from agg2/include/agg_trans_warp_magnifier.h rename to agg/include/agg_trans_warp_magnifier.h index 45f582a..38a92db 100644 --- a/agg2/include/agg_trans_warp_magnifier.h +++ b/agg/include/agg_trans_warp_magnifier.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -33,6 +33,11 @@ namespace agg void magnification(double m) { m_magn = m; } void radius(double r) { m_radius = r; } + double xc() const { return m_xc; } + double yc() const { return m_yc; } + double magnification() const { return m_magn; } + double radius() const { return m_radius; } + void transform(double* x, double* y) const; void inverse_transform(double* x, double* y) const; diff --git a/agg2/include/agg_vcgen_bspline.h b/agg/include/agg_vcgen_bspline.h similarity index 90% rename from agg2/include/agg_vcgen_bspline.h rename to agg/include/agg_vcgen_bspline.h index d45425b..a294454 100644 --- a/agg2/include/agg_vcgen_bspline.h +++ b/agg/include/agg_vcgen_bspline.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -37,7 +37,7 @@ namespace agg }; public: - typedef pod_deque vertex_storage; + typedef pod_bvector vertex_storage; vcgen_bspline(); @@ -49,7 +49,7 @@ namespace agg void add_vertex(double x, double y, unsigned cmd); // Vertex Source Interface - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: diff --git a/agg/include/agg_vcgen_contour.h b/agg/include/agg_vcgen_contour.h new file mode 100644 index 0000000..8c25da1 --- /dev/null +++ b/agg/include/agg_vcgen_contour.h @@ -0,0 +1,94 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_VCGEN_CONTOUR_INCLUDED +#define AGG_VCGEN_CONTOUR_INCLUDED + +#include "agg_math_stroke.h" + +namespace agg +{ + + //----------------------------------------------------------vcgen_contour + // + // See Implementation agg_vcgen_contour.cpp + // + class vcgen_contour + { + enum status_e + { + initial, + ready, + outline, + out_vertices, + end_poly, + stop + }; + + public: + typedef vertex_sequence vertex_storage; + typedef pod_bvector coord_storage; + + vcgen_contour(); + + void line_cap(line_cap_e lc) { m_stroker.line_cap(lc); } + void line_join(line_join_e lj) { m_stroker.line_join(lj); } + void inner_join(inner_join_e ij) { m_stroker.inner_join(ij); } + + line_cap_e line_cap() const { return m_stroker.line_cap(); } + line_join_e line_join() const { return m_stroker.line_join(); } + inner_join_e inner_join() const { return m_stroker.inner_join(); } + + void width(double w) { m_stroker.width(m_width = w); } + void miter_limit(double ml) { m_stroker.miter_limit(ml); } + void miter_limit_theta(double t) { m_stroker.miter_limit_theta(t); } + void inner_miter_limit(double ml) { m_stroker.inner_miter_limit(ml); } + void approximation_scale(double as) { m_stroker.approximation_scale(as); } + + double width() const { return m_width; } + double miter_limit() const { return m_stroker.miter_limit(); } + double inner_miter_limit() const { return m_stroker.inner_miter_limit(); } + double approximation_scale() const { return m_stroker.approximation_scale(); } + + void auto_detect_orientation(bool v) { m_auto_detect = v; } + bool auto_detect_orientation() const { return m_auto_detect; } + + // Generator interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + vcgen_contour(const vcgen_contour&); + const vcgen_contour& operator = (const vcgen_contour&); + + math_stroke m_stroker; + double m_width; + vertex_storage m_src_vertices; + coord_storage m_out_vertices; + status_e m_status; + unsigned m_src_vertex; + unsigned m_out_vertex; + unsigned m_closed; + unsigned m_orientation; + bool m_auto_detect; + }; + +} + +#endif diff --git a/agg2/include/agg_vcgen_dash.h b/agg/include/agg_vcgen_dash.h similarity index 85% rename from agg2/include/agg_vcgen_dash.h rename to agg/include/agg_vcgen_dash.h index 0e9d7d0..c87dce4 100644 --- a/agg2/include/agg_vcgen_dash.h +++ b/agg/include/agg_vcgen_dash.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -21,7 +21,6 @@ #include "agg_basics.h" #include "agg_vertex_sequence.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -32,7 +31,7 @@ namespace agg // class vcgen_dash { - enum + enum max_dashes_e { max_dashes = 32 }; @@ -62,14 +61,9 @@ namespace agg void add_vertex(double x, double y, unsigned cmd); // Vertex Source Interface - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); - typedef vcgen_dash source_type; - typedef vertex_iterator iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: vcgen_dash(const vcgen_dash&); const vcgen_dash& operator = (const vcgen_dash&); diff --git a/agg2/include/agg_vcgen_markers_term.h b/agg/include/agg_vcgen_markers_term.h similarity index 79% rename from agg2/include/agg_vcgen_markers_term.h rename to agg/include/agg_vcgen_markers_term.h index 2bfef0c..ee1e74e 100644 --- a/agg2/include/agg_vcgen_markers_term.h +++ b/agg/include/agg_vcgen_markers_term.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -18,7 +18,6 @@ #include "agg_basics.h" #include "agg_vertex_sequence.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -39,14 +38,9 @@ namespace agg void add_vertex(double x, double y, unsigned cmd); // Vertex Source Interface - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); - typedef vcgen_markers_term source_type; - typedef vertex_iterator iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: vcgen_markers_term(const vcgen_markers_term&); const vcgen_markers_term& operator = (const vcgen_markers_term&); @@ -59,7 +53,7 @@ namespace agg coord_type(double x_, double y_) : x(x_), y(y_) {} }; - typedef pod_deque coord_storage; + typedef pod_bvector coord_storage; coord_storage m_markers; unsigned m_curr_id; diff --git a/agg2/include/agg_vcgen_smooth_poly1.h b/agg/include/agg_vcgen_smooth_poly1.h similarity index 94% rename from agg2/include/agg_vcgen_smooth_poly1.h rename to agg/include/agg_vcgen_smooth_poly1.h index 346a38a..80fc0fb 100644 --- a/agg2/include/agg_vcgen_smooth_poly1.h +++ b/agg/include/agg_vcgen_smooth_poly1.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -57,7 +57,7 @@ namespace agg void add_vertex(double x, double y, unsigned cmd); // Vertex Source Interface - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: diff --git a/agg/include/agg_vcgen_stroke.h b/agg/include/agg_vcgen_stroke.h new file mode 100644 index 0000000..778223f --- /dev/null +++ b/agg/include/agg_vcgen_stroke.h @@ -0,0 +1,102 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_VCGEN_STROKE_INCLUDED +#define AGG_VCGEN_STROKE_INCLUDED + +#include "agg_math_stroke.h" + + +namespace agg +{ + + //============================================================vcgen_stroke + // + // See Implementation agg_vcgen_stroke.cpp + // Stroke generator + // + //------------------------------------------------------------------------ + class vcgen_stroke + { + enum status_e + { + initial, + ready, + cap1, + cap2, + outline1, + close_first, + outline2, + out_vertices, + end_poly1, + end_poly2, + stop + }; + + public: + typedef vertex_sequence vertex_storage; + typedef pod_bvector coord_storage; + + vcgen_stroke(); + + void line_cap(line_cap_e lc) { m_stroker.line_cap(lc); } + void line_join(line_join_e lj) { m_stroker.line_join(lj); } + void inner_join(inner_join_e ij) { m_stroker.inner_join(ij); } + + line_cap_e line_cap() const { return m_stroker.line_cap(); } + line_join_e line_join() const { return m_stroker.line_join(); } + inner_join_e inner_join() const { return m_stroker.inner_join(); } + + void width(double w) { m_stroker.width(w); } + void miter_limit(double ml) { m_stroker.miter_limit(ml); } + void miter_limit_theta(double t) { m_stroker.miter_limit_theta(t); } + void inner_miter_limit(double ml) { m_stroker.inner_miter_limit(ml); } + void approximation_scale(double as) { m_stroker.approximation_scale(as); } + + double width() const { return m_stroker.width(); } + double miter_limit() const { return m_stroker.miter_limit(); } + double inner_miter_limit() const { return m_stroker.inner_miter_limit(); } + double approximation_scale() const { return m_stroker.approximation_scale(); } + + void shorten(double s) { m_shorten = s; } + double shorten() const { return m_shorten; } + + // Vertex Generator Interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + vcgen_stroke(const vcgen_stroke&); + const vcgen_stroke& operator = (const vcgen_stroke&); + + math_stroke m_stroker; + vertex_storage m_src_vertices; + coord_storage m_out_vertices; + double m_shorten; + unsigned m_closed; + status_e m_status; + status_e m_prev_status; + unsigned m_src_vertex; + unsigned m_out_vertex; + }; + + +} + +#endif diff --git a/agg2/include/agg_vcgen_vertex_sequence.h b/agg/include/agg_vcgen_vertex_sequence.h similarity index 96% rename from agg2/include/agg_vcgen_vertex_sequence.h rename to agg/include/agg_vcgen_vertex_sequence.h index be87309..5adc671 100644 --- a/agg2/include/agg_vcgen_vertex_sequence.h +++ b/agg/include/agg_vcgen_vertex_sequence.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -43,7 +43,7 @@ namespace agg void add_vertex(double x, double y, unsigned cmd); // Vertex Source Interface - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); void shorten(double s) { m_shorten = s; } diff --git a/agg2/include/agg_vertex_sequence.h b/agg/include/agg_vertex_sequence.h similarity index 91% rename from agg2/include/agg_vertex_sequence.h rename to agg/include/agg_vertex_sequence.h index b650f5e..2ad0701 100644 --- a/agg2/include/agg_vertex_sequence.h +++ b/agg/include/agg_vertex_sequence.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -27,10 +27,10 @@ namespace agg { //----------------------------------------------------------vertex_sequence - // Modified agg::pod_deque. The data is interpreted as a sequence of vertices. - // It means that the type T must expose: + // Modified agg::pod_bvector. The data is interpreted as a sequence + // of vertices. It means that the type T must expose: // - // bool operator() (const T& val) + // bool T::operator() (const T& val) // // that is called every time new vertex is being added. The main purpose // of this operator is the possibility to calculate some values during @@ -64,10 +64,10 @@ namespace agg // necessary. //------------------------------------------------------------------------ template - class vertex_sequence : public pod_deque + class vertex_sequence : public pod_bvector { public: - typedef pod_deque base_type; + typedef pod_bvector base_type; void add(const T& val); void modify_last(const T& val); @@ -124,10 +124,6 @@ namespace agg } - - // Coinciding points maximal distance (Epsilon) - const double vertex_dist_epsilon = 1e-14; - //-------------------------------------------------------------vertex_dist // Vertex (x, y) with the distance to the next one. The last vertex has // distance between the last and the first points if the polygon is closed diff --git a/agg2/include/agg_vpgen_clip_polygon.h b/agg/include/agg_vpgen_clip_polygon.h similarity index 91% rename from agg2/include/agg_vpgen_clip_polygon.h rename to agg/include/agg_vpgen_clip_polygon.h index c1e331a..ded754e 100644 --- a/agg2/include/agg_vpgen_clip_polygon.h +++ b/agg/include/agg_vpgen_clip_polygon.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -54,6 +54,9 @@ namespace agg double x2() const { return m_clip_box.x2; } double y2() const { return m_clip_box.y2; } + static bool auto_close() { return true; } + static bool auto_unclose() { return false; } + void reset(); void move_to(double x, double y); void line_to(double x, double y); diff --git a/agg/include/agg_vpgen_clip_polyline.h b/agg/include/agg_vpgen_clip_polyline.h new file mode 100644 index 0000000..b070a77 --- /dev/null +++ b/agg/include/agg_vpgen_clip_polyline.h @@ -0,0 +1,78 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_VPGEN_CLIP_POLYLINE_INCLUDED +#define AGG_VPGEN_CLIP_POLYLINE_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //======================================================vpgen_clip_polyline + // + // See Implementation agg_vpgen_clip_polyline.cpp + // + class vpgen_clip_polyline + { + public: + vpgen_clip_polyline() : + m_clip_box(0, 0, 1, 1), + m_x1(0), + m_y1(0), + m_num_vertices(0), + m_vertex(0), + m_move_to(false) + { + } + + void clip_box(double x1, double y1, double x2, double y2) + { + m_clip_box.x1 = x1; + m_clip_box.y1 = y1; + m_clip_box.x2 = x2; + m_clip_box.y2 = y2; + m_clip_box.normalize(); + } + + double x1() const { return m_clip_box.x1; } + double y1() const { return m_clip_box.y1; } + double x2() const { return m_clip_box.x2; } + double y2() const { return m_clip_box.y2; } + + static bool auto_close() { return false; } + static bool auto_unclose() { return true; } + + void reset(); + void move_to(double x, double y); + void line_to(double x, double y); + unsigned vertex(double* x, double* y); + + private: + rect_d m_clip_box; + double m_x1; + double m_y1; + double m_x[2]; + double m_y[2]; + unsigned m_cmd[2]; + unsigned m_num_vertices; + unsigned m_vertex; + bool m_move_to; + }; + +} + + +#endif diff --git a/agg2/include/agg_vpgen_segmentator.h b/agg/include/agg_vpgen_segmentator.h similarity index 88% rename from agg2/include/agg_vpgen_segmentator.h rename to agg/include/agg_vpgen_segmentator.h index cbfde4d..77248ee 100644 --- a/agg2/include/agg_vpgen_segmentator.h +++ b/agg/include/agg_vpgen_segmentator.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -16,7 +16,6 @@ #ifndef AGG_VPGEN_SEGMENTATOR_INCLUDED #define AGG_VPGEN_SEGMENTATOR_INCLUDED -#include #include "agg_basics.h" namespace agg @@ -34,11 +33,12 @@ namespace agg void approximation_scale(double s) { m_approximation_scale = s; } double approximation_scale() const { return m_approximation_scale; } - void reset() { m_cmd = path_cmd_stop; } + static bool auto_close() { return false; } + static bool auto_unclose() { return false; } + void reset() { m_cmd = path_cmd_stop; } void move_to(double x, double y); void line_to(double x, double y); - unsigned vertex(double* x, double* y); private: diff --git a/agg/include/ctrl/Makefile.am b/agg/include/ctrl/Makefile.am new file mode 100644 index 0000000..660c583 --- /dev/null +++ b/agg/include/ctrl/Makefile.am @@ -0,0 +1,4 @@ +aggincludedir = $(includedir)/agg2/ctrl +agginclude_HEADERS = agg_ctrl.h agg_gamma_spline.h agg_scale_ctrl.h agg_spline_ctrl.h \ + agg_cbox_ctrl.h agg_gamma_ctrl.h agg_rbox_ctrl.h agg_slider_ctrl.h \ + agg_bezier_ctrl.h agg_polygon_ctrl.h diff --git a/agg/include/ctrl/agg_bezier_ctrl.h b/agg/include/ctrl/agg_bezier_ctrl.h new file mode 100644 index 0000000..f300d73 --- /dev/null +++ b/agg/include/ctrl/agg_bezier_ctrl.h @@ -0,0 +1,196 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// classes bezier_ctrl_impl, bezier_ctrl +// +//---------------------------------------------------------------------------- + +#ifndef AGG_BEZIER_CTRL_INCLUDED +#define AGG_BEZIER_CTRL_INCLUDED + +#include "agg_math.h" +#include "agg_ellipse.h" +#include "agg_trans_affine.h" +#include "agg_color_rgba.h" +#include "agg_conv_stroke.h" +#include "agg_conv_curve.h" +#include "agg_polygon_ctrl.h" + + +namespace agg +{ + + //--------------------------------------------------------bezier_ctrl_impl + class bezier_ctrl_impl : public ctrl + { + public: + bezier_ctrl_impl(); + + void curve(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4); + curve4& curve(); + + double x1() const { return m_poly.xn(0); } + double y1() const { return m_poly.yn(0); } + double x2() const { return m_poly.xn(1); } + double y2() const { return m_poly.yn(1); } + double x3() const { return m_poly.xn(2); } + double y3() const { return m_poly.yn(2); } + double x4() const { return m_poly.xn(3); } + double y4() const { return m_poly.yn(3); } + + void x1(double x) { m_poly.xn(0) = x; } + void y1(double y) { m_poly.yn(0) = y; } + void x2(double x) { m_poly.xn(1) = x; } + void y2(double y) { m_poly.yn(1) = y; } + void x3(double x) { m_poly.xn(2) = x; } + void y3(double y) { m_poly.yn(2) = y; } + void x4(double x) { m_poly.xn(3) = x; } + void y4(double y) { m_poly.yn(3) = y; } + + void line_width(double w) { m_stroke.width(w); } + double line_width() const { return m_stroke.width(); } + + void point_radius(double r) { m_poly.point_radius(r); } + double point_radius() const { return m_poly.point_radius(); } + + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + // Vertex source interface + unsigned num_paths() { return 7; }; + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + + private: + curve4 m_curve; + ellipse m_ellipse; + conv_stroke m_stroke; + polygon_ctrl_impl m_poly; + unsigned m_idx; + }; + + + + //----------------------------------------------------------bezier_ctrl + template class bezier_ctrl : public bezier_ctrl_impl + { + public: + bezier_ctrl() : + m_color(rgba(0.0, 0.0, 0.0)) + { + } + + void line_color(const ColorT& c) { m_color = c; } + const ColorT& color(unsigned) const { return m_color; } + + private: + bezier_ctrl(const bezier_ctrl&); + const bezier_ctrl& operator = (const bezier_ctrl&); + + ColorT m_color; + }; + + + + + + //--------------------------------------------------------curve3_ctrl_impl + class curve3_ctrl_impl : public ctrl + { + public: + curve3_ctrl_impl(); + + void curve(double x1, double y1, + double x2, double y2, + double x3, double y3); + curve3& curve(); + + double x1() const { return m_poly.xn(0); } + double y1() const { return m_poly.yn(0); } + double x2() const { return m_poly.xn(1); } + double y2() const { return m_poly.yn(1); } + double x3() const { return m_poly.xn(2); } + double y3() const { return m_poly.yn(2); } + + void x1(double x) { m_poly.xn(0) = x; } + void y1(double y) { m_poly.yn(0) = y; } + void x2(double x) { m_poly.xn(1) = x; } + void y2(double y) { m_poly.yn(1) = y; } + void x3(double x) { m_poly.xn(2) = x; } + void y3(double y) { m_poly.yn(2) = y; } + + void line_width(double w) { m_stroke.width(w); } + double line_width() const { return m_stroke.width(); } + + void point_radius(double r) { m_poly.point_radius(r); } + double point_radius() const { return m_poly.point_radius(); } + + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + // Vertex source interface + unsigned num_paths() { return 6; }; + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + + private: + curve3 m_curve; + ellipse m_ellipse; + conv_stroke m_stroke; + polygon_ctrl_impl m_poly; + unsigned m_idx; + }; + + + + //----------------------------------------------------------curve3_ctrl + template class curve3_ctrl : public curve3_ctrl_impl + { + public: + curve3_ctrl() : + m_color(rgba(0.0, 0.0, 0.0)) + { + } + + void line_color(const ColorT& c) { m_color = c; } + const ColorT& color(unsigned i) const { return m_color; } + + private: + curve3_ctrl(const curve3_ctrl&); + const curve3_ctrl& operator = (const curve3_ctrl&); + + ColorT m_color; + }; + + + + +} + + + +#endif + diff --git a/agg2/include/ctrl/agg_cbox_ctrl.h b/agg/include/ctrl/agg_cbox_ctrl.h similarity index 96% rename from agg2/include/ctrl/agg_cbox_ctrl.h rename to agg/include/ctrl/agg_cbox_ctrl.h index d1aa5a4..7ecbce2 100644 --- a/agg2/include/ctrl/agg_cbox_ctrl.h +++ b/agg/include/ctrl/agg_cbox_ctrl.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -55,7 +55,7 @@ namespace agg // Vertex soutce interface unsigned num_paths() { return 3; }; - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: diff --git a/agg2/include/ctrl/agg_ctrl.h b/agg/include/ctrl/agg_ctrl.h similarity index 81% rename from agg2/include/ctrl/agg_ctrl.h rename to agg/include/ctrl/agg_ctrl.h index 9c120ae..7e811c6 100644 --- a/agg2/include/ctrl/agg_ctrl.h +++ b/agg/include/ctrl/agg_ctrl.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -31,6 +31,7 @@ namespace agg { public: //-------------------------------------------------------------------- + virtual ~ctrl() {} ctrl(double x1, double y1, double x2, double y2, bool flip_y) : m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2), m_flip_y(flip_y), @@ -63,6 +64,9 @@ namespace agg if(m_flip_y) *y = m_y1 + m_y2 - *y; } + //-------------------------------------------------------------------- + double scale() const { return m_mtx ? m_mtx->scale() : 1.0; } + private: ctrl(const ctrl&); const ctrl& operator = (const ctrl&); @@ -82,6 +86,20 @@ namespace agg //-------------------------------------------------------------------- template void render_ctrl(Rasterizer& ras, Scanline& sl, Renderer& r, Ctrl& c) + { + unsigned i; + for(i = 0; i < c.num_paths(); i++) + { + ras.reset(); + ras.add_path(c, i); + render_scanlines_aa_solid(ras, sl, r, c.color(i)); + } + } + + + //-------------------------------------------------------------------- + template + void render_ctrl_rs(Rasterizer& ras, Scanline& sl, Renderer& r, Ctrl& c) { unsigned i; for(i = 0; i < c.num_paths(); i++) diff --git a/agg2/include/ctrl/agg_gamma_ctrl.h b/agg/include/ctrl/agg_gamma_ctrl.h similarity index 98% rename from agg2/include/ctrl/agg_gamma_ctrl.h rename to agg/include/ctrl/agg_gamma_ctrl.h index 1f3d058..0a645a7 100644 --- a/agg2/include/ctrl/agg_gamma_ctrl.h +++ b/agg/include/ctrl/agg_gamma_ctrl.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. diff --git a/agg2/include/ctrl/agg_gamma_spline.h b/agg/include/ctrl/agg_gamma_spline.h similarity index 97% rename from agg2/include/ctrl/agg_gamma_spline.h rename to agg/include/ctrl/agg_gamma_spline.h index 28e735b..4f21710 100644 --- a/agg2/include/ctrl/agg_gamma_spline.h +++ b/agg/include/ctrl/agg_gamma_spline.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. diff --git a/agg/include/ctrl/agg_polygon_ctrl.h b/agg/include/ctrl/agg_polygon_ctrl.h new file mode 100644 index 0000000..9a1f389 --- /dev/null +++ b/agg/include/ctrl/agg_polygon_ctrl.h @@ -0,0 +1,166 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// classes polygon_ctrl_impl, polygon_ctrl +// +//---------------------------------------------------------------------------- + +#ifndef POLYGON_CTRL_INCLUDED +#define POLYGON_CTRL_INCLUDED + +#include "agg_array.h" +#include "agg_conv_stroke.h" +#include "agg_ellipse.h" +#include "agg_color_rgba.h" +#include "agg_ctrl.h" + +namespace agg +{ + class simple_polygon_vertex_source + { + public: + simple_polygon_vertex_source(const double* polygon, unsigned np, + bool roundoff = false, + bool close = true) : + m_polygon(polygon), + m_num_points(np), + m_vertex(0), + m_roundoff(roundoff), + m_close(close) + { + } + + void close(bool f) { m_close = f; } + bool close() const { return m_close; } + + void rewind(unsigned) + { + m_vertex = 0; + } + + unsigned vertex(double* x, double* y) + { + if(m_vertex > m_num_points) return path_cmd_stop; + if(m_vertex == m_num_points) + { + ++m_vertex; + return path_cmd_end_poly | (m_close ? path_flags_close : 0); + } + *x = m_polygon[m_vertex * 2]; + *y = m_polygon[m_vertex * 2 + 1]; + if(m_roundoff) + { + *x = floor(*x) + 0.5; + *y = floor(*y) + 0.5; + } + ++m_vertex; + return (m_vertex == 1) ? path_cmd_move_to : path_cmd_line_to; + } + + private: + const double* m_polygon; + unsigned m_num_points; + unsigned m_vertex; + bool m_roundoff; + bool m_close; + }; + + + + + class polygon_ctrl_impl : public ctrl + { + public: + polygon_ctrl_impl(unsigned np, double point_radius=5); + + unsigned num_points() const { return m_num_points; } + double xn(unsigned n) const { return m_polygon[n * 2]; } + double yn(unsigned n) const { return m_polygon[n * 2 + 1]; } + double& xn(unsigned n) { return m_polygon[n * 2]; } + double& yn(unsigned n) { return m_polygon[n * 2 + 1]; } + + const double* polygon() const { return &m_polygon[0]; } + + void line_width(double w) { m_stroke.width(w); } + double line_width() const { return m_stroke.width(); } + + void point_radius(double r) { m_point_radius = r; } + double point_radius() const { return m_point_radius; } + + void in_polygon_check(bool f) { m_in_polygon_check = f; } + bool in_polygon_check() const { return m_in_polygon_check; } + + void close(bool f) { m_vs.close(f); } + bool close() const { return m_vs.close(); } + + // Vertex source interface + unsigned num_paths() { return 1; } + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + + private: + bool check_edge(unsigned i, double x, double y) const; + bool point_in_polygon(double x, double y) const; + + pod_array m_polygon; + unsigned m_num_points; + int m_node; + int m_edge; + simple_polygon_vertex_source m_vs; + conv_stroke m_stroke; + ellipse m_ellipse; + double m_point_radius; + unsigned m_status; + double m_dx; + double m_dy; + bool m_in_polygon_check; + }; + + + + //----------------------------------------------------------polygon_ctrl + template class polygon_ctrl : public polygon_ctrl_impl + { + public: + polygon_ctrl(unsigned np, double point_radius=5) : + polygon_ctrl_impl(np, point_radius), + m_color(rgba(0.0, 0.0, 0.0)) + { + } + + void line_color(const ColorT& c) { m_color = c; } + const ColorT& color(unsigned) const { return m_color; } + + private: + polygon_ctrl(const polygon_ctrl&); + const polygon_ctrl& operator = (const polygon_ctrl&); + + ColorT m_color; + }; + + + + +} + +#endif + diff --git a/agg2/include/ctrl/agg_rbox_ctrl.h b/agg/include/ctrl/agg_rbox_ctrl.h similarity index 89% rename from agg2/include/ctrl/agg_rbox_ctrl.h rename to agg/include/ctrl/agg_rbox_ctrl.h index dce7f7b..4d47bcc 100644 --- a/agg2/include/ctrl/agg_rbox_ctrl.h +++ b/agg/include/ctrl/agg_rbox_ctrl.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -20,7 +20,7 @@ #ifndef AGG_RBOX_CTRL_INCLUDED #define AGG_RBOX_CTRL_INCLUDED -#include "agg_basics.h" +#include "agg_array.h" #include "agg_ellipse.h" #include "agg_conv_stroke.h" #include "agg_gsv_text.h" @@ -37,7 +37,6 @@ namespace agg class rbox_ctrl_impl : public ctrl { public: - ~rbox_ctrl_impl(); rbox_ctrl_impl(double x1, double y1, double x2, double y2, bool flip_y=false); void border_width(double t, double extra=0.0); @@ -56,20 +55,20 @@ namespace agg // Vertex soutce interface unsigned num_paths() { return 5; }; - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: void calc_rbox(); - double m_border_width; - double m_border_extra; - double m_text_thickness; - double m_text_height; - double m_text_width; - char* m_items[32]; - unsigned m_num_items; - int m_cur_item; + double m_border_width; + double m_border_extra; + double m_text_thickness; + double m_text_height; + double m_text_width; + pod_array m_items[32]; + unsigned m_num_items; + int m_cur_item; double m_xs1; double m_ys1; diff --git a/agg2/include/ctrl/agg_scale_ctrl.h b/agg/include/ctrl/agg_scale_ctrl.h similarity index 91% rename from agg2/include/ctrl/agg_scale_ctrl.h rename to agg/include/ctrl/agg_scale_ctrl.h index d9bbe2f..b1e32c2 100644 --- a/agg2/include/ctrl/agg_scale_ctrl.h +++ b/agg/include/ctrl/agg_scale_ctrl.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -46,15 +46,18 @@ namespace agg scale_ctrl_impl(double x1, double y1, double x2, double y2, bool flip_y=false); void border_thickness(double t, double extra=0.0); + void resize(double x1, double y1, double x2, double y2); double min_delta() const { return m_min_d; } void min_delta(double d) { m_min_d = d; } double value1() const { return m_value1; } - void value1(double value) { m_value1 = value; } + void value1(double value); double value2() const { return m_value2; } - void value2(double value) { m_value2 = value; } + void value2(double value); + + void move(double d); virtual bool in_rect(double x, double y) const; virtual bool on_mouse_button_down(double x, double y); @@ -64,7 +67,7 @@ namespace agg // Vertex soutce interface unsigned num_paths() { return 5; }; - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: @@ -80,6 +83,7 @@ namespace agg double m_xs2; double m_ys2; double m_pdx; + double m_pdy; move_e m_move_what; double m_vx[32]; double m_vy[32]; @@ -102,7 +106,7 @@ namespace agg m_background_color(rgba(1.0, 0.9, 0.8)), m_border_color(rgba(0.0, 0.0, 0.0)), m_pointers_color(rgba(0.8, 0.0, 0.0, 0.8)), - m_slider_color(rgba(0.2, 0.1, 0.0, 0.8)) + m_slider_color(rgba(0.2, 0.1, 0.0, 0.6)) { m_colors[0] = &m_background_color; m_colors[1] = &m_border_color; diff --git a/agg2/include/ctrl/agg_slider_ctrl.h b/agg/include/ctrl/agg_slider_ctrl.h similarity index 96% rename from agg2/include/ctrl/agg_slider_ctrl.h rename to agg/include/ctrl/agg_slider_ctrl.h index 4adfe4e..b50a95c 100644 --- a/agg2/include/ctrl/agg_slider_ctrl.h +++ b/agg/include/ctrl/agg_slider_ctrl.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -61,7 +61,7 @@ namespace agg // Vertex source interface unsigned num_paths() { return 6; }; - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: diff --git a/agg2/include/ctrl/agg_spline_ctrl.h b/agg/include/ctrl/agg_spline_ctrl.h similarity index 94% rename from agg2/include/ctrl/agg_spline_ctrl.h rename to agg/include/ctrl/agg_spline_ctrl.h index 01160df..8477f27 100644 --- a/agg2/include/ctrl/agg_spline_ctrl.h +++ b/agg/include/ctrl/agg_spline_ctrl.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -58,8 +58,8 @@ namespace agg void active_point(int i); - const double* spline() const { return m_spline_values; } - const unsigned char* spline8() const { return m_spline_values8; } + const double* spline() const { return m_spline_values; } + const int8u* spline8() const { return m_spline_values8; } double value(double x) const; void value(unsigned idx, double y); void point(unsigned idx, double x, double y); @@ -71,7 +71,7 @@ namespace agg // Vertex soutce interface unsigned num_paths() { return 5; } - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: @@ -87,7 +87,7 @@ namespace agg double m_yp[32]; bspline m_spline; double m_spline_values[256]; - unsigned char m_spline_values8[256]; + int8u m_spline_values8[256]; double m_border_width; double m_border_extra; double m_curve_width; diff --git a/agg/include/platform/Makefile.am b/agg/include/platform/Makefile.am new file mode 100644 index 0000000..0743d29 --- /dev/null +++ b/agg/include/platform/Makefile.am @@ -0,0 +1,4 @@ +EXTRA_DIST=win32/agg_win32_bmp.h \ + mac/agg_mac_pmap.h +myincludedir = $(includedir)/agg2/platform +myinclude_HEADERS = agg_platform_support.h diff --git a/agg2/include/platform/agg_platform_support.h b/agg/include/platform/agg_platform_support.h similarity index 86% rename from agg2/include/platform/agg_platform_support.h rename to agg/include/platform/agg_platform_support.h index 3de9351..722b009 100644 --- a/agg2/include/platform/agg_platform_support.h +++ b/agg/include/platform/agg_platform_support.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -18,7 +18,7 @@ // It's not a part of the AGG library, it's just a helper class to create // interactive demo examples. Since the examples should not be too complex // this class is provided to support some very basic interactive graphical -// funtionality, such as putting the rendered image to the window, simple +// functionality, such as putting the rendered image to the window, simple // keyboard and mouse input, window resizing, setting the window title, // and catching the "idle" events. // @@ -58,7 +58,7 @@ #include "agg_basics.h" #include "agg_rendering_buffer.h" -#include "agg_trans_affine.h" +#include "agg_trans_viewport.h" #include "ctrl/agg_ctrl.h" namespace agg @@ -73,7 +73,8 @@ namespace agg { window_resize = 1, window_hw_buffer = 2, - window_keep_aspect_ratio = 4 + window_keep_aspect_ratio = 4, + window_process_all_keys = 8 }; //-----------------------------------------------------------pix_format_e @@ -102,15 +103,41 @@ namespace agg enum pix_format_e { pix_format_undefined = 0, // By default. No conversions are applied + pix_format_bw, // 1 bit per color B/W pix_format_gray8, // Simple 256 level grayscale + pix_format_sgray8, // Simple 256 level grayscale (sRGB) + pix_format_gray16, // Simple 65535 level grayscale + pix_format_gray32, // Grayscale, one 32-bit float per pixel pix_format_rgb555, // 15 bit rgb. Depends on the byte ordering! pix_format_rgb565, // 16 bit rgb. Depends on the byte ordering! + pix_format_rgbAAA, // 30 bit rgb. Depends on the byte ordering! + pix_format_rgbBBA, // 32 bit rgb. Depends on the byte ordering! + pix_format_bgrAAA, // 30 bit bgr. Depends on the byte ordering! + pix_format_bgrABB, // 32 bit bgr. Depends on the byte ordering! pix_format_rgb24, // R-G-B, one byte per color component - pix_format_bgr24, // B-G-R, native win32 BMP format. + pix_format_srgb24, // R-G-B, one byte per color component (sRGB) + pix_format_bgr24, // B-G-R, one byte per color component + pix_format_sbgr24, // B-G-R, native win32 BMP format (sRGB) pix_format_rgba32, // R-G-B-A, one byte per color component + pix_format_srgba32, // R-G-B-A, one byte per color component (sRGB) pix_format_argb32, // A-R-G-B, native MAC format + pix_format_sargb32, // A-R-G-B, native MAC format (sRGB) pix_format_abgr32, // A-B-G-R, one byte per color component + pix_format_sabgr32, // A-B-G-R, one byte per color component (sRGB) pix_format_bgra32, // B-G-R-A, native win32 BMP format + pix_format_sbgra32, // B-G-R-A, native win32 BMP format (sRGB) + pix_format_rgb48, // R-G-B, 16 bits per color component + pix_format_bgr48, // B-G-R, native win32 BMP format. + pix_format_rgb96, // R-G-B, one 32-bit float per color component + pix_format_bgr96, // B-G-R, one 32-bit float per color component + pix_format_rgba64, // R-G-B-A, 16 bits byte per color component + pix_format_argb64, // A-R-G-B, native MAC format + pix_format_abgr64, // A-B-G-R, one byte per color component + pix_format_bgra64, // B-G-R-A, native win32 BMP format + pix_format_rgba128, // R-G-B-A, one 32-bit float per color component + pix_format_argb128, // A-R-G-B, one 32-bit float per color component + pix_format_abgr128, // A-B-G-R, one 32-bit float per color component + pix_format_bgra128, // B-G-R-A, one 32-bit float per color component end_of_pix_formats }; @@ -143,9 +170,9 @@ namespace agg // probably supported on different platforms. Any platform dependent codes // should be converted into these ones. There're only those codes are // defined that cannot be represented as printable ASCII-characters. - // All printable ASCII-set can be used in a regilar C/C++ manner: + // All printable ASCII-set can be used in a regular C/C++ manner: // ' ', 'A', '0' '+' and so on. - // Since the clasas is used for creating very simple demo-applications + // Since the class is used for creating very simple demo-applications // we don't need very rich possibilities here, just basic ones. // Actually the numeric key codes are taken from the SDL library, so, // the implementation of the SDL support does not require any mapping. @@ -224,7 +251,7 @@ namespace agg //------------------------------------------------------------------------ // A predeclaration of the platform dependent class. Since we do not // know anything here the only we can have is just a pointer to this - // class as a data member. It should be created and destroyed explicitely + // class as a data member. It should be created and destroyed explicitly // in the constructor/destructor of the platform_support class. // Although the pointer to platform_specific is public the application // cannot have access to its members or methods since it does not know @@ -236,10 +263,10 @@ namespace agg // A helper class that contains pointers to a number of controls. // This class is used to ease the event handling with controls. // The implementation should simply call the appropriate methods - // of this class when appropriate events occure. + // of this class when appropriate events occur. class ctrl_container { - enum { max_ctrl = 64 }; + enum max_ctrl_e { max_ctrl = 64 }; public: //-------------------------------------------------------------------- @@ -396,7 +423,7 @@ namespace agg class platform_support { public: - enum { max_images = 16 }; + enum max_images_e { max_images = 16 }; // format - see enum pix_format_e {}; // flip_y - true if you want to have the Y-axis flipped vertically. @@ -410,7 +437,7 @@ namespace agg const char* caption() const { return m_caption; } //-------------------------------------------------------------------- - // These 3 menthods handle working with images. The image + // These 3 methods handle working with images. The image // formats are the simplest ones, such as .BMP in Windows or // .ppm in Linux. In the applications the names of the files // should not have any file extensions. Method load_img() can @@ -441,11 +468,11 @@ namespace agg //-------------------------------------------------------------------- // The following provides a very simple mechanism of doing someting - // in background. It's not multitheading. When whait_mode is true + // in background. It's not multithreading. When wait_mode is true // the class waits for the events and it does not ever call on_idle(). // When it's false it calls on_idle() when the event queue is empty. // The mode can be changed anytime. This mechanism is satisfactory - // for creation very simple animations. + // to create very simple animations. bool wait_mode() const { return m_wait_mode; } void wait_mode(bool wait_mode) { m_wait_mode = wait_mode; } @@ -475,7 +502,7 @@ namespace agg //-------------------------------------------------------------------- - // Returns file extension used in the implemenation for the particular + // Returns file extension used in the implementation for the particular // system. const char* img_ext() const; @@ -518,7 +545,7 @@ namespace agg // In my demo applications these functions are defined inside // the the_application class (implicit inlining) which is in general // very bad practice, I mean vitual inline methods. At least it does - // not make sence. + // not make sense. // But in this case it's quite appropriate bacause we have the only // instance of the the_application class and it is in the same file // where this class is defined. @@ -562,10 +589,15 @@ namespace agg { if(m_window_flags & window_keep_aspect_ratio) { - double sx = double(width) / double(m_initial_width); - double sy = double(height) / double(m_initial_height); - if(sy < sx) sx = sy; - m_resize_mtx = trans_affine_scaling(sx, sx); + //double sx = double(width) / double(m_initial_width); + //double sy = double(height) / double(m_initial_height); + //if(sy < sx) sx = sy; + //m_resize_mtx = trans_affine_scaling(sx, sx); + trans_viewport vp; + vp.preserve_aspect_ratio(0.5, 0.5, aspect_ratio_meet); + vp.device_viewport(0, 0, width, height); + vp.world_viewport(0, 0, m_initial_width, m_initial_height); + m_resize_mtx = vp.to_affine(); } else { @@ -574,11 +606,13 @@ namespace agg double(height) / double(m_initial_height)); } } - const trans_affine& trans_affine_resizing() const { return m_resize_mtx; } - double width() const { return m_rbuf_window.width(); } - double height() const { return m_rbuf_window.height(); } - double initial_width() const { return m_initial_width; } - double initial_height() const { return m_initial_height; } + trans_affine& trans_affine_resizing() { return m_resize_mtx; } + const trans_affine& trans_affine_resizing() const { return m_resize_mtx; } + double width() const { return m_rbuf_window.width(); } + double height() const { return m_rbuf_window.height(); } + double initial_width() const { return m_initial_width; } + double initial_height() const { return m_initial_height; } + unsigned window_flags() const { return m_window_flags; } //-------------------------------------------------------------------- // Get raw display handler depending on the system. @@ -610,7 +644,7 @@ namespace agg // open it in the current directory. The demos usually expect // all the supplementary files to be placed in the current // directory, that is usually coincides with the directory where - // the the executable is. However, in some systems (BeOS) it's not so. + // the executable is. However, in some systems (BeOS) it's not so. // For those kinds of systems full_file_name() can help access files // preserving commonly used policy. // So, it's a good idea to use in the demos the following: @@ -623,7 +657,7 @@ namespace agg platform_specific* m_specific; ctrl_container m_ctrls; - // Sorry, I'm too tired to descibe the private + // Sorry, I'm too tired to describe the private // data membders. See the implementations for different // platforms for details. private: diff --git a/agg2/include/platform/mac/agg_mac_pmap.h b/agg/include/platform/mac/agg_mac_pmap.h similarity index 96% rename from agg2/include/platform/mac/agg_mac_pmap.h rename to agg/include/platform/mac/agg_mac_pmap.h index 82e20d9..c71091d 100644 --- a/agg2/include/platform/mac/agg_mac_pmap.h +++ b/agg/include/platform/mac/agg_mac_pmap.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.0 -// Copyright (C) 2002 Maxim Shemanarev (McSeem) +// Anti-Grain Geometry - Version 2.4 +// Copyright (C) 2002-2005 Maxim Shemanarev (McSeem) // Copyright (C) 2002 Hansruedi Baer (MacOS support) // // Permission to copy, use, modify, sell and distribute this software @@ -22,7 +22,6 @@ #define AGG_MAC_PMAP_INCLUDED -#include #include diff --git a/agg2/include/platform/win32/agg_win32_bmp.h b/agg/include/platform/win32/agg_win32_bmp.h similarity index 82% rename from agg2/include/platform/win32/agg_win32_bmp.h rename to agg/include/platform/win32/agg_win32_bmp.h index 7980015..961a44d 100644 --- a/agg2/include/platform/win32/agg_win32_bmp.h +++ b/agg/include/platform/win32/agg_win32_bmp.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -21,7 +21,6 @@ #include -#include namespace agg @@ -31,7 +30,9 @@ namespace agg org_mono8 = 8, org_color16 = 16, org_color24 = 24, - org_color32 = 32 + org_color32 = 32, + org_color48 = 48, + org_color64 = 64 }; class pixel_map @@ -46,6 +47,11 @@ namespace agg unsigned height, org_e org, unsigned clear_val=256); + HBITMAP create_dib_section(HDC h_dc, + unsigned width, + unsigned height, + org_e org, + unsigned clear_val=256); void clear(unsigned clear_val=256); void attach_to_bmp(BITMAPINFO* bmp); @@ -89,6 +95,11 @@ namespace agg pixel_map(const pixel_map&); const pixel_map& operator = (const pixel_map&); void create_from_bmp(BITMAPINFO *bmp); + + HBITMAP create_dib_section_from_args(HDC h_dc, + unsigned width, + unsigned height, + unsigned bits_per_pixel); private: BITMAPINFO* m_bmp; diff --git a/agg/include/util/Makefile.am b/agg/include/util/Makefile.am new file mode 100644 index 0000000..e197c3d --- /dev/null +++ b/agg/include/util/Makefile.am @@ -0,0 +1,2 @@ +myincludedir = $(includedir)/agg2/util +myinclude_HEADERS = agg_color_conv.h agg_color_conv_rgb8.h agg_color_conv_rgb16.h diff --git a/agg/include/util/agg_color_conv.h b/agg/include/util/agg_color_conv.h new file mode 100644 index 0000000..9f38b3b --- /dev/null +++ b/agg/include/util/agg_color_conv.h @@ -0,0 +1,128 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Conversion from one colorspace/pixel format to another +// +//---------------------------------------------------------------------------- + +#ifndef AGG_COLOR_CONV_INCLUDED +#define AGG_COLOR_CONV_INCLUDED + +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" + + + + +namespace agg +{ + + //--------------------------------------------------------------color_conv + template + void color_conv(RenBuf* dst, const RenBuf* src, CopyRow copy_row_functor) + { + unsigned width = src->width(); + unsigned height = src->height(); + + if(dst->width() < width) width = dst->width(); + if(dst->height() < height) height = dst->height(); + + if(width) + { + unsigned y; + for(y = 0; y < height; y++) + { + copy_row_functor(dst->row_ptr(0, y, width), + src->row_ptr(y), + width); + } + } + } + + + //---------------------------------------------------------color_conv_row + template + void color_conv_row(int8u* dst, + const int8u* src, + unsigned width, + CopyRow copy_row_functor) + { + copy_row_functor(dst, src, width); + } + + + //---------------------------------------------------------color_conv_same + template class color_conv_same + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + std::memmove(dst, src, width*BPP); + } + }; + + + // Generic pixel converter. + template + struct conv_pixel + { + void operator()(void* dst, const void* src) const + { + // Read a pixel from the source format and write it to the destination format. + DstFormat::write_plain_color(dst, SrcFormat::read_plain_color(src)); + } + }; + + // Generic row converter. Uses conv_pixel to convert individual pixels. + template + struct conv_row + { + void operator()(void* dst, const void* src, unsigned width) const + { + conv_pixel conv; + do + { + conv(dst, src); + dst = (int8u*)dst + DstFormat::pix_width; + src = (int8u*)src + SrcFormat::pix_width; + } + while (--width); + } + }; + + // Specialization for case where source and destination formats are identical. + template + struct conv_row + { + void operator()(void* dst, const void* src, unsigned width) const + { + std::memmove(dst, src, width * Format::pix_width); + } + }; + + // Top-level conversion function, converts one pixel format to any other. + template + void convert(RenBuf* dst, const RenBuf* src) + { + color_conv(dst, src, conv_row()); + } +} + + + +#endif diff --git a/agg/include/util/agg_color_conv_rgb16.h b/agg/include/util/agg_color_conv_rgb16.h new file mode 100644 index 0000000..aaa4132 --- /dev/null +++ b/agg/include/util/agg_color_conv_rgb16.h @@ -0,0 +1,285 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// This part of the library 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. +// +//---------------------------------------------------------------------------- +// +// A set of functors used with color_conv(). See file agg_color_conv.h +// These functors can convert images with up to 8 bits per component. +// Use convertors in the following way: +// +// agg::color_conv(dst, src, agg::color_conv_XXXX_to_YYYY()); +//---------------------------------------------------------------------------- + +#ifndef AGG_COLOR_CONV_RGB16_INCLUDED +#define AGG_COLOR_CONV_RGB16_INCLUDED + +#include "agg_basics.h" +#include "agg_color_conv.h" + +namespace agg +{ + + //-------------------------------------------------color_conv_gray16_to_gray8 + class color_conv_gray16_to_gray8 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + int16u* s = (int16u*)src; + do + { + *dst++ = *s++ >> 8; + } + while(--width); + } + }; + + + //-----------------------------------------------------color_conv_rgb24_rgb48 + template class color_conv_rgb24_rgb48 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + int16u* d = (int16u*)dst; + do + { + *d++ = (src[I1] << 8) | src[I1]; + *d++ = (src[1] << 8) | src[1] ; + *d++ = (src[I3] << 8) | src[I3]; + src += 3; + } + while(--width); + } + }; + + typedef color_conv_rgb24_rgb48<0,2> color_conv_rgb24_to_rgb48; + typedef color_conv_rgb24_rgb48<0,2> color_conv_bgr24_to_bgr48; + typedef color_conv_rgb24_rgb48<2,0> color_conv_rgb24_to_bgr48; + typedef color_conv_rgb24_rgb48<2,0> color_conv_bgr24_to_rgb48; + + + //-----------------------------------------------------color_conv_rgb24_rgb48 + template class color_conv_rgb48_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + const int16u* s = (const int16u*)src; + do + { + *dst++ = s[I1] >> 8; + *dst++ = s[1] >> 8; + *dst++ = s[I3] >> 8; + s += 3; + } + while(--width); + } + }; + + typedef color_conv_rgb48_rgb24<0,2> color_conv_rgb48_to_rgb24; + typedef color_conv_rgb48_rgb24<0,2> color_conv_bgr48_to_bgr24; + typedef color_conv_rgb48_rgb24<2,0> color_conv_rgb48_to_bgr24; + typedef color_conv_rgb48_rgb24<2,0> color_conv_bgr48_to_rgb24; + + + //----------------------------------------------color_conv_rgbAAA_rgb24 + template class color_conv_rgbAAA_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + int32u rgb = *(int32u*)src; + dst[R] = int8u(rgb >> 22); + dst[1] = int8u(rgb >> 12); + dst[B] = int8u(rgb >> 2); + src += 4; + dst += 3; + } + while(--width); + } + }; + + typedef color_conv_rgbAAA_rgb24<0,2> color_conv_rgbAAA_to_rgb24; + typedef color_conv_rgbAAA_rgb24<2,0> color_conv_rgbAAA_to_bgr24; + typedef color_conv_rgbAAA_rgb24<2,0> color_conv_bgrAAA_to_rgb24; + typedef color_conv_rgbAAA_rgb24<0,2> color_conv_bgrAAA_to_bgr24; + + + //----------------------------------------------color_conv_rgbBBA_rgb24 + template class color_conv_rgbBBA_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + int32u rgb = *(int32u*)src; + dst[R] = int8u(rgb >> 24); + dst[1] = int8u(rgb >> 13); + dst[B] = int8u(rgb >> 2); + src += 4; + dst += 3; + } + while(--width); + } + }; + + typedef color_conv_rgbBBA_rgb24<0,2> color_conv_rgbBBA_to_rgb24; + typedef color_conv_rgbBBA_rgb24<2,0> color_conv_rgbBBA_to_bgr24; + + + //----------------------------------------------color_conv_bgrABB_rgb24 + template class color_conv_bgrABB_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + int32u bgr = *(int32u*)src; + dst[R] = int8u(bgr >> 3); + dst[1] = int8u(bgr >> 14); + dst[B] = int8u(bgr >> 24); + src += 4; + dst += 3; + } + while(--width); + } + }; + + typedef color_conv_bgrABB_rgb24<2,0> color_conv_bgrABB_to_rgb24; + typedef color_conv_bgrABB_rgb24<0,2> color_conv_bgrABB_to_bgr24; + + + //-------------------------------------------------color_conv_rgba64_rgba32 + template class color_conv_rgba64_rgba32 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + *dst++ = int8u(((int16u*)src)[I1] >> 8); + *dst++ = int8u(((int16u*)src)[I2] >> 8); + *dst++ = int8u(((int16u*)src)[I3] >> 8); + *dst++ = int8u(((int16u*)src)[I4] >> 8); + src += 8; + } + while(--width); + } + }; + + //------------------------------------------------------------------------ + typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_rgba64_to_rgba32; //----color_conv_rgba64_to_rgba32 + typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_argb64_to_argb32; //----color_conv_argb64_to_argb32 + typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_bgra64_to_bgra32; //----color_conv_bgra64_to_bgra32 + typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_abgr64_to_abgr32; //----color_conv_abgr64_to_abgr32 + typedef color_conv_rgba64_rgba32<0,3,2,1> color_conv_argb64_to_abgr32; //----color_conv_argb64_to_abgr32 + typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_argb64_to_bgra32; //----color_conv_argb64_to_bgra32 + typedef color_conv_rgba64_rgba32<1,2,3,0> color_conv_argb64_to_rgba32; //----color_conv_argb64_to_rgba32 + typedef color_conv_rgba64_rgba32<3,0,1,2> color_conv_bgra64_to_abgr32; //----color_conv_bgra64_to_abgr32 + typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_bgra64_to_argb32; //----color_conv_bgra64_to_argb32 + typedef color_conv_rgba64_rgba32<2,1,0,3> color_conv_bgra64_to_rgba32; //----color_conv_bgra64_to_rgba32 + typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_rgba64_to_abgr32; //----color_conv_rgba64_to_abgr32 + typedef color_conv_rgba64_rgba32<3,0,1,2> color_conv_rgba64_to_argb32; //----color_conv_rgba64_to_argb32 + typedef color_conv_rgba64_rgba32<2,1,0,3> color_conv_rgba64_to_bgra32; //----color_conv_rgba64_to_bgra32 + typedef color_conv_rgba64_rgba32<0,3,2,1> color_conv_abgr64_to_argb32; //----color_conv_abgr64_to_argb32 + typedef color_conv_rgba64_rgba32<1,2,3,0> color_conv_abgr64_to_bgra32; //----color_conv_abgr64_to_bgra32 + typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_abgr64_to_rgba32; //----color_conv_abgr64_to_rgba32 + + + + //--------------------------------------------color_conv_rgb24_rgba64 + template class color_conv_rgb24_rgba64 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + int16u* d = (int16u*)dst; + do + { + d[I1] = (src[0] << 8) | src[0]; + d[I2] = (src[1] << 8) | src[1]; + d[I3] = (src[2] << 8) | src[2]; + d[A] = 65535; + d += 4; + src += 3; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgb24_rgba64<1,2,3,0> color_conv_rgb24_to_argb64; //----color_conv_rgb24_to_argb64 + typedef color_conv_rgb24_rgba64<3,2,1,0> color_conv_rgb24_to_abgr64; //----color_conv_rgb24_to_abgr64 + typedef color_conv_rgb24_rgba64<2,1,0,3> color_conv_rgb24_to_bgra64; //----color_conv_rgb24_to_bgra64 + typedef color_conv_rgb24_rgba64<0,1,2,3> color_conv_rgb24_to_rgba64; //----color_conv_rgb24_to_rgba64 + typedef color_conv_rgb24_rgba64<3,2,1,0> color_conv_bgr24_to_argb64; //----color_conv_bgr24_to_argb64 + typedef color_conv_rgb24_rgba64<1,2,3,0> color_conv_bgr24_to_abgr64; //----color_conv_bgr24_to_abgr64 + typedef color_conv_rgb24_rgba64<0,1,2,3> color_conv_bgr24_to_bgra64; //----color_conv_bgr24_to_bgra64 + typedef color_conv_rgb24_rgba64<2,1,0,3> color_conv_bgr24_to_rgba64; //----color_conv_bgr24_to_rgba64 + + + template class color_conv_rgb24_gray16 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + int16u* d = (int16u*)dst; + do + { + *d++ = src[R]*77 + src[1]*150 + src[B]*29; + src += 3; + } + while(--width); + } + }; + + typedef color_conv_rgb24_gray16<0,2> color_conv_rgb24_to_gray16; + typedef color_conv_rgb24_gray16<2,0> color_conv_bgr24_to_gray16; + + +} + + +#endif diff --git a/agg2/include/util/agg_color_conv_rgb8.h b/agg/include/util/agg_color_conv_rgb8.h similarity index 86% rename from agg2/include/util/agg_color_conv_rgb8.h rename to agg/include/util/agg_color_conv_rgb8.h index fdf9cf4..609460d 100644 --- a/agg2/include/util/agg_color_conv_rgb8.h +++ b/agg/include/util/agg_color_conv_rgb8.h @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -42,16 +42,19 @@ namespace agg class color_conv_rgb24 { public: - void operator () (unsigned char* dst, - const unsigned char* src, + void operator () (int8u* dst, + const int8u* src, unsigned width) const { do { - *dst++ = src[2]; - *dst++ = src[1]; - *dst++ = src[0]; - src += 3; + int8u tmp[3]; + tmp[0] = *src++; + tmp[1] = *src++; + tmp[2] = *src++; + *dst++ = tmp[2]; + *dst++ = tmp[1]; + *dst++ = tmp[0]; } while(--width); } @@ -69,17 +72,21 @@ namespace agg template class color_conv_rgba32 { public: - void operator () (unsigned char* dst, - const unsigned char* src, + void operator () (int8u* dst, + const int8u* src, unsigned width) const { do { - *dst++ = src[I1]; - *dst++ = src[I2]; - *dst++ = src[I3]; - *dst++ = src[I4]; - src += 4; + int8u tmp[4]; + tmp[0] = *src++; + tmp[1] = *src++; + tmp[2] = *src++; + tmp[3] = *src++; + *dst++ = tmp[I1]; + *dst++ = tmp[I2]; + *dst++ = tmp[I3]; + *dst++ = tmp[I4]; } while(--width); } @@ -111,8 +118,8 @@ namespace agg template class color_conv_rgb24_rgba32 { public: - void operator () (unsigned char* dst, - const unsigned char* src, + void operator () (int8u* dst, + const int8u* src, unsigned width) const { do @@ -144,8 +151,8 @@ namespace agg template class color_conv_rgba32_rgb24 { public: - void operator () (unsigned char* dst, - const unsigned char* src, + void operator () (int8u* dst, + const int8u* src, unsigned width) const { do @@ -176,16 +183,16 @@ namespace agg template class color_conv_rgb555_rgb24 { public: - void operator () (unsigned char* dst, - const unsigned char* src, + void operator () (int8u* dst, + const int8u* src, unsigned width) const { do { unsigned rgb = *(int16u*)src; - dst[R] = (unsigned char)((rgb >> 7) & 0xF8); - dst[1] = (unsigned char)((rgb >> 2) & 0xF8); - dst[B] = (unsigned char)((rgb << 3) & 0xF8); + dst[R] = (int8u)((rgb >> 7) & 0xF8); + dst[1] = (int8u)((rgb >> 2) & 0xF8); + dst[B] = (int8u)((rgb << 3) & 0xF8); src += 2; dst += 3; } @@ -203,8 +210,8 @@ namespace agg template class color_conv_rgb24_rgb555 { public: - void operator () (unsigned char* dst, - const unsigned char* src, + void operator () (int8u* dst, + const int8u* src, unsigned width) const { do @@ -229,8 +236,8 @@ namespace agg template class color_conv_rgb565_rgb24 { public: - void operator () (unsigned char* dst, - const unsigned char* src, + void operator () (int8u* dst, + const int8u* src, unsigned width) const { do @@ -256,8 +263,8 @@ namespace agg template class color_conv_rgb24_rgb565 { public: - void operator () (unsigned char* dst, - const unsigned char* src, + void operator () (int8u* dst, + const int8u* src, unsigned width) const { do @@ -283,8 +290,8 @@ namespace agg template class color_conv_rgb555_rgba32 { public: - void operator () (unsigned char* dst, - const unsigned char* src, + void operator () (int8u* dst, + const int8u* src, unsigned width) const { do @@ -313,8 +320,8 @@ namespace agg template class color_conv_rgba32_rgb555 { public: - void operator () (unsigned char* dst, - const unsigned char* src, + void operator () (int8u* dst, + const int8u* src, unsigned width) const { do @@ -343,8 +350,8 @@ namespace agg template class color_conv_rgb565_rgba32 { public: - void operator () (unsigned char* dst, - const unsigned char* src, + void operator () (int8u* dst, + const int8u* src, unsigned width) const { do @@ -373,8 +380,8 @@ namespace agg template class color_conv_rgba32_rgb565 { public: - void operator () (unsigned char* dst, - const unsigned char* src, + void operator () (int8u* dst, + const int8u* src, unsigned width) const { do @@ -401,8 +408,8 @@ namespace agg class color_conv_rgb555_to_rgb565 { public: - void operator () (unsigned char* dst, - const unsigned char* src, + void operator () (int8u* dst, + const int8u* src, unsigned width) const { do @@ -421,8 +428,8 @@ namespace agg class color_conv_rgb565_to_rgb555 { public: - void operator () (unsigned char* dst, - const unsigned char* src, + void operator () (int8u* dst, + const int8u* src, unsigned width) const { do @@ -440,7 +447,27 @@ namespace agg //------------------------------------------------------------------------ typedef color_conv_same<2> color_conv_rgb555_to_rgb555; //----color_conv_rgb555_to_rgb555 typedef color_conv_same<2> color_conv_rgb565_to_rgb565; //----color_conv_rgb565_to_rgb565 + + template class color_conv_rgb24_gray8 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + *dst++ = (src[R]*77 + src[1]*150 + src[B]*29) >> 8; + src += 3; + } + while(--width); + } + }; + + typedef color_conv_rgb24_gray8<0,2> color_conv_rgb24_to_gray8; //----color_conv_rgb24_to_gray8 + typedef color_conv_rgb24_gray8<2,0> color_conv_bgr24_to_gray8; //----color_conv_bgr24_to_gray8 + } diff --git a/agg2/src/agg_arc.cpp b/agg/src/agg_arc.cpp similarity index 85% rename from agg2/src/agg_arc.cpp rename to agg/src/agg_arc.cpp index a6f32a5..4262aab 100644 --- a/agg2/src/agg_arc.cpp +++ b/agg/src/agg_arc.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -17,7 +17,7 @@ // //---------------------------------------------------------------------------- -#include +#include #include "agg_arc.h" @@ -65,16 +65,16 @@ namespace agg unsigned arc::vertex(double* x, double* y) { if(is_stop(m_path_cmd)) return path_cmd_stop; - if((m_angle < m_end) != m_ccw) + if((m_angle < m_end - m_da/4) != m_ccw) { - *x = m_x + cos(m_end) * m_rx; - *y = m_y + sin(m_end) * m_ry; + *x = m_x + std::cos(m_end) * m_rx; + *y = m_y + std::sin(m_end) * m_ry; m_path_cmd = path_cmd_stop; return path_cmd_line_to; } - *x = m_x + cos(m_angle) * m_rx; - *y = m_y + sin(m_angle) * m_ry; + *x = m_x + std::cos(m_angle) * m_rx; + *y = m_y + std::sin(m_angle) * m_ry; m_angle += m_da; @@ -86,7 +86,8 @@ namespace agg //------------------------------------------------------------------------ void arc::normalize(double a1, double a2, bool ccw) { - m_da = fabs(1.0 / ((m_rx + m_ry) * 0.5 * m_scale)); + double ra = (std::fabs(m_rx) + std::fabs(m_ry)) / 2; + m_da = std::acos(ra / (ra + 0.125 / m_scale)) * 2; if(ccw) { while(a2 < a1) a2 += pi * 2.0; diff --git a/agg2/src/agg_arrowhead.cpp b/agg/src/agg_arrowhead.cpp similarity index 93% rename from agg2/src/agg_arrowhead.cpp rename to agg/src/agg_arrowhead.cpp index 7b731bd..1a6f8b4 100644 --- a/agg2/src/agg_arrowhead.cpp +++ b/agg/src/agg_arrowhead.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -42,11 +42,11 @@ namespace agg //------------------------------------------------------------------------ - void arrowhead::rewind(unsigned id) + void arrowhead::rewind(unsigned path_id) { - m_curr_id = id; + m_curr_id = path_id; m_curr_coord = 0; - if(id == 0) + if(path_id == 0) { if(!m_tail_flag) { @@ -71,7 +71,7 @@ namespace agg return; } - if(id == 1) + if(path_id == 1) { if(!m_head_flag) { diff --git a/agg2/src/agg_bezier_arc.cpp b/agg/src/agg_bezier_arc.cpp similarity index 75% rename from agg2/src/agg_bezier_arc.cpp rename to agg/src/agg_bezier_arc.cpp index 4a996aa..4bcd9d8 100644 --- a/agg2/src/agg_bezier_arc.cpp +++ b/agg/src/agg_bezier_arc.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -19,20 +19,28 @@ //---------------------------------------------------------------------------- -#include +#include #include "agg_bezier_arc.h" namespace agg { + // This epsilon is used to prevent us from adding degenerate curves + // (converging to a single point). + // The value isn't very critical. Function arc_to_bezier() has a limit + // of the sweep_angle. If fabs(sweep_angle) exceeds pi/2 the curve + // becomes inaccurate. But slight exceeding is quite appropriate. + //-------------------------------------------------bezier_arc_angle_epsilon + const double bezier_arc_angle_epsilon = 0.01; + //------------------------------------------------------------arc_to_bezier void arc_to_bezier(double cx, double cy, double rx, double ry, double start_angle, double sweep_angle, double* curve) { - double x0 = cos(sweep_angle / 2.0); - double y0 = sin(sweep_angle / 2.0); + double x0 = std::cos(sweep_angle / 2.0); + double y0 = std::sin(sweep_angle / 2.0); double tx = (1.0 - x0) * 4.0 / 3.0; double ty = y0 - tx * x0 / y0; double px[4]; @@ -46,8 +54,8 @@ namespace agg px[3] = x0; py[3] = y0; - double sn = sin(start_angle + sweep_angle / 2.0); - double cs = cos(start_angle + sweep_angle / 2.0); + double sn = std::sin(start_angle + sweep_angle / 2.0); + double cs = std::cos(start_angle + sweep_angle / 2.0); unsigned i; for(i = 0; i < 4; i++) @@ -65,33 +73,48 @@ namespace agg double start_angle, double sweep_angle) { - start_angle = fmod(start_angle, 2.0 * pi); + start_angle = std::fmod(start_angle, 2.0 * pi); if(sweep_angle >= 2.0 * pi) sweep_angle = 2.0 * pi; if(sweep_angle <= -2.0 * pi) sweep_angle = -2.0 * pi; + if(std::fabs(sweep_angle) < 1e-10) + { + m_num_vertices = 4; + m_cmd = path_cmd_line_to; + m_vertices[0] = x + rx * std::cos(start_angle); + m_vertices[1] = y + ry * std::sin(start_angle); + m_vertices[2] = x + rx * std::cos(start_angle + sweep_angle); + m_vertices[3] = y + ry * std::sin(start_angle + sweep_angle); + return; + } + double total_sweep = 0.0; double local_sweep = 0.0; + double prev_sweep; m_num_vertices = 2; + m_cmd = path_cmd_curve4; bool done = false; do { if(sweep_angle < 0.0) { + prev_sweep = total_sweep; local_sweep = -pi * 0.5; total_sweep -= pi * 0.5; - if(total_sweep <= sweep_angle) + if(total_sweep <= sweep_angle + bezier_arc_angle_epsilon) { - local_sweep = sweep_angle - (total_sweep + pi * 0.5); + local_sweep = sweep_angle - prev_sweep; done = true; } } else { + prev_sweep = total_sweep; local_sweep = pi * 0.5; total_sweep += pi * 0.5; - if(total_sweep >= sweep_angle) + if(total_sweep >= sweep_angle - bezier_arc_angle_epsilon) { - local_sweep = sweep_angle - (total_sweep - pi * 0.5); + local_sweep = sweep_angle - prev_sweep; done = true; } } @@ -129,10 +152,8 @@ namespace agg double dx2 = (x0 - x2) / 2.0; double dy2 = (y0 - y2) / 2.0; - // Convert angle from degrees to radians - //------------------------ - double cos_a = cos(angle); - double sin_a = sin(angle); + double cos_a = std::cos(angle); + double sin_a = std::sin(angle); // Calculate (x1, y1) //------------------------ @@ -151,8 +172,8 @@ namespace agg double radii_check = px1/prx + py1/pry; if(radii_check > 1.0) { - rx = sqrt(radii_check) * rx; - ry = sqrt(radii_check) * ry; + rx = std::sqrt(radii_check) * rx; + ry = std::sqrt(radii_check) * ry; prx = rx * rx; pry = ry * ry; if(radii_check > 10.0) m_radii_ok = false; @@ -162,7 +183,7 @@ namespace agg //------------------------ double sign = (large_arc_flag == sweep_flag) ? -1.0 : 1.0; double sq = (prx*pry - prx*py1 - pry*px1) / (prx*py1 + pry*px1); - double coef = sign * sqrt((sq < 0) ? 0 : sq); + double coef = sign * std::sqrt((sq < 0) ? 0 : sq); double cx1 = coef * ((rx * y1) / ry); double cy1 = coef * -((ry * x1) / rx); @@ -184,23 +205,23 @@ namespace agg // Calculate the angle start //------------------------ - n = sqrt(ux*ux + uy*uy); + n = std::sqrt(ux*ux + uy*uy); p = ux; // (1 * ux) + (0 * uy) sign = (uy < 0) ? -1.0 : 1.0; double v = p / n; if(v < -1.0) v = -1.0; if(v > 1.0) v = 1.0; - double start_angle = sign * acos(v); + double start_angle = sign * std::acos(v); // Calculate the sweep angle //------------------------ - n = sqrt((ux*ux + uy*uy) * (vx*vx + vy*vy)); + n = std::sqrt((ux*ux + uy*uy) * (vx*vx + vy*vy)); p = ux * vx + uy * vy; sign = (ux * vy - uy * vx < 0) ? -1.0 : 1.0; v = p / n; if(v < -1.0) v = -1.0; if(v > 1.0) v = 1.0; - double sweep_angle = sign * acos(v); + double sweep_angle = sign * std::acos(v); if(!sweep_flag && sweep_angle > 0) { sweep_angle -= pi * 2.0; diff --git a/agg2/src/agg_bspline.cpp b/agg/src/agg_bspline.cpp similarity index 93% rename from agg2/src/agg_bspline.cpp rename to agg/src/agg_bspline.cpp index 6bd67d2..e1fda9f 100644 --- a/agg2/src/agg_bspline.cpp +++ b/agg/src/agg_bspline.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -17,26 +17,16 @@ // //---------------------------------------------------------------------------- - #include "agg_bspline.h" namespace agg { - - //------------------------------------------------------------------------ - bspline::~bspline() - { - delete [] m_am; - } - - //------------------------------------------------------------------------ bspline::bspline() : m_max(0), m_num(0), m_x(0), m_y(0), - m_am(0), m_last_idx(-1) { } @@ -47,7 +37,6 @@ namespace agg m_num(0), m_x(0), m_y(0), - m_am(0), m_last_idx(-1) { init(num); @@ -59,7 +48,6 @@ namespace agg m_num(0), m_x(0), m_y(0), - m_am(0), m_last_idx(-1) { init(num, x, y); @@ -71,11 +59,10 @@ namespace agg { if(max > 2 && max > m_max) { - delete [] m_am; - m_am = new double[max * 3]; + m_am.resize(max * 3); m_max = max; - m_x = m_am + m_max; - m_y = m_am + m_max * 2; + m_x = &m_am[m_max]; + m_y = &m_am[m_max * 2]; } m_num = 0; m_last_idx = -1; @@ -103,7 +90,6 @@ namespace agg double* temp; double* r; double* s; - double* al; double h, p, d, f, e; for(k = 0; k < m_num; k++) @@ -113,8 +99,8 @@ namespace agg n1 = 3 * m_num; - al = new double[n1]; - temp = al; + pod_array al(n1); + temp = &al[0]; for(k = 0; k < n1; k++) { @@ -155,7 +141,6 @@ namespace agg al[k] = al[k] * al[k + 1] + s[k]; m_am[k] = al[k]; } - delete al; } m_last_idx = -1; } diff --git a/agg/src/agg_color_rgba.cpp b/agg/src/agg_color_rgba.cpp new file mode 100644 index 0000000..9fe1534 --- /dev/null +++ b/agg/src/agg_color_rgba.cpp @@ -0,0 +1,17 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.4 +// Copyright (C) 2009 John Horigan (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// +// Contact: john@glyphic.com.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +// rgbaN construction from grayN types is no longer required, +// as grayN types now define their own conversions to rgbaN. diff --git a/agg/src/agg_curves.cpp b/agg/src/agg_curves.cpp new file mode 100644 index 0000000..a08fcb9 --- /dev/null +++ b/agg/src/agg_curves.cpp @@ -0,0 +1,613 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#include +#include "agg_curves.h" +#include "agg_math.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + const double curve_distance_epsilon = 1e-30; + const double curve_collinearity_epsilon = 1e-30; + const double curve_angle_tolerance_epsilon = 0.01; + enum curve_recursion_limit_e { curve_recursion_limit = 32 }; + + + + //------------------------------------------------------------------------ + void curve3_inc::approximation_scale(double s) + { + m_scale = s; + } + + //------------------------------------------------------------------------ + double curve3_inc::approximation_scale() const + { + return m_scale; + } + + //------------------------------------------------------------------------ + void curve3_inc::init(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + m_start_x = x1; + m_start_y = y1; + m_end_x = x3; + m_end_y = y3; + + double dx1 = x2 - x1; + double dy1 = y2 - y1; + double dx2 = x3 - x2; + double dy2 = y3 - y2; + + double len = std::sqrt(dx1 * dx1 + dy1 * dy1) + std::sqrt(dx2 * dx2 + dy2 * dy2); + + m_num_steps = uround(len * 0.25 * m_scale); + + if(m_num_steps < 4) + { + m_num_steps = 4; + } + + double subdivide_step = 1.0 / m_num_steps; + double subdivide_step2 = subdivide_step * subdivide_step; + + double tmpx = (x1 - x2 * 2.0 + x3) * subdivide_step2; + double tmpy = (y1 - y2 * 2.0 + y3) * subdivide_step2; + + m_saved_fx = m_fx = x1; + m_saved_fy = m_fy = y1; + + m_saved_dfx = m_dfx = tmpx + (x2 - x1) * (2.0 * subdivide_step); + m_saved_dfy = m_dfy = tmpy + (y2 - y1) * (2.0 * subdivide_step); + + m_ddfx = tmpx * 2.0; + m_ddfy = tmpy * 2.0; + + m_step = m_num_steps; + } + + //------------------------------------------------------------------------ + void curve3_inc::rewind(unsigned) + { + if(m_num_steps == 0) + { + m_step = -1; + return; + } + m_step = m_num_steps; + m_fx = m_saved_fx; + m_fy = m_saved_fy; + m_dfx = m_saved_dfx; + m_dfy = m_saved_dfy; + } + + //------------------------------------------------------------------------ + unsigned curve3_inc::vertex(double* x, double* y) + { + if(m_step < 0) return path_cmd_stop; + if(m_step == m_num_steps) + { + *x = m_start_x; + *y = m_start_y; + --m_step; + return path_cmd_move_to; + } + if(m_step == 0) + { + *x = m_end_x; + *y = m_end_y; + --m_step; + return path_cmd_line_to; + } + m_fx += m_dfx; + m_fy += m_dfy; + m_dfx += m_ddfx; + m_dfy += m_ddfy; + *x = m_fx; + *y = m_fy; + --m_step; + return path_cmd_line_to; + } + + //------------------------------------------------------------------------ + void curve3_div::init(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + m_points.remove_all(); + m_distance_tolerance_square = 0.5 / m_approximation_scale; + m_distance_tolerance_square *= m_distance_tolerance_square; + bezier(x1, y1, x2, y2, x3, y3); + m_count = 0; + } + + //------------------------------------------------------------------------ + void curve3_div::recursive_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + unsigned level) + { + if(level > curve_recursion_limit) + { + return; + } + + // Calculate all the mid-points of the line segments + //---------------------- + double x12 = (x1 + x2) / 2; + double y12 = (y1 + y2) / 2; + double x23 = (x2 + x3) / 2; + double y23 = (y2 + y3) / 2; + double x123 = (x12 + x23) / 2; + double y123 = (y12 + y23) / 2; + + double dx = x3-x1; + double dy = y3-y1; + double d = std::fabs(((x2 - x3) * dy - (y2 - y3) * dx)); + double da; + + if(d > curve_collinearity_epsilon) + { + // Regular case + //----------------- + if(d * d <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + // If the curvature doesn't exceed the distance_tolerance value + // we tend to finish subdivisions. + //---------------------- + if(m_angle_tolerance < curve_angle_tolerance_epsilon) + { + m_points.add(point_d(x123, y123)); + return; + } + + // Angle & Cusp Condition + //---------------------- + da = std::fabs(std::atan2(y3 - y2, x3 - x2) - std::atan2(y2 - y1, x2 - x1)); + if(da >= pi) da = 2*pi - da; + + if(da < m_angle_tolerance) + { + // Finally we can stop the recursion + //---------------------- + m_points.add(point_d(x123, y123)); + return; + } + } + } + else + { + // Collinear case + //------------------ + da = dx*dx + dy*dy; + if(da == 0) + { + d = calc_sq_distance(x1, y1, x2, y2); + } + else + { + d = ((x2 - x1)*dx + (y2 - y1)*dy) / da; + if(d > 0 && d < 1) + { + // Simple collinear case, 1---2---3 + // We can leave just two endpoints + return; + } + if(d <= 0) d = calc_sq_distance(x2, y2, x1, y1); + else if(d >= 1) d = calc_sq_distance(x2, y2, x3, y3); + else d = calc_sq_distance(x2, y2, x1 + d*dx, y1 + d*dy); + } + if(d < m_distance_tolerance_square) + { + m_points.add(point_d(x2, y2)); + return; + } + } + + // Continue subdivision + //---------------------- + recursive_bezier(x1, y1, x12, y12, x123, y123, level + 1); + recursive_bezier(x123, y123, x23, y23, x3, y3, level + 1); + } + + //------------------------------------------------------------------------ + void curve3_div::bezier(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + m_points.add(point_d(x1, y1)); + recursive_bezier(x1, y1, x2, y2, x3, y3, 0); + m_points.add(point_d(x3, y3)); + } + + + + + + //------------------------------------------------------------------------ + void curve4_inc::approximation_scale(double s) + { + m_scale = s; + } + + //------------------------------------------------------------------------ + double curve4_inc::approximation_scale() const + { + return m_scale; + } + +#if defined(_MSC_VER) && _MSC_VER <= 1200 + //------------------------------------------------------------------------ + static double MSC60_fix_ICE(double v) { return v; } +#endif + + //------------------------------------------------------------------------ + void curve4_inc::init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + m_start_x = x1; + m_start_y = y1; + m_end_x = x4; + m_end_y = y4; + + double dx1 = x2 - x1; + double dy1 = y2 - y1; + double dx2 = x3 - x2; + double dy2 = y3 - y2; + double dx3 = x4 - x3; + double dy3 = y4 - y3; + + double len = (std::sqrt(dx1 * dx1 + dy1 * dy1) + + std::sqrt(dx2 * dx2 + dy2 * dy2) + + std::sqrt(dx3 * dx3 + dy3 * dy3)) * 0.25 * m_scale; + +#if defined(_MSC_VER) && _MSC_VER <= 1200 + m_num_steps = uround(MSC60_fix_ICE(len)); +#else + m_num_steps = uround(len); +#endif + + if(m_num_steps < 4) + { + m_num_steps = 4; + } + + double subdivide_step = 1.0 / m_num_steps; + double subdivide_step2 = subdivide_step * subdivide_step; + double subdivide_step3 = subdivide_step * subdivide_step * subdivide_step; + + double pre1 = 3.0 * subdivide_step; + double pre2 = 3.0 * subdivide_step2; + double pre4 = 6.0 * subdivide_step2; + double pre5 = 6.0 * subdivide_step3; + + double tmp1x = x1 - x2 * 2.0 + x3; + double tmp1y = y1 - y2 * 2.0 + y3; + + double tmp2x = (x2 - x3) * 3.0 - x1 + x4; + double tmp2y = (y2 - y3) * 3.0 - y1 + y4; + + m_saved_fx = m_fx = x1; + m_saved_fy = m_fy = y1; + + m_saved_dfx = m_dfx = (x2 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdivide_step3; + m_saved_dfy = m_dfy = (y2 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdivide_step3; + + m_saved_ddfx = m_ddfx = tmp1x * pre4 + tmp2x * pre5; + m_saved_ddfy = m_ddfy = tmp1y * pre4 + tmp2y * pre5; + + m_dddfx = tmp2x * pre5; + m_dddfy = tmp2y * pre5; + + m_step = m_num_steps; + } + + //------------------------------------------------------------------------ + void curve4_inc::rewind(unsigned) + { + if(m_num_steps == 0) + { + m_step = -1; + return; + } + m_step = m_num_steps; + m_fx = m_saved_fx; + m_fy = m_saved_fy; + m_dfx = m_saved_dfx; + m_dfy = m_saved_dfy; + m_ddfx = m_saved_ddfx; + m_ddfy = m_saved_ddfy; + } + + //------------------------------------------------------------------------ + unsigned curve4_inc::vertex(double* x, double* y) + { + if(m_step < 0) return path_cmd_stop; + if(m_step == m_num_steps) + { + *x = m_start_x; + *y = m_start_y; + --m_step; + return path_cmd_move_to; + } + + if(m_step == 0) + { + *x = m_end_x; + *y = m_end_y; + --m_step; + return path_cmd_line_to; + } + + m_fx += m_dfx; + m_fy += m_dfy; + m_dfx += m_ddfx; + m_dfy += m_ddfy; + m_ddfx += m_dddfx; + m_ddfy += m_dddfy; + + *x = m_fx; + *y = m_fy; + --m_step; + return path_cmd_line_to; + } + + + + + //------------------------------------------------------------------------ + void curve4_div::init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + m_points.remove_all(); + m_distance_tolerance_square = 0.5 / m_approximation_scale; + m_distance_tolerance_square *= m_distance_tolerance_square; + bezier(x1, y1, x2, y2, x3, y3, x4, y4); + m_count = 0; + } + + //------------------------------------------------------------------------ + void curve4_div::recursive_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4, + unsigned level) + { + if(level > curve_recursion_limit) + { + return; + } + + // Calculate all the mid-points of the line segments + //---------------------- + double x12 = (x1 + x2) / 2; + double y12 = (y1 + y2) / 2; + double x23 = (x2 + x3) / 2; + double y23 = (y2 + y3) / 2; + double x34 = (x3 + x4) / 2; + double y34 = (y3 + y4) / 2; + double x123 = (x12 + x23) / 2; + double y123 = (y12 + y23) / 2; + double x234 = (x23 + x34) / 2; + double y234 = (y23 + y34) / 2; + double x1234 = (x123 + x234) / 2; + double y1234 = (y123 + y234) / 2; + + + // Try to approximate the full cubic curve by a single straight line + //------------------ + double dx = x4-x1; + double dy = y4-y1; + + double d2 = std::fabs(((x2 - x4) * dy - (y2 - y4) * dx)); + double d3 = std::fabs(((x3 - x4) * dy - (y3 - y4) * dx)); + double da1, da2, k; + + switch((int(d2 > curve_collinearity_epsilon) << 1) + + int(d3 > curve_collinearity_epsilon)) + { + case 0: + // All collinear OR p1==p4 + //---------------------- + k = dx*dx + dy*dy; + if(k == 0) + { + d2 = calc_sq_distance(x1, y1, x2, y2); + d3 = calc_sq_distance(x4, y4, x3, y3); + } + else + { + k = 1 / k; + da1 = x2 - x1; + da2 = y2 - y1; + d2 = k * (da1*dx + da2*dy); + da1 = x3 - x1; + da2 = y3 - y1; + d3 = k * (da1*dx + da2*dy); + if(d2 > 0 && d2 < 1 && d3 > 0 && d3 < 1) + { + // Simple collinear case, 1---2---3---4 + // We can leave just two endpoints + return; + } + if(d2 <= 0) d2 = calc_sq_distance(x2, y2, x1, y1); + else if(d2 >= 1) d2 = calc_sq_distance(x2, y2, x4, y4); + else d2 = calc_sq_distance(x2, y2, x1 + d2*dx, y1 + d2*dy); + + if(d3 <= 0) d3 = calc_sq_distance(x3, y3, x1, y1); + else if(d3 >= 1) d3 = calc_sq_distance(x3, y3, x4, y4); + else d3 = calc_sq_distance(x3, y3, x1 + d3*dx, y1 + d3*dy); + } + if(d2 > d3) + { + if(d2 < m_distance_tolerance_square) + { + m_points.add(point_d(x2, y2)); + return; + } + } + else + { + if(d3 < m_distance_tolerance_square) + { + m_points.add(point_d(x3, y3)); + return; + } + } + break; + + case 1: + // p1,p2,p4 are collinear, p3 is significant + //---------------------- + if(d3 * d3 <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + if(m_angle_tolerance < curve_angle_tolerance_epsilon) + { + m_points.add(point_d(x23, y23)); + return; + } + + // Angle Condition + //---------------------- + da1 = std::fabs(std::atan2(y4 - y3, x4 - x3) - std::atan2(y3 - y2, x3 - x2)); + if(da1 >= pi) da1 = 2*pi - da1; + + if(da1 < m_angle_tolerance) + { + m_points.add(point_d(x2, y2)); + m_points.add(point_d(x3, y3)); + return; + } + + if(m_cusp_limit != 0.0) + { + if(da1 > m_cusp_limit) + { + m_points.add(point_d(x3, y3)); + return; + } + } + } + break; + + case 2: + // p1,p3,p4 are collinear, p2 is significant + //---------------------- + if(d2 * d2 <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + if(m_angle_tolerance < curve_angle_tolerance_epsilon) + { + m_points.add(point_d(x23, y23)); + return; + } + + // Angle Condition + //---------------------- + da1 = std::fabs(std::atan2(y3 - y2, x3 - x2) - std::atan2(y2 - y1, x2 - x1)); + if(da1 >= pi) da1 = 2*pi - da1; + + if(da1 < m_angle_tolerance) + { + m_points.add(point_d(x2, y2)); + m_points.add(point_d(x3, y3)); + return; + } + + if(m_cusp_limit != 0.0) + { + if(da1 > m_cusp_limit) + { + m_points.add(point_d(x2, y2)); + return; + } + } + } + break; + + case 3: + // Regular case + //----------------- + if((d2 + d3)*(d2 + d3) <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + // If the curvature doesn't exceed the distance_tolerance value + // we tend to finish subdivisions. + //---------------------- + if(m_angle_tolerance < curve_angle_tolerance_epsilon) + { + m_points.add(point_d(x23, y23)); + return; + } + + // Angle & Cusp Condition + //---------------------- + k = std::atan2(y3 - y2, x3 - x2); + da1 = std::fabs(k - std::atan2(y2 - y1, x2 - x1)); + da2 = std::fabs(std::atan2(y4 - y3, x4 - x3) - k); + if(da1 >= pi) da1 = 2*pi - da1; + if(da2 >= pi) da2 = 2*pi - da2; + + if(da1 + da2 < m_angle_tolerance) + { + // Finally we can stop the recursion + //---------------------- + m_points.add(point_d(x23, y23)); + return; + } + + if(m_cusp_limit != 0.0) + { + if(da1 > m_cusp_limit) + { + m_points.add(point_d(x2, y2)); + return; + } + + if(da2 > m_cusp_limit) + { + m_points.add(point_d(x3, y3)); + return; + } + } + } + break; + } + + // Continue subdivision + //---------------------- + recursive_bezier(x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1); + recursive_bezier(x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1); + } + + //------------------------------------------------------------------------ + void curve4_div::bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + m_points.add(point_d(x1, y1)); + recursive_bezier(x1, y1, x2, y2, x3, y3, x4, y4, 0); + m_points.add(point_d(x4, y4)); + } + +} + diff --git a/agg2/src/agg_embedded_raster_fonts.cpp b/agg/src/agg_embedded_raster_fonts.cpp similarity index 99% rename from agg2/src/agg_embedded_raster_fonts.cpp rename to agg/src/agg_embedded_raster_fonts.cpp index f8148fb..ee4dc65 100644 --- a/agg2/src/agg_embedded_raster_fonts.cpp +++ b/agg/src/agg_embedded_raster_fonts.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. diff --git a/agg2/src/agg_gsv_text.cpp b/agg/src/agg_gsv_text.cpp similarity index 96% rename from agg2/src/agg_gsv_text.cpp rename to agg/src/agg_gsv_text.cpp index 59d6240..01adfbf 100644 --- a/agg2/src/agg_gsv_text.cpp +++ b/agg/src/agg_gsv_text.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -16,9 +16,11 @@ // Class gsv_text // //---------------------------------------------------------------------------- -#include -#include +#include +#include #include "agg_gsv_text.h" +#include "agg_bounding_rect.h" + namespace agg @@ -480,16 +482,6 @@ namespace agg 0xf6,0xfa,0x04,0x06,0x08,0xfa }; - - - //------------------------------------------------------------------------- - gsv_text::~gsv_text() - { - if(m_loaded_font) delete [] m_loaded_font; - if(m_text_buf) delete [] m_text_buf; - } - - //------------------------------------------------------------------------- gsv_text::gsv_text() : m_x(0.0), @@ -500,11 +492,10 @@ namespace agg m_space(0.0), m_line_space(0.0), m_text(m_chr), - m_text_buf(0), - m_buf_size(0), + m_text_buf(), m_cur_chr(m_chr), m_font(gsv_default_font), - m_loaded_font(0), + m_loaded_font(), m_status(initial), m_big_endian(false), m_flip(false) @@ -515,13 +506,11 @@ namespace agg if(*(char*)&t == 0) m_big_endian = true; } - - //------------------------------------------------------------------------- void gsv_text::font(const void* font) { m_font = font; - if(m_font == 0) m_font = m_loaded_font; + if(m_font == 0) m_font = &m_loaded_font[0]; } //------------------------------------------------------------------------- @@ -551,32 +540,30 @@ namespace agg //if(m_flip) m_y += m_height; } - //------------------------------------------------------------------------- void gsv_text::load_font(const char* file) { - if(m_loaded_font) delete [] m_loaded_font; - m_loaded_font = 0; - - FILE* fd = fopen(file, "rb"); + m_loaded_font.resize(0); + FILE* fd = std::fopen(file, "rb"); if(fd) { unsigned len; - fseek(fd, 0l, SEEK_END); - len = ftell(fd); - fseek(fd, 0l, SEEK_SET); + std::fseek(fd, 0l, SEEK_END); + len = std::ftell(fd); + std::fseek(fd, 0l, SEEK_SET); if(len > 0) { - m_loaded_font = new char [len]; - fread(m_loaded_font, 1, len, fd); - m_font = m_loaded_font; + m_loaded_font.resize(len); + if (std::fread(&m_loaded_font[0], 1, len, fd) == len) + m_font = &m_loaded_font[0]; + else + m_font = 0; } - fclose(fd); + std::fclose(fd); } } - //------------------------------------------------------------------------- void gsv_text::text(const char* text) { @@ -586,18 +573,15 @@ namespace agg m_text = m_chr; return; } - unsigned new_size = strlen(text) + 1; - if(new_size > m_buf_size) + unsigned new_size = std::strlen(text) + 1; + if(new_size > m_text_buf.size()) { - if(m_text_buf) delete [] m_text_buf; - m_text_buf = new char [m_buf_size = new_size]; + m_text_buf.resize(new_size); } - memcpy(m_text_buf, text, new_size); - m_text = m_text_buf; + std::memcpy(&m_text_buf[0], text, new_size); + m_text = &m_text_buf[0]; } - - //------------------------------------------------------------------------- void gsv_text::rewind(unsigned) { @@ -614,7 +598,6 @@ namespace agg m_cur_chr = m_text; } - //------------------------------------------------------------------------- unsigned gsv_text::vertex(double* x, double* y) { @@ -622,7 +605,6 @@ namespace agg int8 yc, yf; int dx, dy; bool quit = false; - while(!quit) { @@ -683,6 +665,13 @@ namespace agg return path_cmd_stop; } + //------------------------------------------------------------------------- + double gsv_text::text_width() + { + double x1, y1, x2, y2; + bounding_rect_single(*this, 0, &x1, &y1, &x2, &y2); + return x2 - x1; + } } diff --git a/agg2/src/agg_image_filters.cpp b/agg/src/agg_image_filters.cpp similarity index 50% rename from agg2/src/agg_image_filters.cpp rename to agg/src/agg_image_filters.cpp index ceb5024..549d9ad 100644 --- a/agg2/src/agg_image_filters.cpp +++ b/agg/src/agg_image_filters.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -13,7 +13,7 @@ // http://www.antigrain.com //---------------------------------------------------------------------------- // -// Filtering class image_filter_base implemantation +// Filtering class image_filter_lut implemantation // //---------------------------------------------------------------------------- @@ -23,38 +23,20 @@ namespace agg { - - //-------------------------------------------------------------------- - image_filter_base::~image_filter_base() - { - delete [] m_weight_array_int; - delete [] m_weight_array_dbl; - } - - //-------------------------------------------------------------------- - image_filter_base::image_filter_base(unsigned dimension) : - m_dimension(dimension), - m_start(-int(dimension / 2 - 1)), - m_weight_array_dbl(new double [dimension << image_subpixel_shift]), - m_weight_array_int(new int [dimension << image_subpixel_shift]) + void image_filter_lut::realloc_lut(double radius) { + m_radius = radius; + m_diameter = uceil(radius) * 2; + m_start = -int(m_diameter / 2 - 1); + unsigned size = m_diameter << image_subpixel_shift; + if(size > m_weight_array.size()) + { + m_weight_array.resize(size); + } } - //-------------------------------------------------------------------- - void image_filter_base::weight(unsigned idx, double val) - { - m_weight_array_dbl[idx] = val; - m_weight_array_int[idx] = int(val * image_filter_size); - } - - //-------------------------------------------------------------------- - double image_filter_base::calc_x(unsigned idx) const - { - return double(idx) / double(image_subpixel_size) - - double(m_dimension / 2); - } //-------------------------------------------------------------------- // This function normalizes integer values and corrects the rounding @@ -63,41 +45,59 @@ namespace agg // of 1.0 which means that any sum of pixel weights must be equal to 1.0. // So, the filter function must produce a graph of the proper shape. //-------------------------------------------------------------------- - void image_filter_base::normalize() + void image_filter_lut::normalize() { unsigned i; int flip = 1; - for(i = 0; i < image_subpixel_size; i++) + for(i = 0; i < image_subpixel_scale; i++) { for(;;) { int sum = 0; unsigned j; - for(j = 0; j < m_dimension; j++) + for(j = 0; j < m_diameter; j++) { - sum += m_weight_array_int[j * image_subpixel_size + i]; + sum += m_weight_array[j * image_subpixel_scale + i]; } - sum -= image_filter_size; - if(sum == 0) break; + if(sum == image_filter_scale) break; + + double k = double(image_filter_scale) / double(sum); + sum = 0; + for(j = 0; j < m_diameter; j++) + { + sum += m_weight_array[j * image_subpixel_scale + i] = + iround(m_weight_array[j * image_subpixel_scale + i] * k); + } + sum -= image_filter_scale; int inc = (sum > 0) ? -1 : 1; - for(j = 0; j < m_dimension && sum; j++) + for(j = 0; j < m_diameter && sum; j++) { flip ^= 1; - unsigned idx = flip ? m_dimension/2 + j/2 : m_dimension/2 - j/2; - int v = m_weight_array_int[idx * image_subpixel_size + i]; - if(v < image_filter_size) + unsigned idx = flip ? m_diameter/2 + j/2 : m_diameter/2 - j/2; + int v = m_weight_array[idx * image_subpixel_scale + i]; + if(v < image_filter_scale) { - m_weight_array_int[idx * image_subpixel_size + i] += inc; + m_weight_array[idx * image_subpixel_scale + i] += inc; sum += inc; } } } } + + unsigned pivot = m_diameter << (image_subpixel_shift - 1); + + for(i = 0; i < pivot; i++) + { + m_weight_array[pivot + i] = m_weight_array[pivot - i]; + } + unsigned end = (diameter() << image_subpixel_shift) - 1; + m_weight_array[0] = m_weight_array[end]; } + } diff --git a/agg2/src/agg_line_aa_basics.cpp b/agg/src/agg_line_aa_basics.cpp similarity index 78% rename from agg2/src/agg_line_aa_basics.cpp rename to agg/src/agg_line_aa_basics.cpp index 568c62d..8514f1b 100644 --- a/agg2/src/agg_line_aa_basics.cpp +++ b/agg/src/agg_line_aa_basics.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -13,7 +13,7 @@ // http://www.antigrain.com //---------------------------------------------------------------------------- -#include +#include #include "agg_line_aa_basics.h" namespace agg @@ -41,9 +41,9 @@ namespace agg // (7)111 | 101(5) // [2] | [3] // <3> - // 0,1,2,3,4,5,6,7 - int8u line_parameters::s_orthogonal_quadrant[8] = { 0,0,1,1,3,3,2,2 }; - int8u line_parameters::s_diagonal_quadrant[8] = { 0,1,2,1,0,3,2,3 }; + // 0,1,2,3,4,5,6,7 + const int8u line_parameters::s_orthogonal_quadrant[8] = { 0,0,1,1,3,3,2,2 }; + const int8u line_parameters::s_diagonal_quadrant[8] = { 0,1,2,1,0,3,2,3 }; @@ -69,13 +69,14 @@ namespace agg // Check if the bisectrix is too short double dx = tx - l2.x1; double dy = ty - l2.y1; - if((int)sqrt(dx * dx + dy * dy) < line_subpixel_size) + if((int)std::sqrt(dx * dx + dy * dy) < line_subpixel_scale) { - tx = (l2.x1 + l2.x1 + (l2.y1 - l1.y1) + (l2.y2 - l2.y1)) / 2; - ty = (l2.y1 + l2.y1 - (l2.x1 - l1.x1) - (l2.x2 - l2.x1)) / 2; + *x = (l2.x1 + l2.x1 + (l2.y1 - l1.y1) + (l2.y2 - l2.y1)) >> 1; + *y = (l2.y1 + l2.y1 - (l2.x1 - l1.x1) - (l2.x2 - l2.x1)) >> 1; + return; } - *x = int(tx); - *y = int(ty); + *x = iround(tx); + *y = iround(ty); } } diff --git a/agg2/src/agg_line_profile_aa.cpp b/agg/src/agg_line_profile_aa.cpp similarity index 84% rename from agg2/src/agg_line_profile_aa.cpp rename to agg/src/agg_line_profile_aa.cpp index ba12394..6066662 100644 --- a/agg2/src/agg_line_profile_aa.cpp +++ b/agg/src/agg_line_profile_aa.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -42,14 +42,13 @@ namespace agg //--------------------------------------------------------------------- line_profile_aa::value_type* line_profile_aa::profile(double w) { - m_subpixel_width = int(w * subpixel_size); - unsigned size = m_subpixel_width + subpixel_size * 6; - if(size > m_size) + m_subpixel_width = uround(w * subpixel_scale); + unsigned size = m_subpixel_width + subpixel_scale * 6; + if(size > m_profile.size()) { - delete [] m_profile; - m_profile = new value_type[m_size = size]; + m_profile.resize(size); } - return m_profile; + return &m_profile[0]; } @@ -57,8 +56,8 @@ namespace agg void line_profile_aa::set(double center_width, double smoother_width) { double base_val = 1.0; - if(center_width == 0.0) center_width = 1.0 / subpixel_size; - if(smoother_width == 0.0) smoother_width = 1.0 / subpixel_size; + if(center_width == 0.0) center_width = 1.0 / subpixel_scale; + if(smoother_width == 0.0) smoother_width = 1.0 / subpixel_scale; double width = center_width + smoother_width; if(width < m_min_width) @@ -71,10 +70,10 @@ namespace agg value_type* ch = profile(center_width + smoother_width); - unsigned subpixel_center_width = unsigned(center_width * subpixel_size); - unsigned subpixel_smoother_width = unsigned(smoother_width * subpixel_size); + unsigned subpixel_center_width = unsigned(center_width * subpixel_scale); + unsigned subpixel_smoother_width = unsigned(smoother_width * subpixel_scale); - value_type* ch_center = ch + subpixel_size*2; + value_type* ch_center = ch + subpixel_scale*2; value_type* ch_smoother = ch_center + subpixel_center_width; unsigned i; @@ -97,7 +96,7 @@ namespace agg unsigned n_smoother = profile_size() - subpixel_smoother_width - subpixel_center_width - - subpixel_size*2; + subpixel_scale*2; val = m_gamma[0]; for(i = 0; i < n_smoother; i++) @@ -106,7 +105,7 @@ namespace agg } ch = ch_center; - for(i = 0; i < subpixel_size*2; i++) + for(i = 0; i < subpixel_scale*2; i++) { *--ch = *ch_center++; } diff --git a/agg2/src/agg_rounded_rect.cpp b/agg/src/agg_rounded_rect.cpp similarity index 96% rename from agg2/src/agg_rounded_rect.cpp rename to agg/src/agg_rounded_rect.cpp index bc677a3..1605091 100644 --- a/agg2/src/agg_rounded_rect.cpp +++ b/agg/src/agg_rounded_rect.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -17,7 +17,7 @@ // //---------------------------------------------------------------------------- -#include +#include #include "agg_rounded_rect.h" @@ -78,8 +78,8 @@ namespace agg //-------------------------------------------------------------------- void rounded_rect::normalize_radius() { - double dx = fabs(m_y2 - m_y1); - double dy = fabs(m_x2 - m_x1); + double dx = std::fabs(m_y2 - m_y1); + double dy = std::fabs(m_x2 - m_x1); double k = 1.0; double t; diff --git a/agg2/src/agg_sqrt_tables.cpp b/agg/src/agg_sqrt_tables.cpp similarity index 97% rename from agg2/src/agg_sqrt_tables.cpp rename to agg/src/agg_sqrt_tables.cpp index 9d176b3..19a1bd8 100644 --- a/agg2/src/agg_sqrt_tables.cpp +++ b/agg/src/agg_sqrt_tables.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -21,7 +21,7 @@ namespace agg { - int16u g_sqrt_table[1024] = + int16u g_sqrt_table[1024] = //----------g_sqrt_table { 0, 2048,2896,3547,4096,4579,5017,5418,5793,6144,6476,6792,7094,7384,7663,7932,8192,8444, @@ -100,7 +100,7 @@ namespace agg }; - int8 g_elder_bit_table[256] = + int8 g_elder_bit_table[256] = //---------g_elder_bit_table { 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, diff --git a/agg2/src/agg_trans_affine.cpp b/agg/src/agg_trans_affine.cpp similarity index 68% rename from agg2/src/agg_trans_affine.cpp rename to agg/src/agg_trans_affine.cpp index 7382d27..961f8ee 100644 --- a/agg2/src/agg_trans_affine.cpp +++ b/agg/src/agg_trans_affine.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -27,12 +27,12 @@ namespace agg const trans_affine& trans_affine::parl_to_parl(const double* src, const double* dst) { - m0 = src[2] - src[0]; - m1 = src[3] - src[1]; - m2 = src[4] - src[0]; - m3 = src[5] - src[1]; - m4 = src[0]; - m5 = src[1]; + sx = src[2] - src[0]; + shy = src[3] - src[1]; + shx = src[4] - src[0]; + sy = src[5] - src[1]; + tx = src[0]; + ty = src[1]; invert(); multiply(trans_affine(dst[2] - dst[0], dst[3] - dst[1], dst[4] - dst[0], dst[5] - dst[1], @@ -69,15 +69,15 @@ namespace agg //------------------------------------------------------------------------ const trans_affine& trans_affine::multiply(const trans_affine& m) { - double t0 = m0 * m.m0 + m1 * m.m2; - double t2 = m2 * m.m0 + m3 * m.m2; - double t4 = m4 * m.m0 + m5 * m.m2 + m.m4; - m1 = m0 * m.m1 + m1 * m.m3; - m3 = m2 * m.m1 + m3 * m.m3; - m5 = m4 * m.m1 + m5 * m.m3 + m.m5; - m0 = t0; - m2 = t2; - m4 = t4; + double t0 = sx * m.sx + shy * m.shx; + double t2 = shx * m.sx + sy * m.shx; + double t4 = tx * m.sx + ty * m.shx + m.tx; + shy = sx * m.shy + shy * m.sy; + sy = shx * m.shy + sy * m.sy; + ty = tx * m.shy + ty * m.sy + m.ty; + sx = t0; + shx = t2; + tx = t4; return *this; } @@ -85,18 +85,18 @@ namespace agg //------------------------------------------------------------------------ const trans_affine& trans_affine::invert() { - double d = determinant(); + double d = determinant_reciprocal(); - double t0 = m3 * d; - m3 = m0 * d; - m1 = -m1 * d; - m2 = -m2 * d; + double t0 = sy * d; + sy = sx * d; + shy = -shy * d; + shx = -shx * d; - double t4 = -m4 * t0 - m5 * m2; - m5 = -m4 * m1 - m5 * m3; + double t4 = -tx * t0 - ty * shx; + ty = -tx * shy - ty * sy; - m0 = t0; - m4 = t4; + sx = t0; + tx = t4; return *this; } @@ -104,55 +104,55 @@ namespace agg //------------------------------------------------------------------------ const trans_affine& trans_affine::flip_x() { - m0 = -m0; - m1 = -m1; - m4 = -m4; + sx = -sx; + shy = -shy; + tx = -tx; return *this; } //------------------------------------------------------------------------ const trans_affine& trans_affine::flip_y() { - m2 = -m2; - m3 = -m3; - m5 = -m5; + shx = -shx; + sy = -sy; + ty = -ty; return *this; } //------------------------------------------------------------------------ const trans_affine& trans_affine::reset() { - m0 = m3 = 1.0; - m1 = m2 = m4 = m5 = 0.0; + sx = sy = 1.0; + shy = shx = tx = ty = 0.0; return *this; } //------------------------------------------------------------------------ - inline bool is_equal_eps(double v1, double v2, double epsilon) + bool trans_affine::is_identity(double epsilon) const { - return fabs(v1 - v2) < epsilon; + return is_equal_eps(sx, 1.0, epsilon) && + is_equal_eps(shy, 0.0, epsilon) && + is_equal_eps(shx, 0.0, epsilon) && + is_equal_eps(sy, 1.0, epsilon) && + is_equal_eps(tx, 0.0, epsilon) && + is_equal_eps(ty, 0.0, epsilon); } //------------------------------------------------------------------------ - bool trans_affine::is_identity(double epsilon) const + bool trans_affine::is_valid(double epsilon) const { - return is_equal_eps(m0, 1.0, epsilon) && - is_equal_eps(m1, 0.0, epsilon) && - is_equal_eps(m2, 0.0, epsilon) && - is_equal_eps(m3, 1.0, epsilon) && - is_equal_eps(m4, 0.0, epsilon) && - is_equal_eps(m5, 0.0, epsilon); + return std::fabs(sx) > epsilon && std::fabs(sy) > epsilon; } //------------------------------------------------------------------------ bool trans_affine::is_equal(const trans_affine& m, double epsilon) const { - return is_equal_eps(m0, m.m0, epsilon) && - is_equal_eps(m1, m.m1, epsilon) && - is_equal_eps(m2, m.m2, epsilon) && - is_equal_eps(m3, m.m3, epsilon) && - is_equal_eps(m4, m.m4, epsilon) && - is_equal_eps(m5, m.m5, epsilon); + return is_equal_eps(sx, m.sx, epsilon) && + is_equal_eps(shy, m.shy, epsilon) && + is_equal_eps(shx, m.shx, epsilon) && + is_equal_eps(sy, m.sy, epsilon) && + is_equal_eps(tx, m.tx, epsilon) && + is_equal_eps(ty, m.ty, epsilon); } //------------------------------------------------------------------------ @@ -164,19 +164,18 @@ namespace agg double y2 = 0.0; transform(&x1, &y1); transform(&x2, &y2); - return atan2(y2-y1, x2-x1); + return std::atan2(y2-y1, x2-x1); } //------------------------------------------------------------------------ void trans_affine::translation(double* dx, double* dy) const { - trans_affine t(*this); - t *= trans_affine_rotation(-rotation()); - t.transform(dx, dy); + *dx = tx; + *dy = ty; } //------------------------------------------------------------------------ - void trans_affine::scaling(double* sx, double* sy) const + void trans_affine::scaling(double* x, double* y) const { double x1 = 0.0; double y1 = 0.0; @@ -186,8 +185,8 @@ namespace agg t *= trans_affine_rotation(-rotation()); t.transform(&x1, &y1); t.transform(&x2, &y2); - *sx = x2 - x1; - *sy = y2 - y1; + *x = x2 - x1; + *y = y2 - y1; } diff --git a/agg2/src/agg_trans_double_path.cpp b/agg/src/agg_trans_double_path.cpp similarity index 98% rename from agg2/src/agg_trans_double_path.cpp rename to agg/src/agg_trans_double_path.cpp index ccc3f61..cd40c7f 100644 --- a/agg2/src/agg_trans_double_path.cpp +++ b/agg/src/agg_trans_double_path.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -101,6 +101,7 @@ namespace agg double dist; double d; + vertices.close(false); if(vertices.size() > 2) { if(vertices[vertices.size() - 2].dist * 10.0 < @@ -118,7 +119,6 @@ namespace agg } dist = 0; - vertices.close(false); for(i = 0; i < vertices.size(); i++) { vertex_dist& v = vertices[i]; @@ -228,7 +228,7 @@ namespace agg } else { - i = (unsigned)floor(*x * kindex); + i = unsigned(*x * kindex); j = i + 1; dd = vertices[j].dist - vertices[i].dist; d = ((*x * kindex) - i) * dd; diff --git a/agg2/src/agg_trans_single_path.cpp b/agg/src/agg_trans_single_path.cpp similarity index 97% rename from agg2/src/agg_trans_single_path.cpp rename to agg/src/agg_trans_single_path.cpp index d7a34fe..2120fc9 100644 --- a/agg2/src/agg_trans_single_path.cpp +++ b/agg/src/agg_trans_single_path.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -70,6 +70,7 @@ namespace agg double dist; double d; + m_src_vertices.close(false); if(m_src_vertices.size() > 2) { if(m_src_vertices[m_src_vertices.size() - 2].dist * 10.0 < @@ -87,7 +88,6 @@ namespace agg } dist = 0.0; - m_src_vertices.close(false); for(i = 0; i < m_src_vertices.size(); i++) { vertex_dist& v = m_src_vertices[i]; @@ -180,7 +180,7 @@ namespace agg } else { - i = (unsigned)floor(*x * m_kindex); + i = unsigned(*x * m_kindex); j = i + 1; dd = m_src_vertices[j].dist - m_src_vertices[i].dist; d = ((*x * m_kindex) - i) * dd; diff --git a/agg2/src/agg_trans_warp_magnifier.cpp b/agg/src/agg_trans_warp_magnifier.cpp similarity index 61% rename from agg2/src/agg_trans_warp_magnifier.cpp rename to agg/src/agg_trans_warp_magnifier.cpp index 60b383d..f4bfc5d 100644 --- a/agg2/src/agg_trans_warp_magnifier.cpp +++ b/agg/src/agg_trans_warp_magnifier.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -13,7 +13,7 @@ // http://www.antigrain.com //---------------------------------------------------------------------------- -#include +#include #include "agg_trans_warp_magnifier.h" namespace agg @@ -24,7 +24,7 @@ namespace agg { double dx = *x - m_xc; double dy = *y - m_yc; - double r = sqrt(dx * dx + dy * dy); + double r = std::sqrt(dx * dx + dy * dy); if(r < m_radius) { *x = m_xc + dx * m_magn; @@ -40,10 +40,30 @@ namespace agg //------------------------------------------------------------------------ void trans_warp_magnifier::inverse_transform(double* x, double* y) const { - trans_warp_magnifier t(*this); - t.magnification(1.0 / m_magn); - t.radius(m_radius * m_magn); - t.transform(x, y); + // New version by Andrew Skalkin + //----------------- + double dx = *x - m_xc; + double dy = *y - m_yc; + double r = std::sqrt(dx * dx + dy * dy); + + if(r < m_radius * m_magn) + { + *x = m_xc + dx / m_magn; + *y = m_yc + dy / m_magn; + } + else + { + double rnew = r - m_radius * (m_magn - 1.0); + *x = m_xc + rnew * dx / r; + *y = m_yc + rnew * dy / r; + } + + // Old version + //----------------- + //trans_warp_magnifier t(*this); + //t.magnification(1.0 / m_magn); + //t.radius(m_radius * m_magn); + //t.transform(x, y); } diff --git a/agg2/src/agg_vcgen_bspline.cpp b/agg/src/agg_vcgen_bspline.cpp similarity index 96% rename from agg2/src/agg_vcgen_bspline.cpp rename to agg/src/agg_vcgen_bspline.cpp index b0d00bd..4a0be66 100644 --- a/agg2/src/agg_vcgen_bspline.cpp +++ b/agg/src/agg_vcgen_bspline.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -47,13 +47,13 @@ namespace agg m_status = initial; if(is_move_to(cmd)) { - m_src_vertices.modify_last(point_type(x, y)); + m_src_vertices.modify_last(point_d(x, y)); } else { if(is_vertex(cmd)) { - m_src_vertices.add(point_type(x, y)); + m_src_vertices.add(point_d(x, y)); } else { @@ -114,6 +114,7 @@ namespace agg m_spline_x.prepare(); m_spline_y.prepare(); } + m_status = ready; } diff --git a/agg2/src/agg_vcgen_contour.cpp b/agg/src/agg_vcgen_contour.cpp similarity index 52% rename from agg2/src/agg_vcgen_contour.cpp rename to agg/src/agg_vcgen_contour.cpp index 2a5c665..de8442f 100644 --- a/agg2/src/agg_vcgen_contour.cpp +++ b/agg/src/agg_vcgen_contour.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -17,7 +17,6 @@ // //---------------------------------------------------------------------------- -#include #include "agg_vcgen_contour.h" namespace agg @@ -25,39 +24,27 @@ namespace agg //------------------------------------------------------------------------ vcgen_contour::vcgen_contour() : + m_stroker(), + m_width(1), m_src_vertices(), - m_width(1.0), - m_abs_width(1.0), - m_signed_width(1.0), - m_miter_limit(4.0), + m_out_vertices(), m_status(initial), m_src_vertex(0), m_closed(0), m_orientation(0), - m_auto_detect(true) + m_auto_detect(false) { } - //------------------------------------------------------------------------ void vcgen_contour::remove_all() { m_src_vertices.remove_all(); m_closed = 0; m_orientation = 0; - m_abs_width = fabs(m_width); - m_signed_width = m_width; m_status = initial; } - - //------------------------------------------------------------------------ - void vcgen_contour::miter_limit_theta(double t) - { - m_miter_limit = 1.0 / sin(t * 0.5) ; - } - - //------------------------------------------------------------------------ void vcgen_contour::add_vertex(double x, double y, unsigned cmd) { @@ -86,14 +73,12 @@ namespace agg } } - //------------------------------------------------------------------------ void vcgen_contour::rewind(unsigned) { if(m_status == initial) { m_src_vertices.close(true); - m_signed_width = m_width; if(m_auto_detect) { if(!is_oriented(m_orientation)) @@ -105,19 +90,18 @@ namespace agg } if(is_oriented(m_orientation)) { - m_signed_width = is_ccw(m_orientation) ? m_width : -m_width; + m_stroker.width(is_ccw(m_orientation) ? m_width : -m_width); } } m_status = ready; m_src_vertex = 0; } - //------------------------------------------------------------------------ unsigned vcgen_contour::vertex(double* x, double* y) { - bool done = false; - while(!done) + unsigned cmd = path_cmd_line_to; + while(!is_stop(cmd)) { switch(m_status) { @@ -125,98 +109,56 @@ namespace agg rewind(0); case ready: - if(m_src_vertices.size() < 3) + if(m_src_vertices.size() < 2 + unsigned(m_closed != 0)) { - return path_cmd_stop; + cmd = path_cmd_stop; + break; } - m_src_vertex = 0; m_status = outline; + cmd = path_cmd_move_to; + m_src_vertex = 0; + m_out_vertex = 0; case outline: if(m_src_vertex >= m_src_vertices.size()) { m_status = end_poly; - return path_cmd_end_poly | m_orientation | m_closed; - } - if(calc_miter(m_src_vertices.prev(m_src_vertex), - m_src_vertices.curr(m_src_vertex), - m_src_vertices.next(m_src_vertex))) - { - m_status = add_point; + break; } + m_stroker.calc_join(m_out_vertices, + m_src_vertices.prev(m_src_vertex), + m_src_vertices.curr(m_src_vertex), + m_src_vertices.next(m_src_vertex), + m_src_vertices.prev(m_src_vertex).dist, + m_src_vertices.curr(m_src_vertex).dist); ++m_src_vertex; - *x = m_x1; - *y = m_y1; - return ((m_src_vertex == 1) ? path_cmd_move_to : path_cmd_line_to); + m_status = out_vertices; + m_out_vertex = 0; - case add_point: - *x = m_x2; - *y = m_y2; - m_status = outline; - return path_cmd_line_to; - - case end_poly: - done = true; + case out_vertices: + if(m_out_vertex >= m_out_vertices.size()) + { + m_status = outline; + } + else + { + const point_d& c = m_out_vertices[m_out_vertex++]; + *x = c.x; + *y = c.y; + return cmd; + } break; - } - } - return path_cmd_stop; - } - - - - //------------------------------------------------------------------------ - bool vcgen_contour::calc_miter(const vertex_dist& v0, - const vertex_dist& v1, - const vertex_dist& v2) - { - double dx1, dy1, dx2, dy2; - - dx1 = m_signed_width * (v1.y - v0.y) / v0.dist; - dy1 = m_signed_width * (v1.x - v0.x) / v0.dist; - - dx2 = m_signed_width * (v2.y - v1.y) / v1.dist; - dy2 = m_signed_width * (v2.x - v1.x) / v1.dist; - - double xi; - double yi; - 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)) - { - m_x1 = v1.x + dx1; - m_y1 = v1.y - dy1; - return false; - } - else - { - double d1 = calc_distance(v1.x, v1.y, xi, yi); - double lim = m_abs_width * m_miter_limit; - if(d1 > lim) - { - d1 = lim / d1; - m_x1 = v1.x + dx1; - m_y1 = v1.y - dy1; - m_x2 = v1.x + dx2; - m_y2 = v1.y - dy2; + case end_poly: + if(!m_closed) return path_cmd_stop; + m_status = stop; + return path_cmd_end_poly | path_flags_close | path_flags_ccw; - m_x1 += (xi - m_x1) * d1; - m_y1 += (yi - m_y1) * d1; - m_x2 += (xi - m_x2) * d1; - m_y2 += (yi - m_y2) * d1; - return true; - } - else - { - m_x1 = xi; - m_y1 = yi; + case stop: + return path_cmd_stop; } } - return false; + return cmd; } - } diff --git a/agg2/src/agg_vcgen_dash.cpp b/agg/src/agg_vcgen_dash.cpp similarity index 97% rename from agg2/src/agg_vcgen_dash.cpp rename to agg/src/agg_vcgen_dash.cpp index a9288ce..17cba78 100644 --- a/agg2/src/agg_vcgen_dash.cpp +++ b/agg/src/agg_vcgen_dash.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -17,7 +17,7 @@ // //---------------------------------------------------------------------------- -#include +#include #include "agg_vcgen_dash.h" #include "agg_shorten_path.h" @@ -67,7 +67,7 @@ namespace agg void vcgen_dash::dash_start(double ds) { m_dash_start = ds; - calc_dash_start(fabs(ds)); + calc_dash_start(std::fabs(ds)); } diff --git a/agg2/src/agg_vcgen_markers_term.cpp b/agg/src/agg_vcgen_markers_term.cpp similarity index 94% rename from agg2/src/agg_vcgen_markers_term.cpp rename to agg/src/agg_vcgen_markers_term.cpp index 1411161..3374ab5 100644 --- a/agg2/src/agg_vcgen_markers_term.cpp +++ b/agg/src/agg_vcgen_markers_term.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -73,9 +73,9 @@ namespace agg //------------------------------------------------------------------------ - void vcgen_markers_term::rewind(unsigned id) + void vcgen_markers_term::rewind(unsigned path_id) { - m_curr_id = id * 2; + m_curr_id = path_id * 2; m_curr_idx = m_curr_id; } diff --git a/agg2/src/agg_vcgen_smooth_poly1.cpp b/agg/src/agg_vcgen_smooth_poly1.cpp similarity index 98% rename from agg2/src/agg_vcgen_smooth_poly1.cpp rename to agg/src/agg_vcgen_smooth_poly1.cpp index 79ae34d..ff7d488 100644 --- a/agg2/src/agg_vcgen_smooth_poly1.cpp +++ b/agg/src/agg_vcgen_smooth_poly1.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. diff --git a/agg/src/agg_vcgen_stroke.cpp b/agg/src/agg_vcgen_stroke.cpp new file mode 100644 index 0000000..046ac8c --- /dev/null +++ b/agg/src/agg_vcgen_stroke.cpp @@ -0,0 +1,212 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Stroke generator +// +//---------------------------------------------------------------------------- +#include "agg_vcgen_stroke.h" +#include "agg_shorten_path.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + vcgen_stroke::vcgen_stroke() : + m_stroker(), + m_src_vertices(), + m_out_vertices(), + m_shorten(0.0), + m_closed(0), + m_status(initial), + m_src_vertex(0), + m_out_vertex(0) + { + } + + //------------------------------------------------------------------------ + void vcgen_stroke::remove_all() + { + m_src_vertices.remove_all(); + m_closed = 0; + m_status = initial; + } + + + //------------------------------------------------------------------------ + void vcgen_stroke::add_vertex(double x, double y, unsigned cmd) + { + m_status = initial; + if(is_move_to(cmd)) + { + m_src_vertices.modify_last(vertex_dist(x, y)); + } + else + { + if(is_vertex(cmd)) + { + m_src_vertices.add(vertex_dist(x, y)); + } + else + { + m_closed = get_close_flag(cmd); + } + } + } + + //------------------------------------------------------------------------ + void vcgen_stroke::rewind(unsigned) + { + if(m_status == initial) + { + m_src_vertices.close(m_closed != 0); + shorten_path(m_src_vertices, m_shorten, m_closed); + if(m_src_vertices.size() < 3) m_closed = 0; + } + m_status = ready; + m_src_vertex = 0; + m_out_vertex = 0; + } + + + //------------------------------------------------------------------------ + unsigned vcgen_stroke::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + while(!is_stop(cmd)) + { + switch(m_status) + { + case initial: + rewind(0); + + case ready: + if(m_src_vertices.size() < 2 + unsigned(m_closed != 0)) + { + cmd = path_cmd_stop; + break; + } + m_status = m_closed ? outline1 : cap1; + cmd = path_cmd_move_to; + m_src_vertex = 0; + m_out_vertex = 0; + break; + + case cap1: + m_stroker.calc_cap(m_out_vertices, + m_src_vertices[0], + m_src_vertices[1], + m_src_vertices[0].dist); + m_src_vertex = 1; + m_prev_status = outline1; + m_status = out_vertices; + m_out_vertex = 0; + break; + + case cap2: + m_stroker.calc_cap(m_out_vertices, + m_src_vertices[m_src_vertices.size() - 1], + m_src_vertices[m_src_vertices.size() - 2], + m_src_vertices[m_src_vertices.size() - 2].dist); + m_prev_status = outline2; + m_status = out_vertices; + m_out_vertex = 0; + break; + + case outline1: + if(m_closed) + { + if(m_src_vertex >= m_src_vertices.size()) + { + m_prev_status = close_first; + m_status = end_poly1; + break; + } + } + else + { + if(m_src_vertex >= m_src_vertices.size() - 1) + { + m_status = cap2; + break; + } + } + m_stroker.calc_join(m_out_vertices, + m_src_vertices.prev(m_src_vertex), + m_src_vertices.curr(m_src_vertex), + m_src_vertices.next(m_src_vertex), + m_src_vertices.prev(m_src_vertex).dist, + m_src_vertices.curr(m_src_vertex).dist); + ++m_src_vertex; + m_prev_status = m_status; + m_status = out_vertices; + m_out_vertex = 0; + break; + + case close_first: + m_status = outline2; + cmd = path_cmd_move_to; + + case outline2: + if(m_src_vertex <= unsigned(m_closed == 0)) + { + m_status = end_poly2; + m_prev_status = stop; + break; + } + + --m_src_vertex; + m_stroker.calc_join(m_out_vertices, + m_src_vertices.next(m_src_vertex), + m_src_vertices.curr(m_src_vertex), + m_src_vertices.prev(m_src_vertex), + m_src_vertices.curr(m_src_vertex).dist, + m_src_vertices.prev(m_src_vertex).dist); + + m_prev_status = m_status; + m_status = out_vertices; + m_out_vertex = 0; + break; + + case out_vertices: + if(m_out_vertex >= m_out_vertices.size()) + { + m_status = m_prev_status; + } + else + { + const point_d& c = m_out_vertices[m_out_vertex++]; + *x = c.x; + *y = c.y; + return cmd; + } + break; + + case end_poly1: + m_status = m_prev_status; + return path_cmd_end_poly | path_flags_close | path_flags_ccw; + + case end_poly2: + m_status = m_prev_status; + return path_cmd_end_poly | path_flags_close | path_flags_cw; + + case stop: + cmd = path_cmd_stop; + break; + } + } + return cmd; + } + +} diff --git a/agg2/src/agg_vpgen_clip_polygon.cpp b/agg/src/agg_vpgen_clip_polygon.cpp similarity index 97% rename from agg2/src/agg_vpgen_clip_polygon.cpp rename to agg/src/agg_vpgen_clip_polygon.cpp index affa267..4524526 100644 --- a/agg2/src/agg_vpgen_clip_polygon.cpp +++ b/agg/src/agg_vpgen_clip_polygon.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. diff --git a/agg/src/agg_vpgen_clip_polyline.cpp b/agg/src/agg_vpgen_clip_polyline.cpp new file mode 100644 index 0000000..6840803 --- /dev/null +++ b/agg/src/agg_vpgen_clip_polyline.cpp @@ -0,0 +1,77 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#include "agg_vpgen_clip_polyline.h" +#include "agg_clip_liang_barsky.h" + +namespace agg +{ + //---------------------------------------------------------------------------- + void vpgen_clip_polyline::reset() + { + m_vertex = 0; + m_num_vertices = 0; + m_move_to = false; + } + + //---------------------------------------------------------------------------- + void vpgen_clip_polyline::move_to(double x, double y) + { + m_vertex = 0; + m_num_vertices = 0; + m_x1 = x; + m_y1 = y; + m_move_to = true; + } + + //---------------------------------------------------------------------------- + void vpgen_clip_polyline::line_to(double x, double y) + { + double x2 = x; + double y2 = y; + unsigned flags = clip_line_segment(&m_x1, &m_y1, &x2, &y2, m_clip_box); + + m_vertex = 0; + m_num_vertices = 0; + if((flags & 4) == 0) + { + if((flags & 1) != 0 || m_move_to) + { + m_x[0] = m_x1; + m_y[0] = m_y1; + m_cmd[0] = path_cmd_move_to; + m_num_vertices = 1; + } + m_x[m_num_vertices] = x2; + m_y[m_num_vertices] = y2; + m_cmd[m_num_vertices++] = path_cmd_line_to; + m_move_to = (flags & 2) != 0; + } + m_x1 = x; + m_y1 = y; + } + + //---------------------------------------------------------------------------- + unsigned vpgen_clip_polyline::vertex(double* x, double* y) + { + if(m_vertex < m_num_vertices) + { + *x = m_x[m_vertex]; + *y = m_y[m_vertex]; + return m_cmd[m_vertex++]; + } + return path_cmd_stop; + } +} diff --git a/agg2/src/agg_vpgen_segmentator.cpp b/agg/src/agg_vpgen_segmentator.cpp similarity index 82% rename from agg2/src/agg_vpgen_segmentator.cpp rename to agg/src/agg_vpgen_segmentator.cpp index 42a0c04..0499415 100644 --- a/agg2/src/agg_vpgen_segmentator.cpp +++ b/agg/src/agg_vpgen_segmentator.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -13,7 +13,7 @@ // http://www.antigrain.com //---------------------------------------------------------------------------- -#include +#include #include "agg_vpgen_segmentator.h" namespace agg @@ -26,6 +26,7 @@ namespace agg m_dx = 0.0; m_dy = 0.0; m_dl = 2.0; + m_ddl = 2.0; m_cmd = path_cmd_move_to; } @@ -35,7 +36,7 @@ namespace agg m_y1 += m_dy; m_dx = x - m_x1; m_dy = y - m_y1; - double len = sqrt(m_dx * m_dx + m_dy * m_dy) * m_approximation_scale; + double len = std::sqrt(m_dx * m_dx + m_dy * m_dy) * m_approximation_scale; if(len < 1e-30) len = 1e-30; m_ddl = 1.0 / len; m_dl = (m_cmd == path_cmd_move_to) ? 0.0 : m_ddl; @@ -48,10 +49,13 @@ namespace agg unsigned cmd = m_cmd; m_cmd = path_cmd_line_to; - if(m_dl > 1.0) + if(m_dl >= 1.0 - m_ddl) { m_dl = 1.0; m_cmd = path_cmd_stop; + *x = m_x1 + m_dx; + *y = m_y1 + m_dy; + return cmd; } *x = m_x1 + m_dx * m_dl; *y = m_y1 + m_dy * m_dl; diff --git a/agg/src/ctrl/agg_bezier_ctrl.cpp b/agg/src/ctrl/agg_bezier_ctrl.cpp new file mode 100644 index 0000000..4094134 --- /dev/null +++ b/agg/src/ctrl/agg_bezier_ctrl.cpp @@ -0,0 +1,370 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// classes bezier_ctrl_impl, bezier_ctrl +// +//---------------------------------------------------------------------------- + +#include +#include +#include "ctrl/agg_bezier_ctrl.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + bezier_ctrl_impl::bezier_ctrl_impl() : + ctrl(0,0,1,1,false), + m_stroke(m_curve), + m_poly(4, 5.0), + m_idx(0) + { + m_poly.in_polygon_check(false); + m_poly.xn(0) = 100.0; + m_poly.yn(0) = 0.0; + m_poly.xn(1) = 100.0; + m_poly.yn(1) = 50.0; + m_poly.xn(2) = 50.0; + m_poly.yn(2) = 100.0; + m_poly.xn(3) = 0.0; + m_poly.yn(3) = 100.0; + } + + + //------------------------------------------------------------------------ + void bezier_ctrl_impl::curve(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + m_poly.xn(0) = x1; + m_poly.yn(0) = y1; + m_poly.xn(1) = x2; + m_poly.yn(1) = y2; + m_poly.xn(2) = x3; + m_poly.yn(2) = y3; + m_poly.xn(3) = x4; + m_poly.yn(3) = y4; + curve(); + } + + //------------------------------------------------------------------------ + curve4& bezier_ctrl_impl::curve() + { + m_curve.init(m_poly.xn(0), m_poly.yn(0), + m_poly.xn(1), m_poly.yn(1), + m_poly.xn(2), m_poly.yn(2), + m_poly.xn(3), m_poly.yn(3)); + return m_curve; + } + + //------------------------------------------------------------------------ + void bezier_ctrl_impl::rewind(unsigned idx) + { + m_idx = idx; + + m_curve.approximation_scale(scale()); + switch(idx) + { + default: + case 0: // Control line 1 + m_curve.init(m_poly.xn(0), m_poly.yn(0), + (m_poly.xn(0) + m_poly.xn(1)) * 0.5, + (m_poly.yn(0) + m_poly.yn(1)) * 0.5, + (m_poly.xn(0) + m_poly.xn(1)) * 0.5, + (m_poly.yn(0) + m_poly.yn(1)) * 0.5, + m_poly.xn(1), m_poly.yn(1)); + m_stroke.rewind(0); + break; + + case 1: // Control line 2 + m_curve.init(m_poly.xn(2), m_poly.yn(2), + (m_poly.xn(2) + m_poly.xn(3)) * 0.5, + (m_poly.yn(2) + m_poly.yn(3)) * 0.5, + (m_poly.xn(2) + m_poly.xn(3)) * 0.5, + (m_poly.yn(2) + m_poly.yn(3)) * 0.5, + m_poly.xn(3), m_poly.yn(3)); + m_stroke.rewind(0); + break; + + case 2: // Curve itself + m_curve.init(m_poly.xn(0), m_poly.yn(0), + m_poly.xn(1), m_poly.yn(1), + m_poly.xn(2), m_poly.yn(2), + m_poly.xn(3), m_poly.yn(3)); + m_stroke.rewind(0); + break; + + case 3: // Point 1 + m_ellipse.init(m_poly.xn(0), m_poly.yn(0), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + + case 4: // Point 2 + m_ellipse.init(m_poly.xn(1), m_poly.yn(1), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + + case 5: // Point 3 + m_ellipse.init(m_poly.xn(2), m_poly.yn(2), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + + case 6: // Point 4 + m_ellipse.init(m_poly.xn(3), m_poly.yn(3), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + } + } + + + //------------------------------------------------------------------------ + unsigned bezier_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + switch(m_idx) + { + case 0: + case 1: + case 2: + cmd = m_stroke.vertex(x, y); + break; + + case 3: + case 4: + case 5: + case 6: + case 7: + cmd = m_ellipse.vertex(x, y); + break; + } + + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + return cmd; + } + + + + //------------------------------------------------------------------------ + bool bezier_ctrl_impl::in_rect(double, double) const + { + return false; + } + + + //------------------------------------------------------------------------ + bool bezier_ctrl_impl::on_mouse_button_down(double x, double y) + { + inverse_transform_xy(&x, &y); + return m_poly.on_mouse_button_down(x, y); + } + + + //------------------------------------------------------------------------ + bool bezier_ctrl_impl::on_mouse_move(double x, double y, bool button_flag) + { + inverse_transform_xy(&x, &y); + return m_poly.on_mouse_move(x, y, button_flag); + } + + + //------------------------------------------------------------------------ + bool bezier_ctrl_impl::on_mouse_button_up(double x, double y) + { + return m_poly.on_mouse_button_up(x, y); + } + + + //------------------------------------------------------------------------ + bool bezier_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up) + { + return m_poly.on_arrow_keys(left, right, down, up); + } + + + + + + + //------------------------------------------------------------------------ + curve3_ctrl_impl::curve3_ctrl_impl() : + ctrl(0,0,1,1,false), + m_stroke(m_curve), + m_poly(3, 5.0), + m_idx(0) + { + m_poly.in_polygon_check(false); + m_poly.xn(0) = 100.0; + m_poly.yn(0) = 0.0; + m_poly.xn(1) = 100.0; + m_poly.yn(1) = 50.0; + m_poly.xn(2) = 50.0; + m_poly.yn(2) = 100.0; + } + + + //------------------------------------------------------------------------ + void curve3_ctrl_impl::curve(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + m_poly.xn(0) = x1; + m_poly.yn(0) = y1; + m_poly.xn(1) = x2; + m_poly.yn(1) = y2; + m_poly.xn(2) = x3; + m_poly.yn(2) = y3; + curve(); + } + + //------------------------------------------------------------------------ + curve3& curve3_ctrl_impl::curve() + { + m_curve.init(m_poly.xn(0), m_poly.yn(0), + m_poly.xn(1), m_poly.yn(1), + m_poly.xn(2), m_poly.yn(2)); + return m_curve; + } + + //------------------------------------------------------------------------ + void curve3_ctrl_impl::rewind(unsigned idx) + { + m_idx = idx; + + switch(idx) + { + default: + case 0: // Control line + m_curve.init(m_poly.xn(0), m_poly.yn(0), + (m_poly.xn(0) + m_poly.xn(1)) * 0.5, + (m_poly.yn(0) + m_poly.yn(1)) * 0.5, + m_poly.xn(1), m_poly.yn(1)); + m_stroke.rewind(0); + break; + + case 1: // Control line 2 + m_curve.init(m_poly.xn(1), m_poly.yn(1), + (m_poly.xn(1) + m_poly.xn(2)) * 0.5, + (m_poly.yn(1) + m_poly.yn(2)) * 0.5, + m_poly.xn(2), m_poly.yn(2)); + m_stroke.rewind(0); + break; + + case 2: // Curve itself + m_curve.init(m_poly.xn(0), m_poly.yn(0), + m_poly.xn(1), m_poly.yn(1), + m_poly.xn(2), m_poly.yn(2)); + m_stroke.rewind(0); + break; + + case 3: // Point 1 + m_ellipse.init(m_poly.xn(0), m_poly.yn(0), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + + case 4: // Point 2 + m_ellipse.init(m_poly.xn(1), m_poly.yn(1), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + + case 5: // Point 3 + m_ellipse.init(m_poly.xn(2), m_poly.yn(2), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + } + } + + + //------------------------------------------------------------------------ + unsigned curve3_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + switch(m_idx) + { + case 0: + case 1: + case 2: + cmd = m_stroke.vertex(x, y); + break; + + case 3: + case 4: + case 5: + case 6: + cmd = m_ellipse.vertex(x, y); + break; + } + + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + return cmd; + } + + + + //------------------------------------------------------------------------ + bool curve3_ctrl_impl::in_rect(double, double) const + { + return false; + } + + + //------------------------------------------------------------------------ + bool curve3_ctrl_impl::on_mouse_button_down(double x, double y) + { + inverse_transform_xy(&x, &y); + return m_poly.on_mouse_button_down(x, y); + } + + + //------------------------------------------------------------------------ + bool curve3_ctrl_impl::on_mouse_move(double x, double y, bool button_flag) + { + inverse_transform_xy(&x, &y); + return m_poly.on_mouse_move(x, y, button_flag); + } + + + //------------------------------------------------------------------------ + bool curve3_ctrl_impl::on_mouse_button_up(double x, double y) + { + return m_poly.on_mouse_button_up(x, y); + } + + + //------------------------------------------------------------------------ + bool curve3_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up) + { + return m_poly.on_arrow_keys(left, right, down, up); + } + + + + + + + + + + + + +} + diff --git a/agg2/src/ctrl/agg_cbox_ctrl.cpp b/agg/src/ctrl/agg_cbox_ctrl.cpp similarity index 96% rename from agg2/src/ctrl/agg_cbox_ctrl.cpp rename to agg/src/ctrl/agg_cbox_ctrl.cpp index 55f0237..3cf14f6 100644 --- a/agg2/src/ctrl/agg_cbox_ctrl.cpp +++ b/agg/src/ctrl/agg_cbox_ctrl.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -131,8 +131,8 @@ namespace agg m_text.start_point(m_x1 + m_text_height * 2.0, m_y1 + m_text_height / 5.0); m_text.size(m_text_height, m_text_width); m_text_poly.width(m_text_thickness); - m_text_poly.line_join(vcgen_stroke::round_join); - m_text_poly.line_cap(vcgen_stroke::round_cap); + m_text_poly.line_join(round_join); + m_text_poly.line_cap(round_cap); m_text_poly.rewind(0); break; diff --git a/agg2/src/ctrl/agg_gamma_ctrl.cpp b/agg/src/ctrl/agg_gamma_ctrl.cpp similarity index 98% rename from agg2/src/ctrl/agg_gamma_ctrl.cpp rename to agg/src/ctrl/agg_gamma_ctrl.cpp index 5e39a67..7fd6448 100644 --- a/agg2/src/ctrl/agg_gamma_ctrl.cpp +++ b/agg/src/ctrl/agg_gamma_ctrl.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -245,8 +245,8 @@ namespace agg m_text.size(m_text_height, m_text_width); m_text.start_point(m_xt1 + m_border_width * 2.0, (m_yt1 + m_yt2) * 0.5 - m_text_height * 0.5); m_text_poly.width(m_text_thickness); - m_text_poly.line_join(vcgen_stroke::round_join); - m_text_poly.line_cap(vcgen_stroke::round_cap); + m_text_poly.line_join(round_join); + m_text_poly.line_cap(round_cap); m_text_poly.rewind(0); break; } diff --git a/agg2/src/ctrl/agg_gamma_spline.cpp b/agg/src/ctrl/agg_gamma_spline.cpp similarity index 97% rename from agg2/src/ctrl/agg_gamma_spline.cpp rename to agg/src/ctrl/agg_gamma_spline.cpp index 3e22719..f720fdd 100644 --- a/agg2/src/ctrl/agg_gamma_spline.cpp +++ b/agg/src/ctrl/agg_gamma_spline.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. diff --git a/agg/src/ctrl/agg_polygon_ctrl.cpp b/agg/src/ctrl/agg_polygon_ctrl.cpp new file mode 100644 index 0000000..0d3eeca --- /dev/null +++ b/agg/src/ctrl/agg_polygon_ctrl.cpp @@ -0,0 +1,332 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// classes polygon_ctrl_impl +// +//---------------------------------------------------------------------------- + +#include "ctrl/agg_polygon_ctrl.h" + +namespace agg +{ + + polygon_ctrl_impl::polygon_ctrl_impl(unsigned np, double point_radius) : + ctrl(0, 0, 1, 1, false), + m_polygon(np * 2), + m_num_points(np), + m_node(-1), + m_edge(-1), + m_vs(&m_polygon[0], m_num_points, false), + m_stroke(m_vs), + m_point_radius(point_radius), + m_status(0), + m_dx(0.0), + m_dy(0.0), + m_in_polygon_check(true) + { + m_stroke.width(1.0); + } + + + void polygon_ctrl_impl::rewind(unsigned) + { + m_status = 0; + m_stroke.rewind(0); + } + + unsigned polygon_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + double r = m_point_radius; + if(m_status == 0) + { + cmd = m_stroke.vertex(x, y); + if(!is_stop(cmd)) + { + transform_xy(x, y); + return cmd; + } + if(m_node >= 0 && m_node == int(m_status)) r *= 1.2; + m_ellipse.init(xn(m_status), yn(m_status), r, r, 32); + ++m_status; + } + cmd = m_ellipse.vertex(x, y); + if(!is_stop(cmd)) + { + transform_xy(x, y); + return cmd; + } + if(m_status >= m_num_points) return path_cmd_stop; + if(m_node >= 0 && m_node == int(m_status)) r *= 1.2; + m_ellipse.init(xn(m_status), yn(m_status), r, r, 32); + ++m_status; + cmd = m_ellipse.vertex(x, y); + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + return cmd; + } + + + bool polygon_ctrl_impl::check_edge(unsigned i, double x, double y) const + { + bool ret = false; + + unsigned n1 = i; + unsigned n2 = (i + m_num_points - 1) % m_num_points; + double x1 = xn(n1); + double y1 = yn(n1); + double x2 = xn(n2); + double y2 = yn(n2); + + double dx = x2 - x1; + double dy = y2 - y1; + + if(sqrt(dx*dx + dy*dy) > 0.0000001) + { + double x3 = x; + double y3 = y; + double x4 = x3 - dy; + double y4 = y3 + dx; + + double den = (y4-y3) * (x2-x1) - (x4-x3) * (y2-y1); + double u1 = ((x4-x3) * (y1-y3) - (y4-y3) * (x1-x3)) / den; + + double xi = x1 + u1 * (x2 - x1); + double yi = y1 + u1 * (y2 - y1); + + dx = xi - x; + dy = yi - y; + + if (u1 > 0.0 && u1 < 1.0 && sqrt(dx*dx + dy*dy) <= m_point_radius) + { + ret = true; + } + } + return ret; + } + + + + bool polygon_ctrl_impl::in_rect(double, double) const + { + return false; + } + + + bool polygon_ctrl_impl::on_mouse_button_down(double x, double y) + { + unsigned i; + bool ret = false; + m_node = -1; + m_edge = -1; + inverse_transform_xy(&x, &y); + for (i = 0; i < m_num_points; i++) + { + if(sqrt( (x-xn(i)) * (x-xn(i)) + (y-yn(i)) * (y-yn(i)) ) < m_point_radius) + { + m_dx = x - xn(i); + m_dy = y - yn(i); + m_node = int(i); + ret = true; + break; + } + } + + if(!ret) + { + for (i = 0; i < m_num_points; i++) + { + if(check_edge(i, x, y)) + { + m_dx = x; + m_dy = y; + m_edge = int(i); + ret = true; + break; + } + } + } + + if(!ret) + { + if(point_in_polygon(x, y)) + { + m_dx = x; + m_dy = y; + m_node = int(m_num_points); + ret = true; + } + } + return ret; + } + + + bool polygon_ctrl_impl::on_mouse_move(double x, double y, bool) + { + bool ret = false; + double dx; + double dy; + inverse_transform_xy(&x, &y); + if(m_node == int(m_num_points)) + { + dx = x - m_dx; + dy = y - m_dy; + unsigned i; + for(i = 0; i < m_num_points; i++) + { + xn(i) += dx; + yn(i) += dy; + } + m_dx = x; + m_dy = y; + ret = true; + } + else + { + if(m_edge >= 0) + { + unsigned n1 = m_edge; + unsigned n2 = (n1 + m_num_points - 1) % m_num_points; + dx = x - m_dx; + dy = y - m_dy; + xn(n1) += dx; + yn(n1) += dy; + xn(n2) += dx; + yn(n2) += dy; + m_dx = x; + m_dy = y; + ret = true; + } + else + { + if(m_node >= 0) + { + xn(m_node) = x - m_dx; + yn(m_node) = y - m_dy; + ret = true; + } + } + } + return ret; + } + + bool polygon_ctrl_impl::on_mouse_button_up(double, double) + { + bool ret = (m_node >= 0) || (m_edge >= 0); + m_node = -1; + m_edge = -1; + return ret; + } + + + bool polygon_ctrl_impl::on_arrow_keys(bool, bool, bool, bool) + { + return false; + } + + + //======= Crossings Multiply algorithm of InsideTest ======================== + // + // By Eric Haines, 3D/Eye Inc, erich@eye.com + // + // This version is usually somewhat faster than the original published in + // Graphics Gems IV; by turning the division for testing the X axis crossing + // into a tricky multiplication test this part of the test became faster, + // which had the additional effect of making the test for "both to left or + // both to right" a bit slower for triangles than simply computing the + // intersection each time. The main increase is in triangle testing speed, + // which was about 15% faster; all other polygon complexities were pretty much + // the same as before. On machines where division is very expensive (not the + // case on the HP 9000 series on which I tested) this test should be much + // faster overall than the old code. Your mileage may (in fact, will) vary, + // depending on the machine and the test data, but in general I believe this + // code is both shorter and faster. This test was inspired by unpublished + // Graphics Gems submitted by Joseph Samosky and Mark Haigh-Hutchinson. + // Related work by Samosky is in: + // + // Samosky, Joseph, "SectionView: A system for interactively specifying and + // visualizing sections through three-dimensional medical image data", + // M.S. Thesis, Department of Electrical Engineering and Computer Science, + // Massachusetts Institute of Technology, 1993. + // + // Shoot a test ray along +X axis. The strategy is to compare vertex Y values + // to the testing point's Y and quickly discard edges which are entirely to one + // side of the test ray. Note that CONVEX and WINDING code can be added as + // for the CrossingsTest() code; it is left out here for clarity. + // + // Input 2D polygon _pgon_ with _numverts_ number of vertices and test point + // _point_, returns 1 if inside, 0 if outside. + bool polygon_ctrl_impl::point_in_polygon(double tx, double ty) const + { + if(m_num_points < 3) return false; + if(!m_in_polygon_check) return false; + + unsigned j; + int yflag0, yflag1, inside_flag; + double vtx0, vty0, vtx1, vty1; + + vtx0 = xn(m_num_points - 1); + vty0 = yn(m_num_points - 1); + + // get test bit for above/below X axis + yflag0 = (vty0 >= ty); + + vtx1 = xn(0); + vty1 = yn(0); + + inside_flag = 0; + for (j = 1; j <= m_num_points; ++j) + { + yflag1 = (vty1 >= ty); + // Check if endpoints straddle (are on opposite sides) of X axis + // (i.e. the Y's differ); if so, +X ray could intersect this edge. + // The old test also checked whether the endpoints are both to the + // right or to the left of the test point. However, given the faster + // intersection point computation used below, this test was found to + // be a break-even proposition for most polygons and a loser for + // triangles (where 50% or more of the edges which survive this test + // will cross quadrants and so have to have the X intersection computed + // anyway). I credit Joseph Samosky with inspiring me to try dropping + // the "both left or both right" part of my code. + if (yflag0 != yflag1) + { + // Check intersection of pgon segment with +X ray. + // Note if >= point's X; if so, the ray hits it. + // The division operation is avoided for the ">=" test by checking + // the sign of the first vertex wrto the test point; idea inspired + // by Joseph Samosky's and Mark Haigh-Hutchinson's different + // polygon inclusion tests. + if ( ((vty1-ty) * (vtx0-vtx1) >= + (vtx1-tx) * (vty0-vty1)) == yflag1 ) + { + inside_flag ^= 1; + } + } + + // Move to the next pair of vertices, retaining info as possible. + yflag0 = yflag1; + vtx0 = vtx1; + vty0 = vty1; + + unsigned k = (j >= m_num_points) ? j - m_num_points : j; + vtx1 = xn(k); + vty1 = yn(k); + } + return inside_flag != 0; + } +} + diff --git a/agg2/src/ctrl/agg_rbox_ctrl.cpp b/agg/src/ctrl/agg_rbox_ctrl.cpp similarity index 92% rename from agg2/src/ctrl/agg_rbox_ctrl.cpp rename to agg/src/ctrl/agg_rbox_ctrl.cpp index b9f2fd8..4e36b3b 100644 --- a/agg2/src/ctrl/agg_rbox_ctrl.cpp +++ b/agg/src/ctrl/agg_rbox_ctrl.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -22,22 +22,7 @@ namespace agg { - - //------------------------------------------------------------------------ - rbox_ctrl_impl::~rbox_ctrl_impl() - { - if(m_num_items) - { - char** item = m_items + m_num_items - 1; - while(m_num_items--) - { - delete *item; - --item; - } - } - } - - + //------------------------------------------------------------------------ rbox_ctrl_impl::rbox_ctrl_impl(double x1, double y1, double x2, double y2, bool flip_y) : @@ -73,8 +58,8 @@ namespace agg { if(m_num_items < 32) { - m_items[m_num_items] = new char[strlen(text) + 1]; - strcpy(m_items[m_num_items], text); + m_items[m_num_items].resize(strlen(text) + 1); + strcpy(&m_items[m_num_items][0], text); m_num_items++; } } @@ -142,12 +127,12 @@ namespace agg break; case 2: // Text - m_text.text(m_items[0]); + m_text.text(&m_items[0][0]); m_text.start_point(m_xs1 + m_dy * 1.5, m_ys1 + m_dy / 2.0); m_text.size(m_text_height, m_text_width); m_text_poly.width(m_text_thickness); - m_text_poly.line_join(vcgen_stroke::round_join); - m_text_poly.line_cap(vcgen_stroke::round_cap); + m_text_poly.line_join(round_join); + m_text_poly.line_cap(round_cap); m_text_poly.rewind(0); break; @@ -209,7 +194,7 @@ namespace agg } else { - m_text.text(m_items[m_draw_item]); + m_text.text(&m_items[m_draw_item][0]); m_text.start_point(m_xs1 + m_dy * 1.5, m_ys1 + m_dy * (m_draw_item + 1) - m_dy / 2.0); diff --git a/agg/src/ctrl/agg_scale_ctrl.cpp b/agg/src/ctrl/agg_scale_ctrl.cpp new file mode 100644 index 0000000..361382b --- /dev/null +++ b/agg/src/ctrl/agg_scale_ctrl.cpp @@ -0,0 +1,454 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// classes scale_ctrl_impl, scale_ctrl +// +//---------------------------------------------------------------------------- + +#include "ctrl/agg_scale_ctrl.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + scale_ctrl_impl::scale_ctrl_impl(double x1, double y1, + double x2, double y2, bool flip_y) : + ctrl(x1, y1, x2, y2, flip_y), + m_border_thickness(1.0), + m_border_extra((fabs(x2 - x1) > fabs(y2 - y1)) ? (y2 - y1) / 2 : (x2 - x1) / 2), + m_pdx(0.0), + m_pdy(0.0), + m_move_what(move_nothing), + m_value1(0.3), + m_value2(0.7), + m_min_d(0.01) + { + calc_box(); + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::calc_box() + { + m_xs1 = m_x1 + m_border_thickness; + m_ys1 = m_y1 + m_border_thickness; + m_xs2 = m_x2 - m_border_thickness; + m_ys2 = m_y2 - m_border_thickness; + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::border_thickness(double t, double extra) + { + m_border_thickness = t; + m_border_extra = extra; + calc_box(); + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::resize(double x1, double y1, double x2, double y2) + { + m_x1 = x1; + m_y1 = y1; + m_x2 = x2; + m_y2 = y2; + calc_box(); + m_border_extra = (fabs(x2 - x1) > fabs(y2 - y1)) ? + (y2 - y1) / 2 : + (x2 - x1) / 2; + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::value1(double value) + { + if(value < 0.0) value = 0.0; + if(value > 1.0) value = 1.0; + if(m_value2 - value < m_min_d) value = m_value2 - m_min_d; + m_value1 = value; + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::value2(double value) + { + if(value < 0.0) value = 0.0; + if(value > 1.0) value = 1.0; + if(m_value1 + value < m_min_d) value = m_value1 + m_min_d; + m_value2 = value; + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::move(double d) + { + m_value1 += d; + m_value2 += d; + if(m_value1 < 0.0) + { + m_value2 -= m_value1; + m_value1 = 0.0; + } + if(m_value2 > 1.0) + { + m_value1 -= m_value2 - 1.0; + m_value2 = 1.0; + } + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::rewind(unsigned idx) + { + m_idx = idx; + + switch(idx) + { + default: + + case 0: // Background + m_vertex = 0; + m_vx[0] = m_x1 - m_border_extra; + m_vy[0] = m_y1 - m_border_extra; + m_vx[1] = m_x2 + m_border_extra; + m_vy[1] = m_y1 - m_border_extra; + m_vx[2] = m_x2 + m_border_extra; + m_vy[2] = m_y2 + m_border_extra; + m_vx[3] = m_x1 - m_border_extra; + m_vy[3] = m_y2 + m_border_extra; + break; + + case 1: // Border + m_vertex = 0; + m_vx[0] = m_x1; + m_vy[0] = m_y1; + m_vx[1] = m_x2; + m_vy[1] = m_y1; + m_vx[2] = m_x2; + m_vy[2] = m_y2; + m_vx[3] = m_x1; + m_vy[3] = m_y2; + m_vx[4] = m_x1 + m_border_thickness; + m_vy[4] = m_y1 + m_border_thickness; + m_vx[5] = m_x1 + m_border_thickness; + m_vy[5] = m_y2 - m_border_thickness; + m_vx[6] = m_x2 - m_border_thickness; + m_vy[6] = m_y2 - m_border_thickness; + m_vx[7] = m_x2 - m_border_thickness; + m_vy[7] = m_y1 + m_border_thickness; + break; + + case 2: // pointer1 + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_value1, + (m_ys1 + m_ys2) / 2.0, + m_y2 - m_y1, + m_y2 - m_y1, + 32); + } + else + { + m_ellipse.init((m_xs1 + m_xs2) / 2.0, + m_ys1 + (m_ys2 - m_ys1) * m_value1, + m_x2 - m_x1, + m_x2 - m_x1, + 32); + } + m_ellipse.rewind(0); + break; + + case 3: // pointer2 + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_value2, + (m_ys1 + m_ys2) / 2.0, + m_y2 - m_y1, + m_y2 - m_y1, + 32); + } + else + { + m_ellipse.init((m_xs1 + m_xs2) / 2.0, + m_ys1 + (m_ys2 - m_ys1) * m_value2, + m_x2 - m_x1, + m_x2 - m_x1, + 32); + } + m_ellipse.rewind(0); + break; + + case 4: // slider + m_vertex = 0; + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + m_vx[0] = m_xs1 + (m_xs2 - m_xs1) * m_value1; + m_vy[0] = m_y1 - m_border_extra / 2.0; + m_vx[1] = m_xs1 + (m_xs2 - m_xs1) * m_value2; + m_vy[1] = m_vy[0]; + m_vx[2] = m_vx[1]; + m_vy[2] = m_y2 + m_border_extra / 2.0; + m_vx[3] = m_vx[0]; + m_vy[3] = m_vy[2]; + } + else + { + m_vx[0] = m_x1 - m_border_extra / 2.0; + m_vy[0] = m_ys1 + (m_ys2 - m_ys1) * m_value1; + m_vx[1] = m_vx[0]; + m_vy[1] = m_ys1 + (m_ys2 - m_ys1) * m_value2; + m_vx[2] = m_x2 + m_border_extra / 2.0; + m_vy[2] = m_vy[1]; + m_vx[3] = m_vx[2]; + m_vy[3] = m_vy[0]; + } + break; + } + } + + + //------------------------------------------------------------------------ + unsigned scale_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + switch(m_idx) + { + case 0: + case 4: + if(m_vertex == 0) cmd = path_cmd_move_to; + if(m_vertex >= 4) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 1: + if(m_vertex == 0 || m_vertex == 4) cmd = path_cmd_move_to; + if(m_vertex >= 8) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 2: + case 3: + cmd = m_ellipse.vertex(x, y); + break; + + default: + cmd = path_cmd_stop; + break; + } + + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + + return cmd; + } + + + + //------------------------------------------------------------------------ + bool scale_ctrl_impl::in_rect(double x, double y) const + { + inverse_transform_xy(&x, &y); + return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2; + } + + + //------------------------------------------------------------------------ + bool scale_ctrl_impl::on_mouse_button_down(double x, double y) + { + inverse_transform_xy(&x, &y); + + double xp1; + double xp2; + double ys1; + double ys2; + double xp; + double yp; + + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + xp1 = m_xs1 + (m_xs2 - m_xs1) * m_value1; + xp2 = m_xs1 + (m_xs2 - m_xs1) * m_value2; + ys1 = m_y1 - m_border_extra / 2.0; + ys2 = m_y2 + m_border_extra / 2.0; + yp = (m_ys1 + m_ys2) / 2.0; + + if(x > xp1 && y > ys1 && x < xp2 && y < ys2) + { + m_pdx = xp1 - x; + m_move_what = move_slider; + return true; + } + + //if(x < xp1 && calc_distance(x, y, xp1, yp) <= m_y2 - m_y1) + if(calc_distance(x, y, xp1, yp) <= m_y2 - m_y1) + { + m_pdx = xp1 - x; + m_move_what = move_value1; + return true; + } + + //if(x > xp2 && calc_distance(x, y, xp2, yp) <= m_y2 - m_y1) + if(calc_distance(x, y, xp2, yp) <= m_y2 - m_y1) + { + m_pdx = xp2 - x; + m_move_what = move_value2; + return true; + } + } + else + { + xp1 = m_x1 - m_border_extra / 2.0; + xp2 = m_x2 + m_border_extra / 2.0; + ys1 = m_ys1 + (m_ys2 - m_ys1) * m_value1; + ys2 = m_ys1 + (m_ys2 - m_ys1) * m_value2; + xp = (m_xs1 + m_xs2) / 2.0; + + if(x > xp1 && y > ys1 && x < xp2 && y < ys2) + { + m_pdy = ys1 - y; + m_move_what = move_slider; + return true; + } + + //if(y < ys1 && calc_distance(x, y, xp, ys1) <= m_x2 - m_x1) + if(calc_distance(x, y, xp, ys1) <= m_x2 - m_x1) + { + m_pdy = ys1 - y; + m_move_what = move_value1; + return true; + } + + //if(y > ys2 && calc_distance(x, y, xp, ys2) <= m_x2 - m_x1) + if(calc_distance(x, y, xp, ys2) <= m_x2 - m_x1) + { + m_pdy = ys2 - y; + m_move_what = move_value2; + return true; + } + } + + return false; + } + + + //------------------------------------------------------------------------ + bool scale_ctrl_impl::on_mouse_move(double x, double y, bool button_flag) + { + inverse_transform_xy(&x, &y); + if(!button_flag) + { + return on_mouse_button_up(x, y); + } + + double xp = x + m_pdx; + double yp = y + m_pdy; + double dv; + + switch(m_move_what) + { + case move_value1: + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + m_value1 = (xp - m_xs1) / (m_xs2 - m_xs1); + } + else + { + m_value1 = (yp - m_ys1) / (m_ys2 - m_ys1); + } + if(m_value1 < 0.0) m_value1 = 0.0; + if(m_value1 > m_value2 - m_min_d) m_value1 = m_value2 - m_min_d; + return true; + + case move_value2: + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + m_value2 = (xp - m_xs1) / (m_xs2 - m_xs1); + } + else + { + m_value2 = (yp - m_ys1) / (m_ys2 - m_ys1); + } + if(m_value2 > 1.0) m_value2 = 1.0; + if(m_value2 < m_value1 + m_min_d) m_value2 = m_value1 + m_min_d; + return true; + + case move_slider: + dv = m_value2 - m_value1; + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + m_value1 = (xp - m_xs1) / (m_xs2 - m_xs1); + } + else + { + m_value1 = (yp - m_ys1) / (m_ys2 - m_ys1); + } + m_value2 = m_value1 + dv; + if(m_value1 < 0.0) + { + dv = m_value2 - m_value1; + m_value1 = 0.0; + m_value2 = m_value1 + dv; + } + if(m_value2 > 1.0) + { + dv = m_value2 - m_value1; + m_value2 = 1.0; + m_value1 = m_value2 - dv; + } + return true; + default: + return false; + } + } + + + //------------------------------------------------------------------------ + bool scale_ctrl_impl::on_mouse_button_up(double, double) + { + m_move_what = move_nothing; + return false; + } + + + //------------------------------------------------------------------------ + bool scale_ctrl_impl::on_arrow_keys(bool /*left*/, bool /*right*/, bool /*down*/, bool /*up*/) + { +/* + if(right || up) + { + m_value += 0.005; + if(m_value > 1.0) m_value = 1.0; + return true; + } + + if(left || down) + { + m_value -= 0.005; + if(m_value < 0.0) m_value = 0.0; + return true; + } +*/ + return false; + } + +} + diff --git a/agg2/src/ctrl/agg_slider_ctrl.cpp b/agg/src/ctrl/agg_slider_ctrl.cpp similarity index 97% rename from agg2/src/ctrl/agg_slider_ctrl.cpp rename to agg/src/ctrl/agg_slider_ctrl.cpp index d6395d9..ad00486 100644 --- a/agg2/src/ctrl/agg_slider_ctrl.cpp +++ b/agg/src/ctrl/agg_slider_ctrl.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -168,8 +168,8 @@ namespace agg m_text.start_point(m_x1, m_y1); m_text.size((m_y2 - m_y1) * 1.2, m_y2 - m_y1); m_text_poly.width(m_text_thickness); - m_text_poly.line_join(vcgen_stroke::round_join); - m_text_poly.line_cap(vcgen_stroke::round_cap); + m_text_poly.line_join(round_join); + m_text_poly.line_cap(round_cap); m_text_poly.rewind(0); break; diff --git a/agg2/src/ctrl/agg_spline_ctrl.cpp b/agg/src/ctrl/agg_spline_ctrl.cpp similarity index 98% rename from agg2/src/ctrl/agg_spline_ctrl.cpp rename to agg/src/ctrl/agg_spline_ctrl.cpp index 5a12575..74808d4 100644 --- a/agg2/src/ctrl/agg_spline_ctrl.cpp +++ b/agg/src/ctrl/agg_spline_ctrl.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -235,7 +235,7 @@ namespace agg { m_ellipse.init(calc_xp(i), calc_yp(i), m_point_size, m_point_size, 32); - m_curve_pnt.add_path(m_ellipse, 0, false); + m_curve_pnt.concat_path(m_ellipse); } } m_curve_poly.rewind(0); @@ -249,7 +249,7 @@ namespace agg m_ellipse.init(calc_xp(m_active_pnt), calc_yp(m_active_pnt), m_point_size, m_point_size, 32); - m_curve_pnt.add_path(m_ellipse); + m_curve_pnt.concat_path(m_ellipse); } m_curve_poly.rewind(0); break; diff --git a/agg/src/platform/AmigaOS/Makefile.am b/agg/src/platform/AmigaOS/Makefile.am new file mode 100644 index 0000000..474153c --- /dev/null +++ b/agg/src/platform/AmigaOS/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST=agg_platform_support.cpp diff --git a/agg/src/platform/AmigaOS/agg_platform_support.cpp b/agg/src/platform/AmigaOS/agg_platform_support.cpp new file mode 100644 index 0000000..b14d09c --- /dev/null +++ b/agg/src/platform/AmigaOS/agg_platform_support.cpp @@ -0,0 +1,977 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// class platform_support +// +//---------------------------------------------------------------------------- + +#include "platform/agg_platform_support.h" +#include "util/agg_color_conv_rgb8.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +Library* DataTypesBase = 0; +Library* GraphicsBase = 0; +Library* IntuitionBase = 0; +Library* KeymapBase = 0; +Library* P96Base = 0; + +DataTypesIFace* IDataTypes = 0; +GraphicsIFace* IGraphics = 0; +IntuitionIFace* IIntuition = 0; +KeymapIFace* IKeymap = 0; +P96IFace* IP96 = 0; + +Class* RequesterClass = 0; +Class* WindowClass = 0; + + +namespace agg +{ + void handle_idcmp(Hook* hook, APTR win, IntuiMessage* msg); + + //------------------------------------------------------------------------ + class platform_specific + { + public: + platform_specific(platform_support& support, pix_format_e format, + bool flip_y); + ~platform_specific(); + bool handle_input(); + bool load_img(const char* file, unsigned idx, rendering_buffer* rbuf); + bool create_img(unsigned idx, rendering_buffer* rbuf, unsigned width, + unsigned height); + bool make_bitmap(); + public: + platform_support& m_support; + RGBFTYPE m_ftype; + pix_format_e m_format; + unsigned m_bpp; + BitMap* m_bitmap; + bool m_flip_y; + uint16 m_width; + uint16 m_height; + APTR m_window_obj; + Window* m_window; + Hook* m_idcmp_hook; + unsigned m_input_flags; + bool m_dragging; + double m_start_time; + uint16 m_last_key; + BitMap* m_img_bitmaps[platform_support::max_images]; + }; + + //------------------------------------------------------------------------ + platform_specific::platform_specific(platform_support& support, + pix_format_e format, bool flip_y) : + m_support(support), + m_ftype(RGBFB_NONE), + m_format(format), + m_bpp(0), + m_bitmap(0), + m_flip_y(flip_y), + m_width(0), + m_height(0), + m_window_obj(0), + m_window(0), + m_idcmp_hook(0), + m_input_flags(0), + m_dragging(false), + m_start_time(0.0), + m_last_key(0) + { + switch ( format ) + { + case pix_format_gray8: + // Not supported. + break; + case pix_format_rgb555: + m_ftype = RGBFB_R5G5B5; + m_bpp = 15; + break; + case pix_format_rgb565: + m_ftype = RGBFB_R5G6B5; + m_bpp = 16; + break; + case pix_format_rgb24: + m_ftype = RGBFB_R8G8B8; + m_bpp = 24; + break; + case pix_format_bgr24: + m_ftype = RGBFB_B8G8R8; + m_bpp = 24; + break; + case pix_format_bgra32: + m_ftype = RGBFB_B8G8R8A8; + m_bpp = 32; + break; + case pix_format_abgr32: + m_ftype = RGBFB_A8B8G8R8; + m_bpp = 32; + break; + case pix_format_argb32: + m_ftype = RGBFB_A8R8G8B8; + m_bpp = 32; + break; + case pix_format_rgba32: + m_ftype = RGBFB_R8G8B8A8; + m_bpp = 32; + break; + } + + for ( unsigned i = 0; i < platform_support::max_images; ++i ) + { + m_img_bitmaps[i] = 0; + } + } + + //------------------------------------------------------------------------ + platform_specific::~platform_specific() + { + IIntuition->DisposeObject(m_window_obj); + + IP96->p96FreeBitMap(m_bitmap); + + for ( unsigned i = 0; i < platform_support::max_images; ++i ) + { + IP96->p96FreeBitMap(m_img_bitmaps[i]); + } + + if ( m_idcmp_hook != 0 ) + { + IExec->FreeSysObject(ASOT_HOOK, m_idcmp_hook); + } + } + + //------------------------------------------------------------------------ + bool platform_specific::handle_input() + { + int16 code = 0; + uint32 result = 0; + Object* obj = reinterpret_cast(m_window_obj); + + while ( (result = IIntuition->IDoMethod(obj, WM_HANDLEINPUT, + &code)) != WMHI_LASTMSG ) + { + switch ( result & WMHI_CLASSMASK ) + { + case WMHI_CLOSEWINDOW: + return true; + break; + case WMHI_INTUITICK: + if ( !m_support.wait_mode() ) + { + m_support.on_idle(); + } + break; + case WMHI_NEWSIZE: + if ( make_bitmap() ) + { + m_support.trans_affine_resizing(m_width, m_height); + m_support.on_resize(m_width, m_height); + m_support.force_redraw(); + } + break; + } + } + + return false; + } + + //------------------------------------------------------------------------ + bool platform_specific::load_img(const char* file, unsigned idx, + rendering_buffer* rbuf) + { + if ( m_img_bitmaps[idx] != 0 ) + { + IP96->p96FreeBitMap(m_img_bitmaps[idx]); + m_img_bitmaps[idx] = 0; + } + + bool result = false; + + Object* picture = IDataTypes->NewDTObject(const_cast(file), + DTA_GroupID, GID_PICTURE, + PDTA_DestMode, PMODE_V43, + PDTA_Remap, FALSE, + TAG_END); + if ( picture != 0 ) + { + gpLayout layout; + layout.MethodID = DTM_PROCLAYOUT; + layout.gpl_GInfo = 0; + layout.gpl_Initial = 1; + ULONG loaded = IDataTypes->DoDTMethodA(picture, 0, 0, + reinterpret_cast(&layout)); + if ( loaded != 0 ) + { + BitMap* src_bitmap = 0; + IDataTypes->GetDTAttrs(picture, + PDTA_ClassBitMap, &src_bitmap, + TAG_END); + + bool supported = false; + + RGBFTYPE ftype = static_cast(IP96->p96GetBitMapAttr( + src_bitmap, P96BMA_RGBFORMAT)); + + switch ( ftype ) + { + case RGBFB_R8G8B8: + supported = true; + break; + default: + m_support.message("File uses unsupported graphics mode."); + break; + } + + if ( supported ) { + uint16 width = IP96->p96GetBitMapAttr(src_bitmap, + P96BMA_WIDTH); + uint16 height = IP96->p96GetBitMapAttr(src_bitmap, + P96BMA_HEIGHT); + + m_img_bitmaps[idx] = IP96->p96AllocBitMap(width, height, + m_bpp, BMF_USERPRIVATE, 0, m_ftype); + if ( m_img_bitmaps[idx] != 0 ) + { + int8u* buf = reinterpret_cast( + IP96->p96GetBitMapAttr(m_img_bitmaps[idx], + P96BMA_MEMORY)); + int bpr = IP96->p96GetBitMapAttr(m_img_bitmaps[idx], + P96BMA_BYTESPERROW); + int stride = (m_flip_y) ? -bpr : bpr; + rbuf->attach(buf, width, height, stride); + + // P96 sets the alpha to zero so it can't be used to + // color convert true color modes. + if ( m_bpp == 32 ) + { + RenderInfo ri; + int32 lock = IP96->p96LockBitMap(src_bitmap, + reinterpret_cast(&ri), + sizeof(RenderInfo)); + + rendering_buffer rbuf_src; + rbuf_src.attach( + reinterpret_cast(ri.Memory), + width, height, (m_flip_y) ? + -ri.BytesPerRow : ri.BytesPerRow); + + switch ( m_format ) + { + case pix_format_bgra32: + color_conv(rbuf, &rbuf_src, + color_conv_rgb24_to_bgra32()); + break; + case pix_format_abgr32: + color_conv(rbuf, &rbuf_src, + color_conv_rgb24_to_abgr32()); + break; + case pix_format_argb32: + color_conv(rbuf, &rbuf_src, + color_conv_rgb24_to_argb32()); + break; + case pix_format_rgba32: + color_conv(rbuf, &rbuf_src, + color_conv_rgb24_to_rgba32()); + break; + } + + IP96->p96UnlockBitMap(src_bitmap, lock); + } + else + { + IGraphics->BltBitMap(src_bitmap, 0, 0, + m_img_bitmaps[idx], 0, 0, width, height, + ABC|ABNC, 0xFF, 0); + } + + result = true; + } + } + } + } + + IGraphics->WaitBlit(); + IDataTypes->DisposeDTObject(picture); + + return result; + } + + //------------------------------------------------------------------------ + bool platform_specific::create_img(unsigned idx, rendering_buffer* rbuf, + unsigned width, unsigned height) + { + if ( m_img_bitmaps[idx] != 0 ) + { + IP96->p96FreeBitMap(m_img_bitmaps[idx]); + m_img_bitmaps[idx] = 0; + } + + m_img_bitmaps[idx] = IP96->p96AllocBitMap(width, height, + m_bpp, BMF_USERPRIVATE, m_bitmap, m_ftype); + if ( m_img_bitmaps[idx] != 0 ) + { + int8u* buf = reinterpret_cast( + IP96->p96GetBitMapAttr(m_img_bitmaps[idx], + P96BMA_MEMORY)); + int bpr = IP96->p96GetBitMapAttr(m_img_bitmaps[idx], + P96BMA_BYTESPERROW); + int stride = (m_flip_y) ? -bpr : bpr; + + rbuf->attach(buf, width, height, stride); + + return true; + } + + return false; + } + + //------------------------------------------------------------------------ + bool platform_specific::make_bitmap() + { + uint32 width = 0; + uint32 height = 0; + IIntuition->GetWindowAttrs(m_window, + WA_InnerWidth, &width, + WA_InnerHeight, &height, + TAG_END); + + BitMap* bm = IP96->p96AllocBitMap(width, height, m_bpp, + BMF_USERPRIVATE|BMF_CLEAR, 0, m_ftype); + if ( bm == 0 ) + { + return false; + } + + int8u* buf = reinterpret_cast( + IP96->p96GetBitMapAttr(bm, P96BMA_MEMORY)); + int bpr = IP96->p96GetBitMapAttr(bm, P96BMA_BYTESPERROW); + int stride = (m_flip_y) ? -bpr : bpr; + + m_support.rbuf_window().attach(buf, width, height, stride); + + if ( m_bitmap != 0 ) + { + IP96->p96FreeBitMap(m_bitmap); + m_bitmap = 0; + } + + m_bitmap = bm; + m_width = width; + m_height = height; + + return true; + } + + //------------------------------------------------------------------------ + platform_support::platform_support(pix_format_e format, bool flip_y) : + m_specific(new platform_specific(*this, format, flip_y)), + m_format(format), + m_bpp(m_specific->m_bpp), + m_window_flags(0), + m_wait_mode(true), + m_flip_y(flip_y), + m_initial_width(10), + m_initial_height(10) + { + std::strncpy(m_caption, "Anti-Grain Geometry", 256); + } + + //------------------------------------------------------------------------ + platform_support::~platform_support() + { + delete m_specific; + } + + //------------------------------------------------------------------------ + void platform_support::caption(const char* cap) + { + std::strncpy(m_caption, cap, 256); + if ( m_specific->m_window != 0 ) + { + const char* ignore = reinterpret_cast(-1); + IIntuition->SetWindowAttr(m_specific->m_window, + WA_Title, m_caption, sizeof(char*)); + } + } + + //------------------------------------------------------------------------ + void platform_support::start_timer() + { + timeval tv; + gettimeofday(&tv, 0); + m_specific->m_start_time = tv.tv_secs + tv.tv_micro/1e6; + } + + //------------------------------------------------------------------------ + double platform_support::elapsed_time() const + { + timeval tv; + gettimeofday(&tv, 0); + double end_time = tv.tv_secs + tv.tv_micro/1e6; + + double elasped_seconds = end_time - m_specific->m_start_time; + double elasped_millis = elasped_seconds*1e3; + + return elasped_millis; + } + + //------------------------------------------------------------------------ + void* platform_support::raw_display_handler() + { + return 0; // Not available. + } + + //------------------------------------------------------------------------ + void platform_support::message(const char* msg) + { + APTR req = IIntuition->NewObject(RequesterClass, 0, + REQ_TitleText, "Anti-Grain Geometry", + REQ_Image, REQIMAGE_INFO, + REQ_BodyText, msg, + REQ_GadgetText, "_Ok", + TAG_END); + if ( req == 0 ) + { + IDOS->Printf("Message: %s\n", msg); + return; + } + + orRequest reqmsg; + reqmsg.MethodID = RM_OPENREQ; + reqmsg.or_Attrs = 0; + reqmsg.or_Window = m_specific->m_window; + reqmsg.or_Screen = 0; + + IIntuition->IDoMethodA(reinterpret_cast(req), + reinterpret_cast(&reqmsg)); + IIntuition->DisposeObject(req); + } + + //------------------------------------------------------------------------ + bool platform_support::init(unsigned width, unsigned height, + unsigned flags) + { + if( m_specific->m_ftype == RGBFB_NONE ) + { + message("Unsupported mode requested."); + return false; + } + + m_window_flags = flags; + + m_specific->m_idcmp_hook = reinterpret_cast( + IExec->AllocSysObjectTags(ASOT_HOOK, + ASOHOOK_Entry, handle_idcmp, + ASOHOOK_Data, this, + TAG_END)); + if ( m_specific->m_idcmp_hook == 0 ) + { + return false; + } + + m_specific->m_window_obj = IIntuition->NewObject(WindowClass, 0, + WA_Title, m_caption, + WA_AutoAdjustDClip, TRUE, + WA_InnerWidth, width, + WA_InnerHeight, height, + WA_Activate, TRUE, + WA_SmartRefresh, TRUE, + WA_NoCareRefresh, TRUE, + WA_CloseGadget, TRUE, + WA_DepthGadget, TRUE, + WA_SizeGadget, (flags & agg::window_resize) ? TRUE : FALSE, + WA_DragBar, TRUE, + WA_AutoAdjust, TRUE, + WA_ReportMouse, TRUE, + WA_RMBTrap, TRUE, + WA_MouseQueue, 1, + WA_IDCMP, + IDCMP_NEWSIZE | + IDCMP_MOUSEBUTTONS | + IDCMP_MOUSEMOVE | + IDCMP_RAWKEY | + IDCMP_INTUITICKS, + WINDOW_IDCMPHook, m_specific->m_idcmp_hook, + WINDOW_IDCMPHookBits, + IDCMP_MOUSEBUTTONS | + IDCMP_MOUSEMOVE | + IDCMP_RAWKEY, + TAG_END); + if ( m_specific->m_window_obj == 0 ) + { + return false; + } + + Object* obj = reinterpret_cast(m_specific->m_window_obj); + m_specific->m_window = + reinterpret_cast(IIntuition->IDoMethod(obj, WM_OPEN)); + if ( m_specific->m_window == 0 ) + { + return false; + } + + RGBFTYPE ftype = static_cast(IP96->p96GetBitMapAttr( + m_specific->m_window->RPort->BitMap, P96BMA_RGBFORMAT)); + + switch ( ftype ) + { + case RGBFB_A8R8G8B8: + case RGBFB_B8G8R8A8: + case RGBFB_R5G6B5PC: + break; + default: + message("Unsupported screen mode.\n"); + return false; + } + + if ( !m_specific->make_bitmap() ) + { + return false; + } + + m_initial_width = width; + m_initial_height = height; + + on_init(); + on_resize(width, height); + force_redraw(); + + return true; + } + + //------------------------------------------------------------------------ + int platform_support::run() + { + uint32 window_mask = 0; + IIntuition->GetAttr(WINDOW_SigMask, m_specific->m_window_obj, + &window_mask); + uint32 wait_mask = window_mask | SIGBREAKF_CTRL_C; + + bool done = false; + + while ( !done ) + { + uint32 sig_mask = IExec->Wait(wait_mask); + if ( sig_mask & SIGBREAKF_CTRL_C ) + { + done = true; + } + else + { + done = m_specific->handle_input(); + } + } + + return 0; + } + + //------------------------------------------------------------------------ + const char* platform_support::img_ext() const + { + return ".bmp"; + } + + //------------------------------------------------------------------------ + const char* platform_support::full_file_name(const char* file_name) + { + return file_name; + } + + //------------------------------------------------------------------------ + bool platform_support::load_img(unsigned idx, const char* file) + { + if ( idx < max_images ) + { + static char fn[1024]; + std::strncpy(fn, file, 1024); + int len = std::strlen(fn); + if ( len < 4 || std::strcmp(fn + len - 4, ".bmp") != 0 ) + { + std::strncat(fn, ".bmp", 1024); + } + + return m_specific->load_img(fn, idx, &m_rbuf_img[idx]); + } + + return false; + } + + //------------------------------------------------------------------------ + bool platform_support::save_img(unsigned idx, const char* file) + { + message("Not supported"); + return false; + } + + //------------------------------------------------------------------------ + bool platform_support::create_img(unsigned idx, unsigned width, + unsigned height) + { + if ( idx < max_images ) + { + if ( width == 0 ) + { + width = m_specific->m_width; + } + + if ( height == 0 ) + { + height = m_specific->m_height; + } + + return m_specific->create_img(idx, &m_rbuf_img[idx], width, + height); + } + + return false; + } + + //------------------------------------------------------------------------ + void platform_support::force_redraw() + { + on_draw(); + update_window(); + } + + //------------------------------------------------------------------------ + void platform_support::update_window() + { + // Note this function does automatic color conversion. + IGraphics->BltBitMapRastPort(m_specific->m_bitmap, 0, 0, + m_specific->m_window->RPort, m_specific->m_window->BorderLeft, + m_specific->m_window->BorderTop, m_specific->m_width, + m_specific->m_height, ABC|ABNC); + } + + //------------------------------------------------------------------------ + void platform_support::on_init() {} + void platform_support::on_resize(int sx, int sy) {} + void platform_support::on_idle() {} + void platform_support::on_mouse_move(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {} + void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {} + void platform_support::on_ctrl_change() {} + void platform_support::on_draw() {} + void platform_support::on_post_draw(void* raw_handler) {} + + //------------------------------------------------------------------------ + void handle_idcmp(Hook* hook, APTR obj, IntuiMessage* msg) + { + platform_support* app = + reinterpret_cast(hook->h_Data); + Window* window = app->m_specific->m_window; + + int16 x = msg->MouseX - window->BorderLeft; + + int16 y = 0; + if ( app->flip_y() ) + { + y = window->Height - window->BorderBottom - msg->MouseY; + } + else + { + y = msg->MouseY - window->BorderTop; + } + + switch ( msg->Class ) + { + case IDCMP_MOUSEBUTTONS: + if ( msg->Code & IECODE_UP_PREFIX ) + { + if ( msg->Code == SELECTUP ) + { + app->m_specific->m_input_flags = mouse_left; + app->m_specific->m_dragging = false; + } + else if ( msg->Code == MENUUP ) + { + app->m_specific->m_input_flags = mouse_right; + app->m_specific->m_dragging = false; + } + else + { + return; + } + + + if ( app->m_ctrls.on_mouse_button_up(x, y) ) + { + app->on_ctrl_change(); + app->force_redraw(); + } + + app->on_mouse_button_up(x, y, app->m_specific->m_input_flags); + } + else + { + if ( msg->Code == SELECTDOWN ) + { + app->m_specific->m_input_flags = mouse_left; + app->m_specific->m_dragging = true; + } + else if ( msg->Code == MENUDOWN ) + { + app->m_specific->m_input_flags = mouse_right; + app->m_specific->m_dragging = true; + } + else + { + return; + } + + app->m_ctrls.set_cur(x, y); + if ( app->m_ctrls.on_mouse_button_down(x, y) ) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + if ( app->m_ctrls.in_rect(x, y) ) + { + if ( app->m_ctrls.set_cur(x, y) ) + { + app->on_ctrl_change(); + app->force_redraw(); + } + } + else + { + app->on_mouse_button_down(x, y, + app->m_specific->m_input_flags); + } + } + } + break; + case IDCMP_MOUSEMOVE: + if ( app->m_specific->m_dragging ) { + if ( app->m_ctrls.on_mouse_move(x, y, + app->m_specific->m_input_flags & mouse_left) != 0 ) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + if ( !app->m_ctrls.in_rect(x, y) ) + { + app->on_mouse_move(x, y, + app->m_specific->m_input_flags); + } + } + } + break; + case IDCMP_RAWKEY: + { + static InputEvent ie = { 0 }; + ie.ie_Class = IECLASS_RAWKEY; + ie.ie_Code = msg->Code; + ie.ie_Qualifier = msg->Qualifier; + + static const unsigned BUF_SIZE = 16; + static char key_buf[BUF_SIZE]; + int16 num_chars = IKeymap->MapRawKey(&ie, key_buf, BUF_SIZE, 0); + + uint32 code = 0x00000000; + switch ( num_chars ) + { + case 1: + code = key_buf[0]; + break; + case 2: + code = key_buf[0]<<8 | key_buf[1]; + break; + case 3: + code = key_buf[0]<<16 | key_buf[1]<<8 | key_buf[2]; + break; + } + + uint16 key_code = 0; + + if ( num_chars == 1 ) + { + if ( code >= IECODE_ASCII_FIRST && code <= IECODE_ASCII_LAST ) + { + key_code = code; + } + } + + if ( key_code == 0 ) + { + switch ( code ) + { + case 0x00000008: key_code = key_backspace; break; + case 0x00000009: key_code = key_tab; break; + case 0x0000000D: key_code = key_return; break; + case 0x0000001B: key_code = key_escape; break; + case 0x0000007F: key_code = key_delete; break; + case 0x00009B41: + case 0x00009B54: key_code = key_up; break; + case 0x00009B42: + case 0x00009B53: key_code = key_down; break; + case 0x00009B43: + case 0x009B2040: key_code = key_right; break; + case 0x00009B44: + case 0x009B2041: key_code = key_left; break; + case 0x009B307E: key_code = key_f1; break; + case 0x009B317E: key_code = key_f2; break; + case 0x009B327E: key_code = key_f3; break; + case 0x009B337E: key_code = key_f4; break; + case 0x009B347E: key_code = key_f5; break; + case 0x009B357E: key_code = key_f6; break; + case 0x009B367E: key_code = key_f7; break; + case 0x009B377E: key_code = key_f8; break; + case 0x009B387E: key_code = key_f9; break; + case 0x009B397E: key_code = key_f10; break; + case 0x009B3F7E: key_code = key_scrollock; break; + } + } + + if ( ie.ie_Code & IECODE_UP_PREFIX ) + { + if ( app->m_specific->m_last_key != 0 ) + { + bool left = (key_code == key_left) ? true : false; + bool right = (key_code == key_right) ? true : false; + bool down = (key_code == key_down) ? true : false; + bool up = (key_code == key_up) ? true : false; + + if ( app->m_ctrls.on_arrow_keys(left, right, down, up) ) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + app->on_key(x, y, app->m_specific->m_last_key, 0); + } + + app->m_specific->m_last_key = 0; + } + } + else + { + app->m_specific->m_last_key = key_code; + } + break; + } + default: + break; + } + } +} + +//---------------------------------------------------------------------------- +int agg_main(int argc, char* argv[]); +bool open_libs(); +void close_libs(); + +//---------------------------------------------------------------------------- +bool open_libs() +{ + DataTypesBase = IExec->OpenLibrary("datatypes.library", 51); + GraphicsBase = IExec->OpenLibrary("graphics.library", 51); + IntuitionBase = IExec->OpenLibrary("intuition.library", 51); + KeymapBase = IExec->OpenLibrary("keymap.library", 51); + P96Base = IExec->OpenLibrary("Picasso96API.library", 2); + + IDataTypes = reinterpret_cast( + IExec->GetInterface(DataTypesBase, "main", 1, 0)); + IGraphics = reinterpret_cast( + IExec->GetInterface(GraphicsBase, "main", 1, 0)); + IIntuition = reinterpret_cast( + IExec->GetInterface(IntuitionBase, "main", 1, 0)); + IKeymap = reinterpret_cast( + IExec->GetInterface(KeymapBase, "main", 1, 0)); + IP96 = reinterpret_cast( + IExec->GetInterface(P96Base, "main", 1, 0)); + + if ( IDataTypes == 0 || + IGraphics == 0 || + IIntuition == 0 || + IKeymap == 0 || + IP96 == 0 ) + { + close_libs(); + return false; + } + else + { + return true; + } +} + +//---------------------------------------------------------------------------- +void close_libs() +{ + IExec->DropInterface(reinterpret_cast(IP96)); + IExec->DropInterface(reinterpret_cast(IKeymap)); + IExec->DropInterface(reinterpret_cast(IIntuition)); + IExec->DropInterface(reinterpret_cast(IGraphics)); + IExec->DropInterface(reinterpret_cast(IDataTypes)); + + IExec->CloseLibrary(P96Base); + IExec->CloseLibrary(KeymapBase); + IExec->CloseLibrary(IntuitionBase); + IExec->CloseLibrary(GraphicsBase); + IExec->CloseLibrary(DataTypesBase); +} + +//---------------------------------------------------------------------------- +int main(int argc, char* argv[]) +{ + if ( !open_libs() ) { + IDOS->Printf("Can't open libraries.\n"); + return -1; + } + + ClassLibrary* requester = + IIntuition->OpenClass("requester.class", 51, &RequesterClass); + ClassLibrary* window = + IIntuition->OpenClass("window.class", 51, &WindowClass); + if ( requester == 0 || window == 0 ) + { + IDOS->Printf("Can't open classes.\n"); + IIntuition->CloseClass(requester); + IIntuition->CloseClass(window); + close_libs(); + return -1; + } + + int rc = agg_main(argc, argv); + + IIntuition->CloseClass(window); + IIntuition->CloseClass(requester); + close_libs(); + + return rc; +} diff --git a/agg/src/platform/BeOS/Makefile.am b/agg/src/platform/BeOS/Makefile.am new file mode 100644 index 0000000..474153c --- /dev/null +++ b/agg/src/platform/BeOS/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST=agg_platform_support.cpp diff --git a/agg/src/platform/BeOS/agg_platform_support.cpp b/agg/src/platform/BeOS/agg_platform_support.cpp new file mode 100644 index 0000000..3f87aa0 --- /dev/null +++ b/agg/src/platform/BeOS/agg_platform_support.cpp @@ -0,0 +1,990 @@ +//---------------------------------------------------------------------------- +// 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. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: superstippi@gmx.de +//---------------------------------------------------------------------------- +// +// class platform_support +// +//---------------------------------------------------------------------------- + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "platform/agg_platform_support.h" +#include "util/agg_color_conv_rgb8.h" + +using std::nothrow; + + +static void +attach_buffer_to_BBitmap(agg::rendering_buffer& buffer, BBitmap* bitmap, bool flipY) +{ + uint8* bits = (uint8*)bitmap->Bits(); + uint32 width = bitmap->Bounds().IntegerWidth() + 1; + uint32 height = bitmap->Bounds().IntegerHeight() + 1; + int32 bpr = bitmap->BytesPerRow(); + if (flipY) { +// XXX: why don't I have to do this?!? +// bits += bpr * (height - 1); + bpr = -bpr; + } + buffer.attach(bits, width, height, bpr); +} + + +static color_space +pix_format_to_color_space(agg::pix_format_e format) +{ + color_space bitmapFormat = B_NO_COLOR_SPACE; + switch (format) { + case agg::pix_format_rgb555: + + bitmapFormat = B_RGB15; + break; + + case agg::pix_format_rgb565: + + bitmapFormat = B_RGB16; + break; + + case agg::pix_format_rgb24: + case agg::pix_format_bgr24: + + bitmapFormat = B_RGB24; + break; + + case agg::pix_format_rgba32: + case agg::pix_format_argb32: + case agg::pix_format_abgr32: + case agg::pix_format_bgra32: + + bitmapFormat = B_RGBA32; + break; + } + return bitmapFormat; +} + + +// #pragma mark - + + +class AGGView : public BView { + public: + AGGView(BRect frame, agg::platform_support* agg, + agg::pix_format_e format, bool flipY); + virtual ~AGGView(); + + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + + virtual void MessageReceived(BMessage* message); + virtual void Draw(BRect updateRect); + virtual void FrameResized(float width, float height); + + virtual void KeyDown(const char* bytes, int32 numBytes); + + virtual void MouseDown(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMesage); + virtual void MouseUp(BPoint where); + + BBitmap* Bitmap() const; + + uint8 LastKeyDown() const; + uint32 MouseButtons(); + + void Update(); + void ForceRedraw(); + + unsigned GetKeyFlags(); + + private: + BBitmap* fBitmap; + agg::pix_format_e fFormat; + bool fFlipY; + + agg::platform_support* fAGG; + + uint32 fMouseButtons; + int32 fMouseX; + int32 fMouseY; + + uint8 fLastKeyDown; + + bool fRedraw; + + BMessageRunner* fPulse; + bigtime_t fLastPulse; + bool fEnableTicks; +}; + +AGGView::AGGView(BRect frame, + agg::platform_support* agg, + agg::pix_format_e format, + bool flipY) + : BView(frame, "AGG View", B_FOLLOW_ALL, + B_FRAME_EVENTS | B_WILL_DRAW), + fFormat(format), + fFlipY(flipY), + + fAGG(agg), + + fMouseButtons(0), + fMouseX(-1), + fMouseY(-1), + + fLastKeyDown(0), + + fRedraw(true), + + fPulse(NULL), + fLastPulse(0), + fEnableTicks(true) +{ + SetViewColor(B_TRANSPARENT_32_BIT); + + frame.OffsetTo(0.0, 0.0); + fBitmap = new BBitmap(frame, 0, pix_format_to_color_space(fFormat)); + if (fBitmap->IsValid()) { + attach_buffer_to_BBitmap(fAGG->rbuf_window(), fBitmap, fFlipY); + } else { + delete fBitmap; + fBitmap = NULL; + } +} + + +AGGView::~AGGView() +{ + delete fBitmap; + delete fPulse; +} + + +void +AGGView::AttachedToWindow() +{ + BMessage message('tick'); + BMessenger target(this, Looper()); + delete fPulse; +// BScreen screen; +// TODO: calc screen retrace + fPulse = new BMessageRunner(target, &message, 40000); + + // make sure we call this once + fAGG->on_resize(Bounds().IntegerWidth() + 1, + Bounds().IntegerHeight() + 1); + MakeFocus(); +} + + +void +AGGView::DetachedFromWindow() +{ + delete fPulse; + fPulse = NULL; +} + + +void +AGGView::MessageReceived(BMessage* message) +{ + bigtime_t now = system_time(); + switch (message->what) { + case 'tick': + // drop messages that have piled up + if (/*now - fLastPulse > 30000*/fEnableTicks) { + fLastPulse = now; + if (!fAGG->wait_mode()) + fAGG->on_idle(); + Window()->PostMessage('entk', this); + fEnableTicks = false; + } else { +// printf("dropping tick message (%lld)\n", now - fLastPulse); + } + break; + case 'entk': + fEnableTicks = true; + if (now - fLastPulse > 30000) { + fLastPulse = now; + if (!fAGG->wait_mode()) + fAGG->on_idle(); + } + break; + default: + BView::MessageReceived(message); + break; + } +} + + +void +AGGView::Draw(BRect updateRect) +{ + if (fBitmap) { + if (fRedraw) { + fAGG->on_draw(); + fRedraw = false; + } + if (fFormat == agg::pix_format_bgra32) { + DrawBitmap(fBitmap, updateRect, updateRect); + } else { + BBitmap* bitmap = new BBitmap(fBitmap->Bounds(), 0, B_RGBA32); + + agg::rendering_buffer rbufSrc; + attach_buffer_to_BBitmap(rbufSrc, fBitmap, false); + + agg::rendering_buffer rbufDst; + attach_buffer_to_BBitmap(rbufDst, bitmap, false); + + switch(fFormat) { + case agg::pix_format_rgb555: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_rgb555_to_bgra32()); + break; + case agg::pix_format_rgb565: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_rgb565_to_bgra32()); + break; + case agg::pix_format_rgb24: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_rgb24_to_bgra32()); + break; + case agg::pix_format_bgr24: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_bgr24_to_bgra32()); + break; + case agg::pix_format_rgba32: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_rgba32_to_bgra32()); + break; + case agg::pix_format_argb32: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_argb32_to_bgra32()); + break; + case agg::pix_format_abgr32: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_abgr32_to_bgra32()); + break; + case agg::pix_format_bgra32: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_bgra32_to_bgra32()); + break; + } + DrawBitmap(bitmap, updateRect, updateRect); + delete bitmap; + } + } else { + FillRect(updateRect); + } +} + + +void +AGGView::FrameResized(float width, float height) +{ + BRect r(0.0, 0.0, width, height); + BBitmap* bitmap = new BBitmap(r, 0, pix_format_to_color_space(fFormat)); + if (bitmap->IsValid()) { + delete fBitmap; + fBitmap = bitmap; + attach_buffer_to_BBitmap(fAGG->rbuf_window(), fBitmap, fFlipY); + + fAGG->trans_affine_resizing((int)width + 1, + (int)height + 1); + + // pass the event on to AGG + fAGG->on_resize((int)width + 1, (int)height + 1); + + fRedraw = true; + Invalidate(); + } else + delete bitmap; +} + + +void +AGGView::KeyDown(const char* bytes, int32 numBytes) +{ + if (bytes && numBytes > 0) { + fLastKeyDown = bytes[0]; + + bool left = false; + bool up = false; + bool right = false; + bool down = false; + + switch (fLastKeyDown) { + + case B_LEFT_ARROW: + left = true; + break; + + case B_UP_ARROW: + up = true; + break; + + case B_RIGHT_ARROW: + right = true; + break; + + case B_DOWN_ARROW: + down = true; + break; + } + +/* case key_f2: +fAGG->copy_window_to_img(agg::platform_support::max_images - 1); +fAGG->save_img(agg::platform_support::max_images - 1, "screenshot"); +break; +}*/ + + + if (fAGG->m_ctrls.on_arrow_keys(left, right, down, up)) { + fAGG->on_ctrl_change(); + fAGG->force_redraw(); + } else { + fAGG->on_key(fMouseX, fMouseY, fLastKeyDown, GetKeyFlags()); + } +// fAGG->on_key(fMouseX, fMouseY, fLastKeyDown, GetKeyFlags()); + + } +} + + +void +AGGView::MouseDown(BPoint where) +{ + BMessage* currentMessage = Window()->CurrentMessage(); + if (currentMessage) { + if (currentMessage->FindInt32("buttons", (int32*)&fMouseButtons) < B_OK) + fMouseButtons = B_PRIMARY_MOUSE_BUTTON; + } else + fMouseButtons = B_PRIMARY_MOUSE_BUTTON; + + fMouseX = (int)where.x; + fMouseY = fFlipY ? (int)(Bounds().Height() - where.y) : (int)where.y; + + // pass the event on to AGG + if (fMouseButtons == B_PRIMARY_MOUSE_BUTTON) { + // left mouse button -> see if to handle in controls + fAGG->m_ctrls.set_cur(fMouseX, fMouseY); + if (fAGG->m_ctrls.on_mouse_button_down(fMouseX, fMouseY)) { + fAGG->on_ctrl_change(); + fAGG->force_redraw(); + } else { + if (fAGG->m_ctrls.in_rect(fMouseX, fMouseY)) { + if (fAGG->m_ctrls.set_cur(fMouseX, fMouseY)) { + fAGG->on_ctrl_change(); + fAGG->force_redraw(); + } + } else { + fAGG->on_mouse_button_down(fMouseX, fMouseY, GetKeyFlags()); + } + } + } else if (fMouseButtons & B_SECONDARY_MOUSE_BUTTON) { + // right mouse button -> simple + fAGG->on_mouse_button_down(fMouseX, fMouseY, GetKeyFlags()); + } + SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); +} + + +void +AGGView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMesage) +{ + // workarround missed mouse up events + // (if we react too slowly, app_server might have dropped events) + BMessage* currentMessage = Window()->CurrentMessage(); + int32 buttons = 0; + if (currentMessage->FindInt32("buttons", &buttons) < B_OK) { + buttons = 0; + } + if (!buttons) + MouseUp(where); + + fMouseX = (int)where.x; + fMouseY = fFlipY ? (int)(Bounds().Height() - where.y) : (int)where.y; + + // pass the event on to AGG + if (fAGG->m_ctrls.on_mouse_move(fMouseX, fMouseY, + (GetKeyFlags() & agg::mouse_left) != 0)) { + fAGG->on_ctrl_change(); + fAGG->force_redraw(); + } else { + if (!fAGG->m_ctrls.in_rect(fMouseX, fMouseY)) { + fAGG->on_mouse_move(fMouseX, fMouseY, GetKeyFlags()); + } + } +} + + +void +AGGView::MouseUp(BPoint where) +{ + fMouseX = (int)where.x; + fMouseY = fFlipY ? (int)(Bounds().Height() - where.y) : (int)where.y; + + // pass the event on to AGG + if (fMouseButtons == B_PRIMARY_MOUSE_BUTTON) { + fMouseButtons = 0; + + if (fAGG->m_ctrls.on_mouse_button_up(fMouseX, fMouseY)) { + fAGG->on_ctrl_change(); + fAGG->force_redraw(); + } + fAGG->on_mouse_button_up(fMouseX, fMouseY, GetKeyFlags()); + } else if (fMouseButtons == B_SECONDARY_MOUSE_BUTTON) { + fMouseButtons = 0; + + fAGG->on_mouse_button_up(fMouseX, fMouseY, GetKeyFlags()); + } +} + + +BBitmap* +AGGView::Bitmap() const +{ + return fBitmap; +} + + +uint8 +AGGView::LastKeyDown() const +{ + return fLastKeyDown; +} + + +uint32 +AGGView::MouseButtons() +{ + uint32 buttons = 0; + if (LockLooper()) { + buttons = fMouseButtons; + UnlockLooper(); + } + return buttons; +} + + +void +AGGView::Update() +{ + // trigger display update + if (LockLooper()) { + Invalidate(); + UnlockLooper(); + } +} + + +void +AGGView::ForceRedraw() +{ + // force a redraw (fRedraw = true;) + // and trigger display update + if (LockLooper()) { + fRedraw = true; + Invalidate(); + UnlockLooper(); + } +} + + +unsigned +AGGView::GetKeyFlags() +{ + uint32 buttons = fMouseButtons; + uint32 mods = modifiers(); + unsigned flags = 0; + if (buttons & B_PRIMARY_MOUSE_BUTTON) flags |= agg::mouse_left; + if (buttons & B_SECONDARY_MOUSE_BUTTON) flags |= agg::mouse_right; + if (mods & B_SHIFT_KEY) flags |= agg::kbd_shift; + if (mods & B_COMMAND_KEY) flags |= agg::kbd_ctrl; + return flags; +} + +// #pragma mark - + + +class AGGWindow : public BWindow { + public: + AGGWindow() + : BWindow(BRect(-50.0, -50.0, -10.0, -10.0), + "AGG Application", B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS) + { + } + + virtual bool QuitRequested() + { + be_app->PostMessage(B_QUIT_REQUESTED); + return true; + } + + bool Init(BRect frame, agg::platform_support* agg, agg::pix_format_e format, + bool flipY, uint32 flags) + { + MoveTo(frame.LeftTop()); + ResizeTo(frame.Width(), frame.Height()); + + SetFlags(flags); + + frame.OffsetTo(0.0, 0.0); + fView = new AGGView(frame, agg, format, flipY); + AddChild(fView); + + return fView->Bitmap() != NULL; + } + + + AGGView* View() const + { + return fView; + } + private: + AGGView* fView; +}; + +// #pragma mark - + + +class AGGApplication : public BApplication { + public: + AGGApplication() + : BApplication("application/x-vnd.AGG-AGG") + { + fWindow = new AGGWindow(); + } + + virtual void ReadyToRun() + { + if (fWindow) { + fWindow->Show(); + } + } + + virtual bool Init(agg::platform_support* agg, int width, int height, + agg::pix_format_e format, bool flipY, uint32 flags) + { + BRect r(50.0, 50.0, + 50.0 + width - 1.0, + 50.0 + height - 1.0); + uint32 windowFlags = B_ASYNCHRONOUS_CONTROLS; + if (!(flags & agg::window_resize)) + windowFlags |= B_NOT_RESIZABLE; + + return fWindow->Init(r, agg, format, flipY, windowFlags);; + } + + + AGGWindow* Window() const + { + return fWindow; + } + + private: + AGGWindow* fWindow; +}; + + +// #pragma mark - + + +namespace agg +{ + +class platform_specific { + public: + platform_specific(agg::platform_support* agg, + agg::pix_format_e format, bool flip_y) + : fAGG(agg), + fApp(NULL), + fFormat(format), + fFlipY(flip_y), + fTimerStart(system_time()) + { + memset(fImages, 0, sizeof(fImages)); + fApp = new AGGApplication(); + fAppPath[0] = 0; + // figure out where we're running from + app_info info; + status_t ret = fApp->GetAppInfo(&info); + if (ret >= B_OK) { + BPath path(&info.ref); + ret = path.InitCheck(); + if (ret >= B_OK) { + ret = path.GetParent(&path); + if (ret >= B_OK) { + std::sprintf(fAppPath, "%s", path.Path()); + } else { + std::fprintf(stderr, "getting app parent folder failed: %s\n", std::strerror(ret)); + } + } else { + std::fprintf(stderr, "making app path failed: %s\n", std::strerror(ret)); + } + } else { + std::fprintf(stderr, "GetAppInfo() failed: %s\n", std::strerror(ret)); + } + } + ~platform_specific() + { + for (int32 i = 0; i < agg::platform_support::max_images; i++) + delete fImages[i]; + delete fApp; + } + + bool Init(int width, int height, unsigned flags) + { + return fApp->Init(fAGG, width, height, fFormat, fFlipY, flags); + } + + int Run() + { + status_t ret = B_NO_INIT; + if (fApp) { + fApp->Run(); + ret = B_OK; + } + return ret; + } + + void SetTitle(const char* title) + { + if (fApp && fApp->Window() && fApp->Window()->Lock()) { + fApp->Window()->SetTitle(title); + fApp->Window()->Unlock(); + } + } + void StartTimer() + { + fTimerStart = system_time(); + } + double ElapsedTime() const + { + return (system_time() - fTimerStart) / 1000.0; + } + + void ForceRedraw() + { + fApp->Window()->View()->ForceRedraw(); + } + void UpdateWindow() + { + fApp->Window()->View()->Update(); + } + + + agg::platform_support* fAGG; + AGGApplication* fApp; + agg::pix_format_e fFormat; + bool fFlipY; + bigtime_t fTimerStart; + BBitmap* fImages[agg::platform_support::max_images]; + + char fAppPath[B_PATH_NAME_LENGTH]; + char fFilePath[B_PATH_NAME_LENGTH]; +}; + + + //------------------------------------------------------------------------ + platform_support::platform_support(pix_format_e format, bool flip_y) : + m_specific(new platform_specific(this, format, flip_y)), + m_format(format), + m_bpp(32/*m_specific->m_bpp*/), + m_window_flags(0), + m_wait_mode(true), + m_flip_y(flip_y), + m_initial_width(10), + m_initial_height(10) + { + std::strcpy(m_caption, "Anti-Grain Geometry Application"); + } + + + //------------------------------------------------------------------------ + platform_support::~platform_support() + { + delete m_specific; + } + + //------------------------------------------------------------------------ + void platform_support::caption(const char* cap) + { + std::strcpy(m_caption, cap); + m_specific->SetTitle(cap); + } + + //------------------------------------------------------------------------ + void platform_support::start_timer() + { + m_specific->StartTimer(); + } + + //------------------------------------------------------------------------ + double platform_support::elapsed_time() const + { + return m_specific->ElapsedTime(); + } + + //------------------------------------------------------------------------ + void* platform_support::raw_display_handler() + { + // TODO: if we ever support BDirectWindow here, that would + // be the frame buffer pointer with offset to the window top left + return NULL; + } + + //------------------------------------------------------------------------ + void platform_support::message(const char* msg) + { + BAlert* alert = new BAlert("AGG Message", msg, "Ok"); + alert->Go(/*NULL*/); + } + + + //------------------------------------------------------------------------ + bool platform_support::init(unsigned width, unsigned height, unsigned flags) + { + m_initial_width = width; + m_initial_height = height; + m_window_flags = flags; + + if (m_specific->Init(width, height, flags)) { + on_init(); + return true; + } + + return false; + } + + + //------------------------------------------------------------------------ + int platform_support::run() + { + return m_specific->Run(); + } + + + //------------------------------------------------------------------------ + const char* platform_support::img_ext() const { return ".ppm"; } + + + const char* platform_support::full_file_name(const char* file_name) + { + std::sprintf(m_specific->fFilePath, "%s/%s", m_specific->fAppPath, file_name); + return m_specific->fFilePath; + } + + + //------------------------------------------------------------------------ + bool platform_support::load_img(unsigned idx, const char* file) + { + if (idx < max_images) + { + char path[B_PATH_NAME_LENGTH]; + std::sprintf(path, "%s/%s%s", m_specific->fAppPath, file, img_ext()); + BBitmap* transBitmap = BTranslationUtils::GetBitmap(path); + if (transBitmap && transBitmap->IsValid()) { + if(transBitmap->ColorSpace() != B_RGB32 && transBitmap->ColorSpace() != B_RGBA32) { + // ups we got a smart ass Translator making our live harder + delete transBitmap; + return false; + } + + color_space format = B_RGB24; + + switch (m_format) { + case pix_format_gray8: + format = B_GRAY8; + break; + case pix_format_rgb555: + format = B_RGB15; + break; + case pix_format_rgb565: + format = B_RGB16; + break; + case pix_format_rgb24: + format = B_RGB24_BIG; + break; + case pix_format_bgr24: + format = B_RGB24; + break; + case pix_format_abgr32: + case pix_format_argb32: + case pix_format_bgra32: + format = B_RGB32; + break; + case pix_format_rgba32: + format = B_RGB32_BIG; + break; + } + BBitmap* bitmap = new (nothrow) BBitmap(transBitmap->Bounds(), 0, format); + if (!bitmap || !bitmap->IsValid()) { + std::fprintf(stderr, "failed to allocate temporary bitmap!\n"); + delete transBitmap; + delete bitmap; + return false; + } + + delete m_specific->fImages[idx]; + + rendering_buffer rbuf_tmp; + attach_buffer_to_BBitmap(rbuf_tmp, transBitmap, m_flip_y); + + m_specific->fImages[idx] = bitmap; + + attach_buffer_to_BBitmap(m_rbuf_img[idx], bitmap, m_flip_y); + + rendering_buffer* dst = &m_rbuf_img[idx]; + + switch(m_format) + { + case pix_format_gray8: + return false; +// color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_gray8()); break; + break; + + case pix_format_rgb555: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb555()); break; + break; + + case pix_format_rgb565: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb565()); break; + break; + + case pix_format_rgb24: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb24()); break; + break; + + case pix_format_bgr24: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgr24()); break; + break; + + case pix_format_abgr32: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_abgr32()); break; + break; + + case pix_format_argb32: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_argb32()); break; + break; + + case pix_format_bgra32: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgra32()); break; + break; + + case pix_format_rgba32: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgba32()); break; + break; + } + delete transBitmap; + + return true; + + } else { + std::fprintf(stderr, "failed to load bitmap: '%s'\n", full_file_name(file)); + } + } + return false; + } + + + + //------------------------------------------------------------------------ + bool platform_support::save_img(unsigned idx, const char* file) + { + // TODO: implement using BTranslatorRoster and friends + return false; + } + + + + //------------------------------------------------------------------------ + bool platform_support::create_img(unsigned idx, unsigned width, unsigned height) + { + if(idx < max_images) + { + if(width == 0) width = m_specific->fApp->Window()->View()->Bitmap()->Bounds().IntegerWidth() + 1; + if(height == 0) height = m_specific->fApp->Window()->View()->Bitmap()->Bounds().IntegerHeight() + 1; + BBitmap* bitmap = new BBitmap(BRect(0.0, 0.0, width - 1, height - 1), 0, B_RGBA32);; + if (bitmap && bitmap->IsValid()) { + delete m_specific->fImages[idx]; + m_specific->fImages[idx] = bitmap; + attach_buffer_to_BBitmap(m_rbuf_img[idx], bitmap, m_flip_y); + return true; + } else { + delete bitmap; + } + } + return false; + } + + + //------------------------------------------------------------------------ + void platform_support::force_redraw() + { + m_specific->ForceRedraw(); + } + + + + //------------------------------------------------------------------------ + void platform_support::update_window() + { + m_specific->UpdateWindow(); + } + + + //------------------------------------------------------------------------ + void platform_support::on_init() {} + void platform_support::on_resize(int sx, int sy) {} + void platform_support::on_idle() {} + void platform_support::on_mouse_move(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {} + void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {} + void platform_support::on_ctrl_change() {} + void platform_support::on_draw() {} + void platform_support::on_post_draw(void* raw_handler) {} +} + + + + + + +//---------------------------------------------------------------------------- +int agg_main(int argc, char* argv[]); + + + +int +main(int argc, char* argv[]) +{ + return agg_main(argc, argv); +} + + + + diff --git a/agg/src/platform/X11/Makefile.am b/agg/src/platform/X11/Makefile.am new file mode 100644 index 0000000..57efcf2 --- /dev/null +++ b/agg/src/platform/X11/Makefile.am @@ -0,0 +1,8 @@ +if ENABLE_X11 +lib_LTLIBRARIES = libaggplatformX11.la + +libaggplatformX11_la_LDFLAGS = -version-info @AGG_LIB_VERSION@ +libaggplatformX11_la_SOURCES = agg_platform_support.cpp +libaggplatformX11_la_CXXFLAGS = -I$(top_srcdir)/include @x_includes@ +libaggplatformX11_la_LIBADD = -lX11 +endif diff --git a/agg2/src/platform/X11/agg_platform_support.cpp b/agg/src/platform/X11/agg_platform_support.cpp similarity index 60% rename from agg2/src/platform/X11/agg_platform_support.cpp rename to agg/src/platform/X11/agg_platform_support.cpp index d3a2502..e33382b 100644 --- a/agg2/src/platform/X11/agg_platform_support.cpp +++ b/agg/src/platform/X11/agg_platform_support.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -17,16 +17,19 @@ // //---------------------------------------------------------------------------- -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include #include #include #include "agg_basics.h" +#include "agg_pixfmt_gray.h" +#include "agg_pixfmt_rgb.h" +#include "agg_pixfmt_rgba.h" #include "util/agg_color_conv_rgb8.h" #include "platform/agg_platform_support.h" @@ -66,7 +69,7 @@ namespace agg bool m_resize_flag; bool m_initialized; //bool m_wait_mode; - clock_t m_sw_start; + std::clock_t m_sw_start; }; @@ -95,7 +98,7 @@ namespace agg m_initialized(false) //m_wait_mode(true) { - memset(m_buf_img, 0, sizeof(m_buf_img)); + std::memset(m_buf_img, 0, sizeof(m_buf_img)); unsigned i; for(i = 0; i < 256; i++) @@ -168,10 +171,20 @@ namespace agg switch(m_format) { + default: break; case pix_format_gray8: + case pix_format_sgray8: m_bpp = 8; break; + case pix_format_gray16: + m_bpp = 16; + break; + + case pix_format_gray32: + m_bpp = 32; + break; + case pix_format_rgb565: case pix_format_rgb555: m_bpp = 16; @@ -179,6 +192,8 @@ namespace agg case pix_format_rgb24: case pix_format_bgr24: + case pix_format_srgb24: + case pix_format_sbgr24: m_bpp = 24; break; @@ -186,10 +201,38 @@ namespace agg case pix_format_abgr32: case pix_format_argb32: case pix_format_rgba32: + case pix_format_sbgra32: + case pix_format_sabgr32: + case pix_format_sargb32: + case pix_format_srgba32: m_bpp = 32; break; + + case pix_format_rgb48: + case pix_format_bgr48: + m_bpp = 48; + break; + + case pix_format_bgra64: + case pix_format_abgr64: + case pix_format_argb64: + case pix_format_rgba64: + m_bpp = 64; + break; + + case pix_format_rgb96: + case pix_format_bgr96: + m_bpp = 96; + break; + + case pix_format_bgra128: + case pix_format_abgr128: + case pix_format_argb128: + case pix_format_rgba128: + m_bpp = 128; + break; } - m_sw_start = clock(); + m_sw_start = std::clock(); } //------------------------------------------------------------------------ @@ -204,7 +247,7 @@ namespace agg tp.value = (unsigned char *)capt; tp.encoding = XA_WM_NAME; tp.format = 8; - tp.nitems = strlen(capt); + tp.nitems = std::strlen(capt); XSetWMName(m_display, m_window, &tp); XStoreName(m_display, m_window, capt); XSetIconName(m_display, m_window, capt); @@ -242,9 +285,11 @@ namespace agg switch(m_sys_format) { + default: break; case pix_format_rgb555: switch(m_format) { + default: break; case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_rgb555()); break; case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgb555()); break; case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_rgb555()); break; @@ -259,6 +304,7 @@ namespace agg case pix_format_rgb565: switch(m_format) { + default: break; case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_rgb565()); break; case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgb565()); break; case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_rgb565()); break; @@ -273,56 +319,148 @@ namespace agg case pix_format_rgba32: switch(m_format) { - case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_rgba32()); break; - case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgba32()); break; - case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_rgba32()); break; - case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_rgba32()); break; - case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_rgba32()); break; - case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_rgba32()); break; - case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_rgba32()); break; - case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_rgba32()); break; + default: break; + case pix_format_sgray8: convert(&rbuf_tmp, src); break; + case pix_format_gray8: convert(&rbuf_tmp, src); break; + case pix_format_gray16: convert(&rbuf_tmp, src); break; + case pix_format_gray32: convert(&rbuf_tmp, src); break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_rgba32()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgba32()); break; + case pix_format_srgb24: convert(&rbuf_tmp, src); break; + case pix_format_sbgr24: convert(&rbuf_tmp, src); break; + case pix_format_rgb24: convert(&rbuf_tmp, src); break; + case pix_format_bgr24: convert(&rbuf_tmp, src); break; + case pix_format_srgba32: convert(&rbuf_tmp, src); break; + case pix_format_sargb32: convert(&rbuf_tmp, src); break; + case pix_format_sabgr32: convert(&rbuf_tmp, src); break; + case pix_format_sbgra32: convert(&rbuf_tmp, src); break; + case pix_format_rgba32: convert(&rbuf_tmp, src); break; + case pix_format_argb32: convert(&rbuf_tmp, src); break; + case pix_format_abgr32: convert(&rbuf_tmp, src); break; + case pix_format_bgra32: convert(&rbuf_tmp, src); break; + case pix_format_rgb48: convert(&rbuf_tmp, src); break; + case pix_format_bgr48: convert(&rbuf_tmp, src); break; + case pix_format_rgba64: convert(&rbuf_tmp, src); break; + case pix_format_argb64: convert(&rbuf_tmp, src); break; + case pix_format_abgr64: convert(&rbuf_tmp, src); break; + case pix_format_bgra64: convert(&rbuf_tmp, src); break; + case pix_format_rgb96: convert(&rbuf_tmp, src); break; + case pix_format_bgr96: convert(&rbuf_tmp, src); break; + case pix_format_rgba128: convert(&rbuf_tmp, src); break; + case pix_format_argb128: convert(&rbuf_tmp, src); break; + case pix_format_abgr128: convert(&rbuf_tmp, src); break; + case pix_format_bgra128: convert(&rbuf_tmp, src); break; } break; case pix_format_abgr32: switch(m_format) { + default: break; + case pix_format_sgray8: convert(&rbuf_tmp, src); break; + case pix_format_gray8: convert(&rbuf_tmp, src); break; + case pix_format_gray16: convert(&rbuf_tmp, src); break; + case pix_format_gray32: convert(&rbuf_tmp, src); break; case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_abgr32()); break; case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_abgr32()); break; - case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_abgr32()); break; - case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_abgr32()); break; - case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_abgr32()); break; - case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_abgr32()); break; - case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_abgr32()); break; - case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_abgr32()); break; + case pix_format_srgb24: convert(&rbuf_tmp, src); break; + case pix_format_sbgr24: convert(&rbuf_tmp, src); break; + case pix_format_rgb24: convert(&rbuf_tmp, src); break; + case pix_format_bgr24: convert(&rbuf_tmp, src); break; + case pix_format_srgba32: convert(&rbuf_tmp, src); break; + case pix_format_sargb32: convert(&rbuf_tmp, src); break; + case pix_format_sabgr32: convert(&rbuf_tmp, src); break; + case pix_format_sbgra32: convert(&rbuf_tmp, src); break; + case pix_format_rgba32: convert(&rbuf_tmp, src); break; + case pix_format_argb32: convert(&rbuf_tmp, src); break; + case pix_format_abgr32: convert(&rbuf_tmp, src); break; + case pix_format_bgra32: convert(&rbuf_tmp, src); break; + case pix_format_rgb48: convert(&rbuf_tmp, src); break; + case pix_format_bgr48: convert(&rbuf_tmp, src); break; + case pix_format_rgba64: convert(&rbuf_tmp, src); break; + case pix_format_argb64: convert(&rbuf_tmp, src); break; + case pix_format_abgr64: convert(&rbuf_tmp, src); break; + case pix_format_bgra64: convert(&rbuf_tmp, src); break; + case pix_format_rgb96: convert(&rbuf_tmp, src); break; + case pix_format_bgr96: convert(&rbuf_tmp, src); break; + case pix_format_rgba128: convert(&rbuf_tmp, src); break; + case pix_format_argb128: convert(&rbuf_tmp, src); break; + case pix_format_abgr128: convert(&rbuf_tmp, src); break; + case pix_format_bgra128: convert(&rbuf_tmp, src); break; } break; case pix_format_argb32: switch(m_format) { + default: break; + case pix_format_sgray8: convert(&rbuf_tmp, src); break; + case pix_format_gray8: convert(&rbuf_tmp, src); break; + case pix_format_gray16: convert(&rbuf_tmp, src); break; + case pix_format_gray32: convert(&rbuf_tmp, src); break; case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_argb32()); break; case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_argb32()); break; - case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_argb32()); break; - case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_argb32()); break; - case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_argb32()); break; - case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_argb32()); break; - case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_argb32()); break; - case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_argb32()); break; + case pix_format_srgb24: convert(&rbuf_tmp, src); break; + case pix_format_sbgr24: convert(&rbuf_tmp, src); break; + case pix_format_rgb24: convert(&rbuf_tmp, src); break; + case pix_format_bgr24: convert(&rbuf_tmp, src); break; + case pix_format_srgba32: convert(&rbuf_tmp, src); break; + case pix_format_sargb32: convert(&rbuf_tmp, src); break; + case pix_format_sabgr32: convert(&rbuf_tmp, src); break; + case pix_format_sbgra32: convert(&rbuf_tmp, src); break; + case pix_format_rgba32: convert(&rbuf_tmp, src); break; + case pix_format_argb32: convert(&rbuf_tmp, src); break; + case pix_format_abgr32: convert(&rbuf_tmp, src); break; + case pix_format_bgra32: convert(&rbuf_tmp, src); break; + case pix_format_rgb48: convert(&rbuf_tmp, src); break; + case pix_format_bgr48: convert(&rbuf_tmp, src); break; + case pix_format_rgba64: convert(&rbuf_tmp, src); break; + case pix_format_argb64: convert(&rbuf_tmp, src); break; + case pix_format_abgr64: convert(&rbuf_tmp, src); break; + case pix_format_bgra64: convert(&rbuf_tmp, src); break; + case pix_format_rgb96: convert(&rbuf_tmp, src); break; + case pix_format_bgr96: convert(&rbuf_tmp, src); break; + case pix_format_rgba128: convert(&rbuf_tmp, src); break; + case pix_format_argb128: convert(&rbuf_tmp, src); break; + case pix_format_abgr128: convert(&rbuf_tmp, src); break; + case pix_format_bgra128: convert(&rbuf_tmp, src); break; } break; case pix_format_bgra32: switch(m_format) { - case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_bgra32()); break; - case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_bgra32()); break; - case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_bgra32()); break; - case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_bgra32()); break; - case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_bgra32()); break; - case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_bgra32()); break; - case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_bgra32()); break; - case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_bgra32()); break; + default: break; + case pix_format_sgray8: convert(&rbuf_tmp, src); break; + case pix_format_gray8: convert(&rbuf_tmp, src); break; + case pix_format_gray16: convert(&rbuf_tmp, src); break; + case pix_format_gray32: convert(&rbuf_tmp, src); break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_bgra32()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_bgra32()); break; + case pix_format_srgb24: convert(&rbuf_tmp, src); break; + case pix_format_sbgr24: convert(&rbuf_tmp, src); break; + case pix_format_rgb24: convert(&rbuf_tmp, src); break; + case pix_format_bgr24: convert(&rbuf_tmp, src); break; + case pix_format_srgba32: convert(&rbuf_tmp, src); break; + case pix_format_sargb32: convert(&rbuf_tmp, src); break; + case pix_format_sabgr32: convert(&rbuf_tmp, src); break; + case pix_format_sbgra32: convert(&rbuf_tmp, src); break; + case pix_format_rgba32: convert(&rbuf_tmp, src); break; + case pix_format_argb32: convert(&rbuf_tmp, src); break; + case pix_format_abgr32: convert(&rbuf_tmp, src); break; + case pix_format_bgra32: convert(&rbuf_tmp, src); break; + case pix_format_rgb48: convert(&rbuf_tmp, src); break; + case pix_format_bgr48: convert(&rbuf_tmp, src); break; + case pix_format_rgba64: convert(&rbuf_tmp, src); break; + case pix_format_argb64: convert(&rbuf_tmp, src); break; + case pix_format_abgr64: convert(&rbuf_tmp, src); break; + case pix_format_bgra64: convert(&rbuf_tmp, src); break; + case pix_format_rgb96: convert(&rbuf_tmp, src); break; + case pix_format_bgr96: convert(&rbuf_tmp, src); break; + case pix_format_rgba128: convert(&rbuf_tmp, src); break; + case pix_format_argb128: convert(&rbuf_tmp, src); break; + case pix_format_abgr128: convert(&rbuf_tmp, src); break; + case pix_format_bgra128: convert(&rbuf_tmp, src); break; } break; } @@ -352,7 +490,7 @@ namespace agg m_initial_width(10), m_initial_height(10) { - strcpy(m_caption, "AGG Application"); + std::strcpy(m_caption, "AGG Application"); } //------------------------------------------------------------------------ @@ -366,7 +504,7 @@ namespace agg //------------------------------------------------------------------------ void platform_support::caption(const char* cap) { - strcpy(m_caption, cap); + std::strcpy(m_caption, cap); if(m_specific->m_initialized) { m_specific->caption(cap); @@ -375,7 +513,7 @@ namespace agg //------------------------------------------------------------------------ - enum + enum xevent_mask_e { xevent_mask = PointerMotionMask| @@ -395,7 +533,7 @@ namespace agg m_specific->m_display = XOpenDisplay(NULL); if(m_specific->m_display == 0) { - fprintf(stderr, "Unable to open DISPLAY!\n"); + std::fprintf(stderr, "Unable to open DISPLAY!\n"); return false; } @@ -408,7 +546,7 @@ namespace agg unsigned long g_mask = m_specific->m_visual->green_mask; unsigned long b_mask = m_specific->m_visual->blue_mask; -//printf("depth=%d, red=%08x, green=%08x, blue=%08x\n", +//std::printf("depth=%d, red=%08x, green=%08x, blue=%08x\n", // m_specific->m_depth, // m_specific->m_visual->red_mask, // m_specific->m_visual->green_mask, @@ -434,7 +572,7 @@ namespace agg // TrueColor, // &vi)) // { -// // printf("TrueColor depth=%d, red=%08x, green=%08x, blue=%08x, bits=%d\n", +// // std::printf("TrueColor depth=%d, red=%08x, green=%08x, blue=%08x, bits=%d\n", // // vi.depth, // // vi.visual->red_mask, // // vi.visual->green_mask, @@ -453,7 +591,7 @@ namespace agg // DirectColor, // &vi)) // { -// // printf("DirectColor depth=%d, red=%08x, green=%08x, blue=%08x, bits=%d\n", +// // std::printf("DirectColor depth=%d, red=%08x, green=%08x, blue=%08x, bits=%d\n", // // vi.depth, // // vi.visual->red_mask, // // vi.visual->green_mask, @@ -472,7 +610,7 @@ namespace agg if(m_specific->m_depth < 15 || r_mask == 0 || g_mask == 0 || b_mask == 0) { - fprintf(stderr, + std::fprintf(stderr, "There's no Visual compatible with minimal AGG requirements:\n" "At least 15-bit color depth and True- or DirectColor class.\n\n"); XCloseDisplay(m_specific->m_display); @@ -562,16 +700,16 @@ namespace agg if(m_specific->m_sys_format == pix_format_undefined) { - fprintf(stderr, + std::fprintf(stderr, "RGB masks are not compatible with AGG pixel formats:\n" - "R=%08x, R=%08x, B=%08x\n", r_mask, g_mask, b_mask); + "R=%08lx, R=%08lx, B=%08lx\n", r_mask, g_mask, b_mask); XCloseDisplay(m_specific->m_display); return false; } - memset(&m_specific->m_window_attributes, + std::memset(&m_specific->m_window_attributes, 0, sizeof(m_specific->m_window_attributes)); @@ -605,7 +743,7 @@ namespace agg m_specific->m_buf_window = new unsigned char[width * height * (m_bpp / 8)]; - memset(m_specific->m_buf_window, 255, width * height * (m_bpp / 8)); + std::memset(m_specific->m_buf_window, 255, width * height * (m_bpp / 8)); m_rbuf_window.attach(m_specific->m_buf_window, width, @@ -750,8 +888,8 @@ namespace agg { case ConfigureNotify: { - if(x_event.xconfigure.width != m_rbuf_window.width() || - x_event.xconfigure.height != m_rbuf_window.height()) + if(x_event.xconfigure.width != int(m_rbuf_window.width()) || + x_event.xconfigure.height != int(m_rbuf_window.height())) { int width = x_event.xconfigure.width; int height = x_event.xconfigure.height; @@ -956,7 +1094,7 @@ namespace agg case ClientMessage: if((x_event.xclient.format == 32) && - (x_event.xclient.data.l[0] == m_specific->m_close_atom)) + (x_event.xclient.data.l[0] == int(m_specific->m_close_atom))) { quit = true; } @@ -1001,17 +1139,17 @@ namespace agg if(idx < max_images) { char buf[1024]; - strcpy(buf, file); - int len = strlen(buf); + std::strcpy(buf, file); + int len = std::strlen(buf); if(len < 4 || strcasecmp(buf + len - 4, ".ppm") != 0) { - strcat(buf, ".ppm"); + std::strcat(buf, ".ppm"); } - FILE* fd = fopen(buf, "rb"); + FILE* fd = std::fopen(buf, "rb"); if(fd == 0) return false; - if((len = fread(buf, 1, 1022, fd)) == 0) + if((len = std::fread(buf, 1, 1022, fd)) == 0) { fclose(fd); return false; @@ -1020,60 +1158,62 @@ namespace agg if(buf[0] != 'P' && buf[1] != '6') { - fclose(fd); + std::fclose(fd); return false; } char* ptr = buf + 2; - while(*ptr && !isdigit(*ptr)) ptr++; + while(*ptr && !std::isdigit((unsigned char)(*ptr))) ptr++; if(*ptr == 0) { - fclose(fd); + std::fclose(fd); return false; } - unsigned width = atoi(ptr); + unsigned width = std::atoi(ptr); if(width == 0 || width > 4096) { - fclose(fd); + std::fclose(fd); return false; } - while(*ptr && isdigit(*ptr)) ptr++; - while(*ptr && !isdigit(*ptr)) ptr++; + while(*ptr && isdigit((unsigned char)(*ptr))) ptr++; + while(*ptr && !isdigit((unsigned char)(*ptr))) ptr++; if(*ptr == 0) { - fclose(fd); + std::fclose(fd); return false; } - unsigned height = atoi(ptr); + unsigned height = std::atoi(ptr); if(height == 0 || height > 4096) { - fclose(fd); + std::fclose(fd); return false; } - while(*ptr && isdigit(*ptr)) ptr++; - while(*ptr && !isdigit(*ptr)) ptr++; - if(atoi(ptr) != 255) + while(*ptr && isdigit((unsigned char)(*ptr))) ptr++; + while(*ptr && !isdigit((unsigned char)(*ptr))) ptr++; + if(std::atoi(ptr) != 255) { - fclose(fd); + std::fclose(fd); return false; } - while(*ptr && isdigit(*ptr)) ptr++; + while(*ptr && isdigit((unsigned char)(*ptr))) ptr++; if(*ptr == 0) { - fclose(fd); + std::fclose(fd); return false; } ptr++; - fseek(fd, long(ptr - buf), SEEK_SET); + std::fseek(fd, long(ptr - buf), SEEK_SET); create_img(idx, width, height); bool ret = true; if(m_format == pix_format_rgb24) { - fread(m_specific->m_buf_img[idx], 1, width * height * 3, fd); + std::size_t sz = std::fread(m_specific->m_buf_img[idx], 1, width * height * 3, fd); + if (sz != width * height * 3) + ret = false; } else { @@ -1086,10 +1226,28 @@ namespace agg -width * 3 : width * 3); - fread(buf_img, 1, width * height * 3, fd); + std::size_t sz = std::fread(buf_img, 1, width * height * 3, fd); + if (sz != width * height * 3) + ret = false; switch(m_format) { + case pix_format_sgray8: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_gray8: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_gray16: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_gray32: + convert(m_rbuf_img+idx, &rbuf_img); + break; + case pix_format_rgb555: color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_rgb555()); break; @@ -1098,24 +1256,96 @@ namespace agg color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_rgb565()); break; + case pix_format_sbgr24: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_rgb24: + convert(m_rbuf_img+idx, &rbuf_img); + break; + case pix_format_bgr24: - color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_bgr24()); + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_srgba32: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_sargb32: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_sbgra32: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_sabgr32: + convert(m_rbuf_img+idx, &rbuf_img); break; case pix_format_rgba32: - color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_rgba32()); + convert(m_rbuf_img+idx, &rbuf_img); break; case pix_format_argb32: - color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_argb32()); + convert(m_rbuf_img+idx, &rbuf_img); break; case pix_format_bgra32: - color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_bgra32()); + convert(m_rbuf_img+idx, &rbuf_img); break; case pix_format_abgr32: - color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_abgr32()); + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_rgb48: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_bgr48: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_rgba64: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_argb64: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_bgra64: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_abgr64: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_rgb96: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_bgr96: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_rgba128: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_argb128: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_bgra128: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_abgr128: + convert(m_rbuf_img+idx, &rbuf_img); break; default: @@ -1124,7 +1354,7 @@ namespace agg delete [] buf_img; } - fclose(fd); + std::fclose(fd); return ret; } return false; @@ -1139,28 +1369,45 @@ namespace agg if(idx < max_images && rbuf_img(idx).buf()) { char buf[1024]; - strcpy(buf, file); - int len = strlen(buf); + std::strcpy(buf, file); + int len = std::strlen(buf); if(len < 4 || strcasecmp(buf + len - 4, ".ppm") != 0) { - strcat(buf, ".ppm"); + std::strcat(buf, ".ppm"); } - FILE* fd = fopen(buf, "wb"); + FILE* fd = std::fopen(buf, "wb"); if(fd == 0) return false; unsigned w = rbuf_img(idx).width(); unsigned h = rbuf_img(idx).height(); - fprintf(fd, "P6\n%d %d\n255\n", w, h); + std::fprintf(fd, "P6\n%d %d\n255\n", w, h); unsigned y; unsigned char* tmp_buf = new unsigned char [w * 3]; for(y = 0; y < rbuf_img(idx).height(); y++) { - const unsigned char* src = rbuf_img(idx).row(m_flip_y ? h - 1 - y : y); + const unsigned char* src = rbuf_img(idx).row_ptr(m_flip_y ? h - 1 - y : y); switch(m_format) { + case pix_format_sgray8: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_gray8: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_gray16: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_gray32: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + default: break; case pix_format_rgb555: color_conv_row(tmp_buf, src, w, color_conv_rgb555_to_rgb24()); break; @@ -1169,34 +1416,106 @@ namespace agg color_conv_row(tmp_buf, src, w, color_conv_rgb565_to_rgb24()); break; + case pix_format_sbgr24: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_srgb24: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + case pix_format_bgr24: - color_conv_row(tmp_buf, src, w, color_conv_bgr24_to_rgb24()); + color_conv_row(tmp_buf, src, w, conv_row()); break; case pix_format_rgb24: - color_conv_row(tmp_buf, src, w, color_conv_rgb24_to_rgb24()); + color_conv_row(tmp_buf, src, w, conv_row()); break; + case pix_format_srgba32: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_sargb32: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_sbgra32: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_sabgr32: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + case pix_format_rgba32: - color_conv_row(tmp_buf, src, w, color_conv_rgba32_to_rgb24()); + color_conv_row(tmp_buf, src, w, conv_row()); break; case pix_format_argb32: - color_conv_row(tmp_buf, src, w, color_conv_argb32_to_rgb24()); + color_conv_row(tmp_buf, src, w, conv_row()); break; case pix_format_bgra32: - color_conv_row(tmp_buf, src, w, color_conv_bgra32_to_rgb24()); + color_conv_row(tmp_buf, src, w, conv_row()); break; case pix_format_abgr32: - color_conv_row(tmp_buf, src, w, color_conv_abgr32_to_rgb24()); + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_bgr48: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_rgb48: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_rgba64: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_argb64: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_bgra64: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_abgr64: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_bgr96: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_rgb96: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_rgba128: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_argb128: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_bgra128: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_abgr128: + color_conv_row(tmp_buf, src, w, conv_row()); break; } - fwrite(tmp_buf, 1, w * 3, fd); + std::fwrite(tmp_buf, 1, w * 3, fd); } delete [] tmp_buf; - fclose(fd); + std::fclose(fd); return true; } return false; @@ -1209,6 +1528,8 @@ namespace agg { if(idx < max_images) { + if(width == 0) width = rbuf_window().width(); + if(height == 0) height = rbuf_window().height(); delete [] m_specific->m_buf_img[idx]; m_specific->m_buf_img[idx] = new unsigned char[width * height * (m_bpp / 8)]; @@ -1235,7 +1556,7 @@ namespace agg //------------------------------------------------------------------------ void platform_support::message(const char* msg) { - fprintf(stderr, "%s\n", msg); + std::fprintf(stderr, "%s\n", msg); } //------------------------------------------------------------------------ @@ -1247,7 +1568,7 @@ namespace agg //------------------------------------------------------------------------ double platform_support::elapsed_time() const { - clock_t stop = clock(); + std::clock_t stop = std::clock(); return double(stop - m_specific->m_sw_start) * 1000.0 / CLOCKS_PER_SEC; } diff --git a/agg/src/platform/mac/Makefile.am b/agg/src/platform/mac/Makefile.am new file mode 100644 index 0000000..6f1b860 --- /dev/null +++ b/agg/src/platform/mac/Makefile.am @@ -0,0 +1,11 @@ +if ENABLE_OSX +lib_LTLIBRARIES = libaggplatformmac.la +libaggplatformmac_la_LDFLAGS=-version-info @AGG_LIB_VERSION@ +libaggplatformmac_la_SOURCES=agg_mac_pmap.cpp \ + agg_platform_support.cpp + +libaggplatformmac_la_CXXFLAGS = -I$(top_srcdir)/include @OSX_CFLAGS@ +libaggplatformmac_la_LIBADD = @OSX_LIBS@ $(top_builddir)/src/libagg.la + + +endif diff --git a/agg2/src/platform/mac/agg_mac_pmap.cpp b/agg/src/platform/mac/agg_mac_pmap.cpp similarity index 97% rename from agg2/src/platform/mac/agg_mac_pmap.cpp rename to agg/src/platform/mac/agg_mac_pmap.cpp index 1af903c..dbc6c46 100644 --- a/agg2/src/platform/mac/agg_mac_pmap.cpp +++ b/agg/src/platform/mac/agg_mac_pmap.cpp @@ -9,7 +9,7 @@ // //---------------------------------------------------------------------------- -#include +#include #include #include #include @@ -71,7 +71,7 @@ namespace agg // create_gray_scale_palette(m_pmap); I didn't care about gray scale palettes so far. if(clear_val <= 255) { - memset(m_buf, clear_val, m_img_size); + std::memset(m_buf, clear_val, m_img_size); } } @@ -80,7 +80,7 @@ namespace agg //------------------------------------------------------------------------ void pixel_map::clear(unsigned clear_val) { - if(m_buf) memset(m_buf, clear_val, m_img_size); + if(m_buf) std::memset(m_buf, clear_val, m_img_size); } @@ -155,8 +155,8 @@ namespace agg void pixel_map::draw(WindowRef window, int x, int y, double scale) const { if(m_pmap == nil || m_buf == NULL) return; - unsigned width = this->width() * scale; - unsigned height = this->height() * scale; + unsigned width = (unsigned)(this->width() * scale); + unsigned height = (unsigned)(this->height() * scale); Rect rect; SetRect (&rect, x, y, x + width, y + height); draw(window, &rect); diff --git a/agg2/src/platform/mac/agg_platform_support.cpp b/agg/src/platform/mac/agg_platform_support.cpp similarity index 96% rename from agg2/src/platform/mac/agg_platform_support.cpp rename to agg/src/platform/mac/agg_platform_support.cpp index 0fc8a8e..a1c2a00 100644 --- a/agg2/src/platform/mac/agg_platform_support.cpp +++ b/agg/src/platform/mac/agg_platform_support.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.0 -// Copyright (C) 2002 Maxim Shemanarev (McSeem) +// Anti-Grain Geometry - Version 2.4 +// Copyright (C) 2002-2005 Maxim Shemanarev (McSeem) // Copyright (C) 2003 Hansruedi Baer (MacOS support) // // Permission to copy, use, modify, sell and distribute this software @@ -30,7 +30,8 @@ #if defined(__MWERKS__) #include "console.h" #endif -#include +#include +#include #include "platform/agg_platform_support.h" #include "platform/mac/agg_mac_pmap.h" #include "util/agg_color_conv_rgb8.h" @@ -101,7 +102,7 @@ pascal void DoPeriodicTask (EventLoopTimerRef theTimer, void* userData); m_input_flags(0), m_redraw_flag(true) { - memset(m_keymap, 0, sizeof(m_keymap)); + std::memset(m_keymap, 0, sizeof(m_keymap)); //Keyboard input is not yet fully supported nor tested //m_keymap[VK_PAUSE] = key_pause; @@ -446,7 +447,7 @@ pascal void DoPeriodicTask (EventLoopTimerRef theTimer, void* userData); m_initial_width(10), m_initial_height(10) { - strcpy(m_caption, "Anti-Grain Geometry Application"); + std::strcpy(m_caption, "Anti-Grain Geometry Application"); } @@ -461,7 +462,7 @@ pascal void DoPeriodicTask (EventLoopTimerRef theTimer, void* userData); //------------------------------------------------------------------------ void platform_support::caption(const char* cap) { - strcpy(m_caption, cap); + std::strcpy(m_caption, cap); if(m_specific->m_window) { SetWindowTitleWithCFString (m_specific->m_window, CFStringCreateWithCStringNoCopy (nil, cap, kCFStringEncodingASCII, nil)); @@ -489,7 +490,8 @@ pascal void DoPeriodicTask (EventLoopTimerRef theTimer, void* userData); Str255 p_msg; ::CopyCStringToPascal (msg, p_msg); - ::StandardAlert (kAlertPlainAlert, "\pAGG Message", p_msg, NULL, &item); + ::StandardAlert (kAlertPlainAlert, (const unsigned char*) "\013AGG Message", p_msg, NULL, &item); + //::StandardAlert (kAlertPlainAlert, (const unsigned char*) "\pAGG Message", p_msg, NULL, &item); } @@ -635,11 +637,15 @@ pascal void DoPeriodicTask (EventLoopTimerRef theTimer, void* userData); if(idx < max_images) { char fn[1024]; - strcpy(fn, file); - int len = strlen(fn); + std::strcpy(fn, file); + int len = std::strlen(fn); +#if defined(__MWERKS__) if(len < 4 || stricmp(fn + len - 4, ".BMP") != 0) +#else + if(len < 4 || strncasecmp(fn + len - 4, ".BMP", 4) != 0) +#endif { - strcat(fn, ".bmp"); + std::strcat(fn, ".bmp"); } return m_specific->load_pmap(fn, idx, &m_rbuf_img[idx]); } @@ -654,11 +660,15 @@ pascal void DoPeriodicTask (EventLoopTimerRef theTimer, void* userData); if(idx < max_images) { char fn[1024]; - strcpy(fn, file); - int len = strlen(fn); + std::strcpy(fn, file); + int len = std::strlen(fn); +#if defined(__MWERKS__) if(len < 4 || stricmp(fn + len - 4, ".BMP") != 0) +#else + if(len < 4 || strncasecmp(fn + len - 4, ".BMP", 4) != 0) +#endif { - strcat(fn, ".bmp"); + std::strcat(fn, ".bmp"); } return m_specific->save_pmap(fn, idx, &m_rbuf_img[idx]); } @@ -1030,8 +1040,14 @@ int main(int argc, char* argv[]) #if defined(__MWERKS__) // argc = ccommand (&argv); #endif + + // Check if we are launched by double-clicking under OSX + // Get rid of extra argument, this will confuse the standard argument parsing + // calls used in the examples to get the name of the image file to be used + if ( argc >= 2 && std::strncmp(argv[1], "-psn", 4) == 0 ) { + argc = 1; + } + +launch: return agg_main(argc, argv); } - - - diff --git a/agg/src/platform/sdl/Makefile.am b/agg/src/platform/sdl/Makefile.am new file mode 100644 index 0000000..590ef82 --- /dev/null +++ b/agg/src/platform/sdl/Makefile.am @@ -0,0 +1,10 @@ +if ENABLE_SDL + +lib_LTLIBRARIES = libaggplatformsdl.la + +libaggplatformsdl_la_LDFLAGS = -version-info @AGG_LIB_VERSION@ +libaggplatformsdl_la_SOURCES = agg_platform_support.cpp +libaggplatformsdl_la_CXXFLAGS = -I$(top_srcdir)/include @SDL_CFLAGS@ +libaggplatformsdl_la_LIBADD = @SDL_LIBS@ +endif + diff --git a/agg2/src/platform/sdl/agg_platform_support.cpp b/agg/src/platform/sdl/agg_platform_support.cpp similarity index 81% rename from agg2/src/platform/sdl/agg_platform_support.cpp rename to agg/src/platform/sdl/agg_platform_support.cpp index 4bf491e..107626a 100644 --- a/agg2/src/platform/sdl/agg_platform_support.cpp +++ b/agg/src/platform/sdl/agg_platform_support.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -17,9 +17,11 @@ // //---------------------------------------------------------------------------- -#include +#include +#include #include "platform/agg_platform_support.h" #include "SDL.h" +#include "SDL_byteorder.h" namespace agg @@ -69,11 +71,11 @@ namespace agg m_cur_x(0), m_cur_y(0) { - memset(m_surf_img, 0, sizeof(m_surf_img)); + std::memset(m_surf_img, 0, sizeof(m_surf_img)); switch(m_format) { - case pix_format_gray8: + case pix_format_gray8: m_bpp = 8; break; @@ -92,9 +94,10 @@ namespace agg m_amask = 0; m_bpp = 16; break; - + +#if SDL_BYTEORDER == SDL_LIL_ENDIAN case pix_format_rgb24: - m_rmask = 0xFF; + m_rmask = 0xFF; m_gmask = 0xFF00; m_bmask = 0xFF0000; m_amask = 0; @@ -140,6 +143,55 @@ namespace agg m_amask = 0xFF000000; m_bpp = 32; break; +#else //SDL_BIG_ENDIAN (PPC) + case pix_format_rgb24: + m_rmask = 0xFF0000; + m_gmask = 0xFF00; + m_bmask = 0xFF; + m_amask = 0; + m_bpp = 24; + break; + + case pix_format_bgr24: + m_rmask = 0xFF; + m_gmask = 0xFF00; + m_bmask = 0xFF0000; + m_amask = 0; + m_bpp = 24; + break; + + case pix_format_bgra32: + m_rmask = 0xFF00; + m_gmask = 0xFF0000; + m_bmask = 0xFF000000; + m_amask = 0xFF; + m_bpp = 32; + break; + + case pix_format_abgr32: + m_rmask = 0xFF; + m_gmask = 0xFF00; + m_bmask = 0xFF0000; + m_amask = 0xFF000000; + m_bpp = 32; + break; + + case pix_format_argb32: + m_rmask = 0xFF0000; + m_gmask = 0xFF00; + m_bmask = 0xFF; + m_amask = 0xFF000000; + m_bpp = 32; + break; + + case pix_format_rgba32: + m_rmask = 0xFF000000; + m_gmask = 0xFF0000; + m_bmask = 0xFF00; + m_amask = 0xFF; + m_bpp = 32; + break; +#endif } } @@ -167,7 +219,7 @@ namespace agg m_flip_y(flip_y) { SDL_Init(SDL_INIT_VIDEO); - strcpy(m_caption, "Anti-Grain Geometry Application"); + std::strcpy(m_caption, "Anti-Grain Geometry Application"); } @@ -182,7 +234,7 @@ namespace agg //------------------------------------------------------------------------ void platform_support::caption(const char* cap) { - strcpy(m_caption, cap); + std::strcpy(m_caption, cap); if(m_specific->m_initialized) { SDL_WM_SetCaption(cap, 0); @@ -214,7 +266,7 @@ namespace agg m_specific->m_surf_screen = SDL_SetVideoMode(width, height, m_bpp, wflags); if(m_specific->m_surf_screen == 0) { - fprintf(stderr, + std::fprintf(stderr, "Unable to set %dx%d %d bpp video: %s\n", width, height, @@ -239,7 +291,7 @@ namespace agg if(m_specific->m_surf_window == 0) { - fprintf(stderr, + std::fprintf(stderr, "Unable to create image buffer %dx%d %d bpp: %s\n", width, height, @@ -381,8 +433,8 @@ namespace agg m_specific->m_cur_x = event.motion.x; m_specific->m_cur_y = y; flags = 0; - if(event.motion.state & SDL_BUTTON(1)) flags |= mouse_left; - if(event.motion.state & SDL_BUTTON(3)) flags |= mouse_right; + if(event.motion.state & SDL_BUTTON_LMASK) flags |= mouse_left; + if(event.motion.state & SDL_BUTTON_RMASK) flags |= mouse_right; if(m_ctrls.on_mouse_move(m_specific->m_cur_x, m_specific->m_cur_y, @@ -401,61 +453,64 @@ namespace agg while (SDL_PeepEvents(&eventtrash, 1, SDL_GETEVENT, SDL_EVENTMASK(SDL_MOUSEMOTION))!=0){;} break; - case SDL_MOUSEBUTTONDOWN: - y = m_flip_y ? - m_rbuf_window.height() - event.motion.y : - event.motion.y; + case SDL_MOUSEBUTTONDOWN: + y = m_flip_y + ? m_rbuf_window.height() - event.button.y + : event.button.y; - m_specific->m_cur_x = event.motion.x; + m_specific->m_cur_x = event.button.x; m_specific->m_cur_y = y; flags = 0; - if(event.button.button == SDL_BUTTON_LEFT) flags = mouse_left; - if(event.button.button == SDL_BUTTON_RIGHT) flags = mouse_right; - - if(flags & mouse_left) + switch(event.button.button) { - if(m_ctrls.on_mouse_button_down(m_specific->m_cur_x, - m_specific->m_cur_y)) - { - m_ctrls.set_cur(m_specific->m_cur_x, - m_specific->m_cur_y); - on_ctrl_change(); - force_redraw(); - } - else + case SDL_BUTTON_LEFT: { - if(m_ctrls.in_rect(m_specific->m_cur_x, - m_specific->m_cur_y)) + flags = mouse_left; + +if(m_ctrls.on_mouse_button_down(m_specific->m_cur_x, + m_specific->m_cur_y)) { - if(m_ctrls.set_cur(m_specific->m_cur_x, - m_specific->m_cur_y)) - { - on_ctrl_change(); - force_redraw(); - } + m_ctrls.set_cur(m_specific->m_cur_x, + m_specific->m_cur_y); + on_ctrl_change(); + force_redraw(); } else { - on_mouse_button_down(m_specific->m_cur_x, - m_specific->m_cur_y, - flags); + if(m_ctrls.in_rect(m_specific->m_cur_x, + m_specific->m_cur_y)) + { + if(m_ctrls.set_cur(m_specific->m_cur_x, + m_specific->m_cur_y)) + { + on_ctrl_change(); + force_redraw(); + } + } + else + { + on_mouse_button_down(m_specific->m_cur_x, + m_specific->m_cur_y, + flags); + } } } - } - if(flags & mouse_right) - { + break; + case SDL_BUTTON_RIGHT: + flags = mouse_right; on_mouse_button_down(m_specific->m_cur_x, - m_specific->m_cur_y, - flags); - } + m_specific->m_cur_y, + flags); + break; + } //switch(event.button.button) break; - + case SDL_MOUSEBUTTONUP: - y = m_flip_y ? - m_rbuf_window.height() - event.motion.y : - event.motion.y; + y = m_flip_y + ? m_rbuf_window.height() - event.button.y + : event.button.y; - m_specific->m_cur_x = event.motion.x; + m_specific->m_cur_x = event.button.x; m_specific->m_cur_y = y; flags = 0; if(m_ctrls.on_mouse_button_up(m_specific->m_cur_x, @@ -493,17 +548,17 @@ namespace agg if(m_specific->m_surf_img[idx]) SDL_FreeSurface(m_specific->m_surf_img[idx]); char fn[1024]; - strcpy(fn, file); - int len = strlen(fn); - if(len < 4 || strcmp(fn + len - 4, ".bmp") != 0) + std::strcpy(fn, file); + int len = std::strlen(fn); + if(len < 4 || std::strcmp(fn + len - 4, ".bmp") != 0) { - strcat(fn, ".bmp"); + std::strcat(fn, ".bmp"); } SDL_Surface* tmp_surf = SDL_LoadBMP(fn); if (tmp_surf == 0) { - fprintf(stderr, "Couldn't load %s: %s\n", fn, SDL_GetError()); + std::fprintf(stderr, "Couldn't load %s: %s\n", fn, SDL_GetError()); return false; } @@ -555,11 +610,11 @@ namespace agg if(idx < max_images && m_specific->m_surf_img[idx]) { char fn[1024]; - strcpy(fn, file); - int len = strlen(fn); - if(len < 4 || strcmp(fn + len - 4, ".bmp") != 0) + std::strcpy(fn, file); + int len = std::strlen(fn); + if(len < 4 || std::strcmp(fn + len - 4, ".bmp") != 0) { - strcat(fn, ".bmp"); + std::strcat(fn, ".bmp"); } return SDL_SaveBMP(m_specific->m_surf_img[idx], fn) == 0; } @@ -587,7 +642,7 @@ namespace agg m_specific->m_amask); if(m_specific->m_surf_img[idx] == 0) { - fprintf(stderr, "Couldn't create image: %s\n", SDL_GetError()); + std::fprintf(stderr, "Couldn't create image: %s\n", SDL_GetError()); return false; } @@ -619,7 +674,7 @@ namespace agg //------------------------------------------------------------------------ void platform_support::message(const char* msg) { - fprintf(stderr, "%s\n", msg); + std::fprintf(stderr, "%s\n", msg); } //------------------------------------------------------------------------ diff --git a/agg/src/platform/win32/Makefile.am b/agg/src/platform/win32/Makefile.am new file mode 100644 index 0000000..df7a675 --- /dev/null +++ b/agg/src/platform/win32/Makefile.am @@ -0,0 +1,13 @@ + + +if ENABLE_WIN32 +lib_LTLIBRARIES = libaggplatformwin32.la + +libaggplatformwin32_la_LDFLAGS = -version-info @AGG_LIB_VERSION@ +libaggplatformwin32_la_SOURCES = agg_platform_support.cpp \ + agg_win32_bmp.cpp + +libaggplatformwin32_la_CXXFLAGS = -I$(top_srcdir)/include @WINDOWS_CFLAGS@ +libaggplatformwin32_la_LIBADD = @WINDOWS_LIBS@ $(top_builddir)/src/libagg.la +endif + diff --git a/agg2/src/platform/win32/agg_platform_support.cpp b/agg/src/platform/win32/agg_platform_support.cpp similarity index 72% rename from agg2/src/platform/win32/agg_platform_support.cpp rename to agg/src/platform/win32/agg_platform_support.cpp index f70ad43..d6ffa88 100644 --- a/agg2/src/platform/win32/agg_platform_support.cpp +++ b/agg/src/platform/win32/agg_platform_support.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// 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. @@ -18,10 +18,15 @@ //---------------------------------------------------------------------------- #include -#include +#include #include "platform/agg_platform_support.h" #include "platform/win32/agg_win32_bmp.h" +#include "util/agg_color_conv.h" #include "util/agg_color_conv_rgb8.h" +#include "util/agg_color_conv_rgb16.h" +#include "agg_pixfmt_gray.h" +#include "agg_pixfmt_rgb.h" +#include "agg_pixfmt_rgba.h" namespace agg @@ -140,12 +145,31 @@ namespace agg switch(m_format) { + case pix_format_bw: + m_sys_format = pix_format_bw; + m_bpp = 1; + m_sys_bpp = 1; + break; + case pix_format_gray8: - m_sys_format = pix_format_gray8; + case pix_format_sgray8: + m_sys_format = pix_format_sgray8; m_bpp = 8; m_sys_bpp = 8; break; + case pix_format_gray16: + m_sys_format = pix_format_sgray8; + m_bpp = 16; + m_sys_bpp = 8; + break; + + case pix_format_gray32: + m_sys_format = pix_format_sgray8; + m_bpp = 32; + m_sys_bpp = 8; + break; + case pix_format_rgb565: case pix_format_rgb555: m_sys_format = pix_format_rgb555; @@ -153,21 +177,69 @@ namespace agg m_sys_bpp = 16; break; + case pix_format_rgbAAA: + case pix_format_bgrAAA: + case pix_format_rgbBBA: + case pix_format_bgrABB: + m_sys_format = pix_format_bgr24; + m_bpp = 32; + m_sys_bpp = 24; + break; + case pix_format_rgb24: case pix_format_bgr24: - m_sys_format = pix_format_bgr24; + case pix_format_srgb24: + case pix_format_sbgr24: + m_sys_format = pix_format_sbgr24; m_bpp = 24; m_sys_bpp = 24; break; + case pix_format_rgb48: + case pix_format_bgr48: + m_sys_format = pix_format_sbgr24; + m_bpp = 48; + m_sys_bpp = 24; + break; + + case pix_format_rgb96: + case pix_format_bgr96: + m_sys_format = pix_format_sbgr24; + m_bpp = 96; + m_sys_bpp = 24; + break; + case pix_format_bgra32: case pix_format_abgr32: case pix_format_argb32: case pix_format_rgba32: - m_sys_format = pix_format_bgra32; + case pix_format_sbgra32: + case pix_format_sabgr32: + case pix_format_sargb32: + case pix_format_srgba32: + m_sys_format = pix_format_sbgr24; m_bpp = 32; - m_sys_bpp = 32; + m_sys_bpp = 24; + break; + + case pix_format_bgra64: + case pix_format_abgr64: + case pix_format_argb64: + case pix_format_rgba64: + m_sys_format = pix_format_sbgr24; + m_bpp = 64; + m_sys_bpp = 24; + break; + + case pix_format_bgra128: + case pix_format_abgr128: + case pix_format_argb128: + case pix_format_rgba128: + m_sys_format = pix_format_sbgr24; + m_bpp = 128; + m_sys_bpp = 24; break; + } ::QueryPerformanceFrequency(&m_sw_freq); ::QueryPerformanceCounter(&m_sw_start); @@ -189,6 +261,140 @@ namespace agg } + //------------------------------------------------------------------------ + static void convert_pmap(rendering_buffer* dst, + const rendering_buffer* src, + pix_format_e format) + { + switch(format) + { + case pix_format_gray8: + convert(dst, src); + break; + + case pix_format_gray16: + convert(dst, src); + break; + + case pix_format_gray32: + convert(dst, src); + break; + + case pix_format_rgb565: + color_conv(dst, src, color_conv_rgb565_to_rgb555()); + break; + + case pix_format_rgbAAA: + color_conv(dst, src, color_conv_rgbAAA_to_bgr24()); + break; + + case pix_format_bgrAAA: + color_conv(dst, src, color_conv_bgrAAA_to_bgr24()); + break; + + case pix_format_rgbBBA: + color_conv(dst, src, color_conv_rgbBBA_to_bgr24()); + break; + + case pix_format_bgrABB: + color_conv(dst, src, color_conv_bgrABB_to_bgr24()); + break; + + case pix_format_srgb24: + color_conv(dst, src, color_conv_rgb24_to_bgr24()); + break; + + case pix_format_rgb24: + convert(dst, src); + break; + + case pix_format_bgr24: + convert(dst, src); + break; + + case pix_format_rgb48: + convert(dst, src); + break; + + case pix_format_bgr48: + convert(dst, src); + break; + + case pix_format_bgra32: + convert(dst, src); + break; + + case pix_format_abgr32: + convert(dst, src); + break; + + case pix_format_argb32: + convert(dst, src); + break; + + case pix_format_rgba32: + convert(dst, src); + break; + + case pix_format_sbgra32: + convert(dst, src); + break; + + case pix_format_sabgr32: + convert(dst, src); + break; + + case pix_format_sargb32: + convert(dst, src); + break; + + case pix_format_srgba32: + convert(dst, src); + break; + + case pix_format_bgra64: + convert(dst, src); + break; + + case pix_format_abgr64: + convert(dst, src); + break; + + case pix_format_argb64: + convert(dst, src); + break; + + case pix_format_rgba64: + convert(dst, src); + break; + + case pix_format_rgb96: + convert(dst, src); + break; + + case pix_format_bgr96: + convert(dst, src); + break; + + case pix_format_bgra128: + convert(dst, src); + break; + + case pix_format_abgr128: + convert(dst, src); + break; + + case pix_format_argb128: + convert(dst, src); + break; + + case pix_format_rgba128: + convert(dst, src); + break; + } + } + + //------------------------------------------------------------------------ void platform_specific::display_pmap(HDC dc, const rendering_buffer* src) { @@ -211,31 +417,7 @@ namespace agg pmap_tmp.stride() : -pmap_tmp.stride()); - switch(m_format) - { - case pix_format_gray8: - return; - - case pix_format_rgb565: - color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgb555()); - break; - - case pix_format_rgb24: - color_conv(&rbuf_tmp, src, color_conv_rgb24_to_bgr24()); - break; - - case pix_format_abgr32: - color_conv(&rbuf_tmp, src, color_conv_abgr32_to_bgra32()); - break; - - case pix_format_argb32: - color_conv(&rbuf_tmp, src, color_conv_argb32_to_bgra32()); - break; - - case pix_format_rgba32: - color_conv(&rbuf_tmp, src, color_conv_rgba32_to_bgra32()); - break; - } + convert_pmap(&rbuf_tmp, src, m_format); pmap_tmp.draw(dc); } } @@ -263,31 +445,8 @@ namespace agg m_flip_y ? pmap_tmp.stride() : -pmap_tmp.stride()); - switch(m_format) - { - case pix_format_gray8: - return false; - case pix_format_rgb565: - color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgb555()); - break; - - case pix_format_rgb24: - color_conv(&rbuf_tmp, src, color_conv_rgb24_to_bgr24()); - break; - - case pix_format_abgr32: - color_conv(&rbuf_tmp, src, color_conv_abgr32_to_bgra32()); - break; - - case pix_format_argb32: - color_conv(&rbuf_tmp, src, color_conv_argb32_to_bgra32()); - break; - - case pix_format_rgba32: - color_conv(&rbuf_tmp, src, color_conv_rgba32_to_bgra32()); - break; - } + convert_pmap(&rbuf_tmp, src, m_format); return pmap_tmp.save_as_bmp(fn); } @@ -322,8 +481,38 @@ namespace agg switch(m_format) { + case pix_format_sgray8: + switch(pmap_tmp.bpp()) + { + //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_gray8()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_gray8()); break; + //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_gray8()); break; + } + break; + case pix_format_gray8: - return false; + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_gray16: + switch(pmap_tmp.bpp()) + { + //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_gray16()); break; + case 24: convert(dst, &rbuf_tmp); break; + //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_gray16()); break; + } + break; + + case pix_format_gray32: + switch(pmap_tmp.bpp()) + { + //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_gray32()); break; + case 24: convert(dst, &rbuf_tmp); break; + //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_gray32()); break; + } break; case pix_format_rgb555: @@ -344,7 +533,7 @@ namespace agg } break; - case pix_format_rgb24: + case pix_format_srgb24: switch(pmap_tmp.bpp()) { case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb24()); break; @@ -353,7 +542,7 @@ namespace agg } break; - case pix_format_bgr24: + case pix_format_sbgr24: switch(pmap_tmp.bpp()) { case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgr24()); break; @@ -362,7 +551,39 @@ namespace agg } break; - case pix_format_abgr32: + case pix_format_rgb24: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_bgr24: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_rgb48: + switch(pmap_tmp.bpp()) + { + //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb48()); break; + case 24: convert(dst, &rbuf_tmp); break; + //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb48()); break; + } + break; + + case pix_format_bgr48: + switch(pmap_tmp.bpp()) + { + //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgr48()); break; + case 24: convert(dst, &rbuf_tmp); break; + //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgr48()); break; + } + break; + + case pix_format_sabgr32: switch(pmap_tmp.bpp()) { case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_abgr32()); break; @@ -371,7 +592,7 @@ namespace agg } break; - case pix_format_argb32: + case pix_format_sargb32: switch(pmap_tmp.bpp()) { case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_argb32()); break; @@ -380,7 +601,7 @@ namespace agg } break; - case pix_format_bgra32: + case pix_format_sbgra32: switch(pmap_tmp.bpp()) { case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgra32()); break; @@ -389,7 +610,7 @@ namespace agg } break; - case pix_format_rgba32: + case pix_format_srgba32: switch(pmap_tmp.bpp()) { case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgba32()); break; @@ -397,6 +618,104 @@ namespace agg case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgba32()); break; } break; + + case pix_format_abgr32: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_argb32: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_bgra32: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_rgba32: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_abgr64: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_argb64: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_bgra64: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_rgba64: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_rgb96: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_bgr96: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_abgr128: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_argb128: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_bgra128: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_rgba128: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; } return true; @@ -428,7 +747,7 @@ namespace agg m_initial_width(10), m_initial_height(10) { - strcpy(m_caption, "Anti-Grain Geometry Application"); + std::strcpy(m_caption, "Anti-Grain Geometry Application"); } @@ -443,7 +762,7 @@ namespace agg //------------------------------------------------------------------------ void platform_support::caption(const char* cap) { - strcpy(m_caption, cap); + std::strcpy(m_caption, cap); if(m_specific->m_hwnd) { SetWindowText(m_specific->m_hwnd, m_caption); @@ -466,39 +785,6 @@ namespace agg double(m_specific->m_sw_freq.QuadPart); } - -/* - //------------------------------------------------------------------------ - static char* unicode_to_ansi(LPCWSTR pszW) - { - ULONG cbAnsi, cCharacters; - char* pszA = 0; - - if (pszW == 0) - { - return 0; - } - - cCharacters = wcslen(pszW)+1; - cbAnsi = cCharacters * 2; - pszA = new char[cbAnsi]; - - if(::WideCharToMultiByte(CP_ACP, - 0, - pszW, - cCharacters, - pszA, - cbAnsi, - 0, - 0) == 0) - { - delete [] pszA; - return 0; - } - return pszA; - } -*/ - //------------------------------------------------------------------------ @@ -526,7 +812,7 @@ namespace agg HDC paintDC; - void* user_data = reinterpret_cast(::GetWindowLong(hWnd, GWL_USERDATA)); + void* user_data = reinterpret_cast(::GetWindowLongPtr(hWnd, GWLP_USERDATA)); platform_support* app = 0; if(user_data) @@ -546,6 +832,7 @@ namespace agg HDC dc = ::GetDC(app->m_specific->m_hwnd); app->m_specific->m_current_dc = dc; + LRESULT ret = 0; switch(msg) { @@ -570,14 +857,15 @@ namespace agg //-------------------------------------------------------------------- case WM_LBUTTONDOWN: - app->m_specific->m_cur_x = LOWORD(lParam); + ::SetCapture(app->m_specific->m_hwnd); + app->m_specific->m_cur_x = int16(LOWORD(lParam)); if(app->flip_y()) { - app->m_specific->m_cur_y = app->rbuf_window().height() - HIWORD(lParam); + app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam)); } else { - app->m_specific->m_cur_y = HIWORD(lParam); + app->m_specific->m_cur_y = int16(HIWORD(lParam)); } app->m_specific->m_input_flags = mouse_left | get_key_flags(wParam); @@ -608,18 +896,25 @@ namespace agg app->m_specific->m_input_flags); } } +/* + if(!app->wait_mode()) + { + app->on_idle(); + } +*/ break; //-------------------------------------------------------------------- case WM_LBUTTONUP: - app->m_specific->m_cur_x = LOWORD(lParam); + ::ReleaseCapture(); + app->m_specific->m_cur_x = int16(LOWORD(lParam)); if(app->flip_y()) { - app->m_specific->m_cur_y = app->rbuf_window().height() - HIWORD(lParam); + app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam)); } else { - app->m_specific->m_cur_y = HIWORD(lParam); + app->m_specific->m_cur_y = int16(HIWORD(lParam)); } app->m_specific->m_input_flags = mouse_left | get_key_flags(wParam); @@ -632,53 +927,73 @@ namespace agg app->on_mouse_button_up(app->m_specific->m_cur_x, app->m_specific->m_cur_y, app->m_specific->m_input_flags); +/* + if(!app->wait_mode()) + { + app->on_idle(); + } +*/ break; //-------------------------------------------------------------------- case WM_RBUTTONDOWN: - app->m_specific->m_cur_x = LOWORD(lParam); + ::SetCapture(app->m_specific->m_hwnd); + app->m_specific->m_cur_x = int16(LOWORD(lParam)); if(app->flip_y()) { - app->m_specific->m_cur_y = app->rbuf_window().height() - HIWORD(lParam); + app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam)); } else { - app->m_specific->m_cur_y = HIWORD(lParam); + app->m_specific->m_cur_y = int16(HIWORD(lParam)); } app->m_specific->m_input_flags = mouse_right | get_key_flags(wParam); app->on_mouse_button_down(app->m_specific->m_cur_x, app->m_specific->m_cur_y, app->m_specific->m_input_flags); +/* + if(!app->wait_mode()) + { + app->on_idle(); + } +*/ break; //-------------------------------------------------------------------- case WM_RBUTTONUP: - app->m_specific->m_cur_x = LOWORD(lParam); + ::ReleaseCapture(); + app->m_specific->m_cur_x = int16(LOWORD(lParam)); if(app->flip_y()) { - app->m_specific->m_cur_y = app->rbuf_window().height() - HIWORD(lParam); + app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam)); } else { - app->m_specific->m_cur_y = HIWORD(lParam); + app->m_specific->m_cur_y = int16(HIWORD(lParam)); } app->m_specific->m_input_flags = mouse_right | get_key_flags(wParam); app->on_mouse_button_up(app->m_specific->m_cur_x, app->m_specific->m_cur_y, app->m_specific->m_input_flags); +/* + if(!app->wait_mode()) + { + app->on_idle(); + } +*/ break; //-------------------------------------------------------------------- case WM_MOUSEMOVE: - app->m_specific->m_cur_x = LOWORD(lParam); + app->m_specific->m_cur_x = int16(LOWORD(lParam)); if(app->flip_y()) { - app->m_specific->m_cur_y = app->rbuf_window().height() - HIWORD(lParam); + app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam)); } else { - app->m_specific->m_cur_y = HIWORD(lParam); + app->m_specific->m_cur_y = int16(HIWORD(lParam)); } app->m_specific->m_input_flags = get_key_flags(wParam); @@ -701,6 +1016,12 @@ namespace agg app->m_specific->m_input_flags); } } +/* + if(!app->wait_mode()) + { + app->on_idle(); + } +*/ break; //-------------------------------------------------------------------- @@ -753,20 +1074,35 @@ namespace agg break; } - - if(app->m_ctrls.on_arrow_keys(left, right, down, up)) - { - app->on_ctrl_change(); - app->force_redraw(); - } - else + if(app->window_flags() & window_process_all_keys) { app->on_key(app->m_specific->m_cur_x, app->m_specific->m_cur_y, app->m_specific->m_last_translated_key, app->m_specific->m_input_flags); } + else + { + if(app->m_ctrls.on_arrow_keys(left, right, down, up)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + app->on_key(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_last_translated_key, + app->m_specific->m_input_flags); + } + } } +/* + if(!app->wait_mode()) + { + app->on_idle(); + } +*/ break; //-------------------------------------------------------------------- @@ -823,11 +1159,12 @@ namespace agg //-------------------------------------------------------------------- default: - return ::DefWindowProc(hWnd, msg, wParam, lParam); + ret = ::DefWindowProc(hWnd, msg, wParam, lParam); + break; } app->m_specific->m_current_dc = 0; ::ReleaseDC(app->m_specific->m_hwnd, dc); - return 0; + return ret; } @@ -898,7 +1235,7 @@ namespace agg height + (height - (rct.bottom - rct.top)), FALSE); - ::SetWindowLong(m_specific->m_hwnd, GWL_USERDATA, (LONG)this); + ::SetWindowLongPtr(m_specific->m_hwnd, GWLP_USERDATA, (LONG)this); m_specific->create_pmap(width, height, &m_rbuf_window); m_initial_width = width; m_initial_height = height; @@ -963,11 +1300,11 @@ namespace agg if(idx < max_images) { char fn[1024]; - strcpy(fn, file); - int len = strlen(fn); - if(len < 4 || stricmp(fn + len - 4, ".BMP") != 0) + std::strcpy(fn, file); + int len = std::strlen(fn); + if(len < 4 || _stricmp(fn + len - 4, ".BMP") != 0) { - strcat(fn, ".bmp"); + std::strcat(fn, ".bmp"); } return m_specific->load_pmap(fn, idx, &m_rbuf_img[idx]); } @@ -982,11 +1319,11 @@ namespace agg if(idx < max_images) { char fn[1024]; - strcpy(fn, file); - int len = strlen(fn); - if(len < 4 || stricmp(fn + len - 4, ".BMP") != 0) + std::strcpy(fn, file); + int len = std::strlen(fn); + if(len < 4 || _stricmp(fn + len - 4, ".BMP") != 0) { - strcat(fn, ".bmp"); + std::strcat(fn, ".bmp"); } return m_specific->save_pmap(fn, idx, &m_rbuf_img[idx]); } @@ -1143,7 +1480,7 @@ namespace agg tok.len = 0; if(m_src_string == 0 || m_start == -1) return tok; - register const char *pstr = m_src_string + m_start; + const char *pstr = m_src_string + m_start; if(*pstr == 0) { @@ -1175,7 +1512,7 @@ namespace agg char c = *pstr; int found = 0; - //We are outside of qotation: find one of separator symbols + //We are outside of quotation: find one of separator symbols if(quote_chr == 0) { if(sep_len == 1) @@ -1184,7 +1521,7 @@ namespace agg } else { - found = strncmp(m_sep, pstr, m_sep_len) == 0; + found = std::strncmp(m_sep, pstr, m_sep_len) == 0; } } @@ -1281,11 +1618,11 @@ int PASCAL WinMain(HINSTANCE hInstance, agg::g_windows_instance = hInstance; agg::g_windows_cmd_show = nCmdShow; - char* argv_str = new char [strlen(lpszCmdLine) + 3]; + char* argv_str = new char [std::strlen(lpszCmdLine) + 3]; char* argv_ptr = argv_str; char* argv[64]; - memset(argv, 0, sizeof(argv)); + std::memset(argv, 0, sizeof(argv)); agg::tokenizer cmd_line(" ", "\"' ", "\"'", '\\', agg::tokenizer::multiple); cmd_line.set_str(lpszCmdLine); @@ -1300,7 +1637,7 @@ int PASCAL WinMain(HINSTANCE hInstance, if(tok.ptr == 0) break; if(tok.len) { - memcpy(argv_ptr, tok.ptr, tok.len); + std::memcpy(argv_ptr, tok.ptr, tok.len); argv[argc++] = argv_ptr; argv_ptr += tok.len; *argv_ptr++ = 0; diff --git a/agg2/src/platform/win32/agg_win32_bmp.cpp b/agg/src/platform/win32/agg_win32_bmp.cpp similarity index 82% rename from agg2/src/platform/win32/agg_win32_bmp.cpp rename to agg/src/platform/win32/agg_win32_bmp.cpp index 55aa8f7..2346b33 100644 --- a/agg2/src/platform/win32/agg_win32_bmp.cpp +++ b/agg/src/platform/win32/agg_win32_bmp.cpp @@ -8,6 +8,8 @@ // //---------------------------------------------------------------------------- +#include +#include #include "platform/win32/agg_win32_bmp.h" #include "agg_basics.h" @@ -59,16 +61,38 @@ namespace agg m_is_internal = true; if(clear_val <= 255) { - memset(m_buf, clear_val, m_img_size); + std::memset(m_buf, clear_val, m_img_size); } } + //------------------------------------------------------------------------ + HBITMAP pixel_map::create_dib_section(HDC h_dc, + unsigned width, + unsigned height, + org_e org, + unsigned clear_val) + { + destroy(); + if(width == 0) width = 1; + if(height == 0) height = 1; + m_bpp = org; + HBITMAP h_bitmap = create_dib_section_from_args(h_dc, width, height, m_bpp); + create_gray_scale_palette(m_bmp); + m_is_internal = true; + if(clear_val <= 255) + { + std::memset(m_buf, clear_val, m_img_size); + } + return h_bitmap; + } + + //------------------------------------------------------------------------ void pixel_map::clear(unsigned clear_val) { - if(m_buf) memset(m_buf, clear_val, m_img_size); + if(m_buf) std::memset(m_buf, clear_val, m_img_size); } @@ -214,13 +238,25 @@ namespace agg case 8: break; - case 16: n = n << 1; + case 16: n *= 2; break; - case 24: n = (n << 1) + n; + case 24: n *= 3; break; - case 32: n = n << 2; + case 32: n *= 4; + break; + + case 48: n *= 6; + break; + + case 64: n *= 8; + break; + + case 96: n *= 12; + break; + + case 128: n *= 16; break; default: n = 0; @@ -256,7 +292,7 @@ namespace agg } dvc_x = bmp_x; - dvc_x = bmp_x; + dvc_y = bmp_y; dvc_width = bmp_width; dvc_height = bmp_height; @@ -358,7 +394,7 @@ namespace agg } dvc_x = bmp_x; - dvc_x = bmp_x; + dvc_y = bmp_y; dvc_width = bmp_width; dvc_height = bmp_height; @@ -440,13 +476,13 @@ namespace agg BITMAPINFO *bmi = 0; unsigned bmp_size; - fread(&bmf, sizeof(bmf), 1, fd); + if (std::fread(&bmf, sizeof(bmf), 1, fd) != 1) goto bmperr; if(bmf.bfType != 0x4D42) goto bmperr; bmp_size = bmf.bfSize - sizeof(BITMAPFILEHEADER); bmi = (BITMAPINFO*) new unsigned char [bmp_size]; - if(fread(bmi, 1, bmp_size, fd) != bmp_size) goto bmperr; + if(std::fread(bmi, 1, bmp_size, fd) != bmp_size) goto bmperr; destroy(); m_bpp = bmi->bmiHeader.biBitCount; create_from_bmp(bmi); @@ -463,12 +499,12 @@ namespace agg //------------------------------------------------------------------------ bool pixel_map::load_from_bmp(const char *filename) { - FILE *fd = fopen(filename, "rb"); + FILE *fd = std::fopen(filename, "rb"); bool ret = false; if(fd) { ret = load_from_bmp(fd); - fclose(fd); + std::fclose(fd); } return ret; } @@ -488,8 +524,8 @@ namespace agg bmf.bfReserved1 = 0; bmf.bfReserved2 = 0; - fwrite(&bmf, sizeof(bmf), 1, fd); - fwrite(m_bmp, m_full_size, 1, fd); + std::fwrite(&bmf, sizeof(bmf), 1, fd); + std::fwrite(m_bmp, m_full_size, 1, fd); return true; } @@ -498,12 +534,12 @@ namespace agg //------------------------------------------------------------------------ bool pixel_map::save_as_bmp(const char *filename) const { - FILE *fd = fopen(filename, "wb"); + FILE *fd = std::fopen(filename, "wb"); bool ret = false; if(fd) { ret = save_as_bmp(fd); - fclose(fd); + std::fclose(fd); } return ret; } @@ -552,13 +588,45 @@ namespace agg } - - - - - - - + //private + //------------------------------------------------------------------------ + HBITMAP pixel_map::create_dib_section_from_args(HDC h_dc, + unsigned width, + unsigned height, + unsigned bits_per_pixel) + { + unsigned line_len = calc_row_len(width, bits_per_pixel); + unsigned img_size = line_len * height; + unsigned rgb_size = calc_palette_size(0, bits_per_pixel) * sizeof(RGBQUAD); + unsigned full_size = sizeof(BITMAPINFOHEADER) + rgb_size; + + BITMAPINFO *bmp = (BITMAPINFO *) new unsigned char[full_size]; + + bmp->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmp->bmiHeader.biWidth = width; + bmp->bmiHeader.biHeight = height; + bmp->bmiHeader.biPlanes = 1; + bmp->bmiHeader.biBitCount = (unsigned short)bits_per_pixel; + bmp->bmiHeader.biCompression = 0; + bmp->bmiHeader.biSizeImage = img_size; + bmp->bmiHeader.biXPelsPerMeter = 0; + bmp->bmiHeader.biYPelsPerMeter = 0; + bmp->bmiHeader.biClrUsed = 0; + bmp->bmiHeader.biClrImportant = 0; + + void* img_ptr = 0; + HBITMAP h_bitmap = ::CreateDIBSection(h_dc, bmp, DIB_RGB_COLORS, &img_ptr, NULL, 0); + + if(img_ptr) + { + m_img_size = calc_row_len(width, bits_per_pixel) * height; + m_full_size = 0; + m_bmp = bmp; + m_buf = (unsigned char *) img_ptr; + } + + return h_bitmap; + } } diff --git a/agg2/README.txt b/agg2/README.txt deleted file mode 100644 index df9d177..0000000 --- a/agg2/README.txt +++ /dev/null @@ -1,18 +0,0 @@ - -The Anti-Grain Geometry Project -A high quality rendering engine for C++ -http://antigrain.com - -Anti-Grain Geometry - Version 2.0 -Copyright (C) 2002 Maxim Shemanarev (McSeem) - -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. - - - -TODO: write compilation/installation stuff - - diff --git a/agg2/include/agg_array.h b/agg2/include/agg_array.h deleted file mode 100644 index 37684d1..0000000 --- a/agg2/include/agg_array.h +++ /dev/null @@ -1,734 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -#ifndef AGG_ARRAY_INCLUDED -#define AGG_ARRAY_INCLUDED - -#include -#include "agg_basics.h" - -namespace agg -{ - - //---------------------------------------------------------------pod_array - // A simple class template to store Plain Old Data, a vector - // of a fixed size. The data is continous in memory - //------------------------------------------------------------------------ - template class pod_array - { - public: - typedef T value_type; - - ~pod_array() { delete [] m_array; } - pod_array() : m_size(0), m_capacity(0), m_array(0) {} - pod_array(unsigned cap, unsigned extra_tail=0); - - // Copying - pod_array(const pod_array&); - const pod_array& operator = (const pod_array&); - - unsigned capacity() const { return m_capacity; } - void capacity(unsigned cap, unsigned extra_tail=0); - - void resize(unsigned new_size); - - void add(const T& v) { m_array[m_size++] = v; } - void inc_size(unsigned size) { m_size += size; } - unsigned size() const { return m_size; } - const T& operator [] (unsigned idx) const { return m_array[idx]; } - T& operator [] (unsigned idx) { return m_array[idx]; } - - void remove_all() { m_size = 0; } - void cut_at(unsigned num) { if(num < m_size) m_size = num; } - - private: - unsigned m_size; - unsigned m_capacity; - T* m_array; - }; - - //------------------------------------------------------------------------ - template - void pod_array::capacity(unsigned cap, unsigned extra_tail) - { - m_size = 0; - if(cap > m_capacity) - { - delete [] m_array; - m_capacity = cap + extra_tail; - m_array = m_capacity ? new T [m_capacity] : 0; - } - } - - //------------------------------------------------------------------------ - template - void pod_array::resize(unsigned new_size) - { - if(new_size > m_size) - { - if(new_size > m_capacity) - { - T* data = new T[new_size]; - memcpy(data, m_array, m_size * sizeof(T)); - delete [] m_array; - m_array = data; - } - } - else - { - m_size = new_size; - } - } - - //------------------------------------------------------------------------ - template pod_array::pod_array(unsigned cap, unsigned extra_tail) : - m_size(0), m_capacity(0), m_array(0) - { - capacity(cap, extra_tail); - } - - //------------------------------------------------------------------------ - template pod_array::pod_array(const pod_array& v) : - m_size(v.m_size), - m_capacity(v.m_capacity), - m_array(v.m_capacity ? new T [v.m_capacity] : 0) - { - memcpy(m_array, v.m_array, sizeof(T) * v.m_size); - } - - //------------------------------------------------------------------------ - template const pod_array& - pod_array::operator = (const pod_array&v) - { - capacity(v.m_capacity); - if(v.m_size) memcpy(m_array, v.m_array, sizeof(T) * v.m_size); - return *this; - } - - - - - - //------------------------------------------------------------------------ - template class pod_array_adaptor - { - public: - typedef T value_type; - pod_array_adaptor(T* array, unsigned size) : - m_array(array), m_size(size) {} - - unsigned size() const { return m_size; } - const T& operator [] (unsigned idx) const { return m_array[idx]; } - T& operator [] (unsigned idx) { return m_array[idx]; } - private: - T* m_array; - unsigned m_size; - }; - - - - - - - //---------------------------------------------------------------pod_deque - // A simple class template to store Plain Old Data, similar to std::deque - // It doesn't reallocate memory but instead, uses blocks of data of size - // of (1 << S), that is, power of two. The data is NOT continuous in memory, - // so the only valid access method is operator [] or curr(), prev(), next() - // - // There reallocs occure only when the pool of pointers to blocks needs - // to be extended (it happens very rear). You can control the value - // of increment to reallocate the pointer buffer. See the second constructor. - // By default, the incremeent value equals (1 << S), i.e., the block size. - //------------------------------------------------------------------------ - template class pod_deque - { - enum - { - block_shift = S, - block_size = 1 << block_shift, - block_mask = block_size - 1 - }; - - public: - typedef T value_type; - - ~pod_deque(); - pod_deque(); - pod_deque(unsigned block_ptr_inc); - - // Copying - pod_deque(const pod_deque& v); - const pod_deque& operator = (const pod_deque& v); - - void remove_all() { m_size = 0; } - void free_all() { free_tail(0); } - void free_tail(unsigned size); - void add(const T& val); - void modify_last(const T& val); - void remove_last(); - - int allocate_continuous_block(unsigned num_elements); - - void cut_at(unsigned size) - { - if(size < m_size) m_size = size; - } - - unsigned size() const { return m_size; } - - const T& operator [] (unsigned idx) const - { - return m_blocks[idx >> block_shift][idx & block_mask]; - } - - T& operator [] (unsigned idx) - { - return m_blocks[idx >> block_shift][idx & block_mask]; - } - - const T& curr(unsigned idx) const - { - return (*this)[idx]; - } - - T& curr(unsigned idx) - { - return (*this)[idx]; - } - - const T& prev(unsigned idx) const - { - return (*this)[(idx + m_size - 1) % m_size]; - } - - T& prev(unsigned idx) - { - return (*this)[(idx + m_size - 1) % m_size]; - } - - const T& next(unsigned idx) const - { - return (*this)[(idx + 1) % m_size]; - } - - T& next(unsigned idx) - { - return (*this)[(idx + 1) % m_size]; - } - - const T& last() const - { - return (*this)[m_size - 1]; - } - - T& last() - { - return (*this)[m_size - 1]; - } - - unsigned byte_size() const; - void serialize(int8u* ptr) const; - - private: - void allocate_block(unsigned nb); - T* data_ptr(); - - unsigned m_size; - unsigned m_num_blocks; - unsigned m_max_blocks; - T** m_blocks; - unsigned m_block_ptr_inc; - }; - - - - - //------------------------------------------------------------------------ - template pod_deque::~pod_deque() - { - if(m_num_blocks) - { - T** blk = m_blocks + m_num_blocks - 1; - while(m_num_blocks--) - { - delete [] *blk; - --blk; - } - delete [] m_blocks; - } - } - - - //------------------------------------------------------------------------ - template - void pod_deque::free_tail(unsigned size) - { - if(size < m_size) - { - unsigned nb = (size + block_mask) >> block_shift; - while(m_num_blocks > nb) - { - delete [] m_blocks[--m_num_blocks]; - } - m_size = size; - } - } - - - //------------------------------------------------------------------------ - template pod_deque::pod_deque() : - m_size(0), - m_num_blocks(0), - m_max_blocks(0), - m_blocks(0), - m_block_ptr_inc(block_size) - { - } - - - //------------------------------------------------------------------------ - template - pod_deque::pod_deque(unsigned block_ptr_inc) : - m_size(0), - m_num_blocks(0), - m_max_blocks(0), - m_blocks(0), - m_block_ptr_inc(block_ptr_inc) - { - } - - - //------------------------------------------------------------------------ - template - pod_deque::pod_deque(const pod_deque& v) : - m_size(v.m_size), - m_num_blocks(v.m_num_blocks), - m_max_blocks(v.m_max_blocks), - m_blocks(v.m_max_blocks ? new T* [v.m_max_blocks] : 0), - m_block_ptr_inc(v.m_block_ptr_inc) - { - unsigned i; - for(i = 0; i < v.m_num_blocks; ++i) - { - m_blocks[i] = new T [block_size]; - memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T)); - } - } - - - //------------------------------------------------------------------------ - template - const pod_deque& pod_deque::operator = (const pod_deque& v) - { - unsigned i; - for(i = m_num_blocks; i < v.m_num_blocks; ++i) - { - allocate_block(i); - } - for(i = 0; i < v.m_num_blocks; ++i) - { - memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T)); - } - m_size = v.m_size; - return *this; - } - - - //------------------------------------------------------------------------ - template - void pod_deque::allocate_block(unsigned nb) - { - if(nb >= m_max_blocks) - { - T** new_blocks = new T* [m_max_blocks + m_block_ptr_inc]; - - if(m_blocks) - { - memcpy(new_blocks, - m_blocks, - m_num_blocks * sizeof(T*)); - - delete [] m_blocks; - } - m_blocks = new_blocks; - m_max_blocks += m_block_ptr_inc; - } - m_blocks[nb] = new T [block_size]; - m_num_blocks++; - } - - - - //------------------------------------------------------------------------ - template - inline T* pod_deque::data_ptr() - { - unsigned nb = m_size >> block_shift; - if(nb >= m_num_blocks) - { - allocate_block(nb); - } - return m_blocks[nb] + (m_size & block_mask); - } - - - - //------------------------------------------------------------------------ - template - inline void pod_deque::add(const T& val) - { - *data_ptr() = val; - ++m_size; - } - - - //------------------------------------------------------------------------ - template - inline void pod_deque::remove_last() - { - if(m_size) --m_size; - } - - - //------------------------------------------------------------------------ - template - void pod_deque::modify_last(const T& val) - { - remove_last(); - add(val); - } - - - //------------------------------------------------------------------------ - template - int pod_deque::allocate_continuous_block(unsigned num_elements) - { - if(num_elements < block_size) - { - data_ptr(); // Allocate initial block if necessary - unsigned rest = block_size - (m_size & block_mask); - unsigned index; - if(num_elements <= rest) - { - // The rest of the block is good, we can use it - //----------------- - index = m_size; - m_size += num_elements; - return index; - } - - // New block - //--------------- - m_size += rest; - data_ptr(); - index = m_size; - m_size += num_elements; - return index; - } - return -1; // Impossible to allocate - } - - - //------------------------------------------------------------------------ - template - unsigned pod_deque::byte_size() const - { - return m_size * sizeof(T); - } - - - //------------------------------------------------------------------------ - template - void pod_deque::serialize(int8u* ptr) const - { - unsigned i; - for(i = 0; i < m_size; i++) - { - memcpy(ptr, &(*this)[i], sizeof(T)); - ptr += sizeof(T); - } - } - - - - - - //-----------------------------------------------------------pod_allocator - // Allocator for arbitrary POD data. Most usable in different cache - // systems for efficient memory allocations. - // Memory is allocated with blocks of fixed size ("block_size" in - // the constructor). If required size exceeds the block size the allocator - // creates a new block of the required size. However, the most efficient - // use is when the average reqired size is much less than the block size. - //------------------------------------------------------------------------ - class pod_allocator - { - public: - void remove_all() - { - if(m_num_blocks) - { - int8u** blk = m_blocks + m_num_blocks - 1; - while(m_num_blocks--) - { - delete [] *blk; - --blk; - } - delete [] m_blocks; - } - m_num_blocks = 0; - m_max_blocks = 0; - m_blocks = 0; - m_buf_ptr = 0; - m_rest = 0; - } - - ~pod_allocator() - { - remove_all(); - } - - pod_allocator(unsigned block_size, unsigned block_ptr_inc=256-8) : - m_block_size(block_size), - m_block_ptr_inc(block_ptr_inc), - m_num_blocks(0), - m_max_blocks(0), - m_blocks(0), - m_buf_ptr(0), - m_rest(0) - { - } - - - int8u* allocate(unsigned size, unsigned alignment=1) - { - if(size == 0) return 0; - if(size <= m_rest) - { - int8u* ptr = m_buf_ptr; - if(alignment > 1) - { - unsigned align = (alignment - (unsigned long)(ptr) % alignment) % alignment; - size += align; - ptr += align; - if(size <= m_rest) - { - m_rest -= size; - m_buf_ptr += size; - return ptr; - } - allocate_block(size); - return allocate(size - align, alignment); - } - m_rest -= size; - m_buf_ptr += size; - return ptr; - } - allocate_block(size + alignment - 1); - return allocate(size, alignment); - } - - - private: - void allocate_block(unsigned size) - { - if(size < m_block_size) size = m_block_size; - if(m_num_blocks >= m_max_blocks) - { - int8u** new_blocks = new int8u* [m_max_blocks + m_block_ptr_inc]; - - if(m_blocks) - { - memcpy(new_blocks, - m_blocks, - m_num_blocks * sizeof(int8u*)); - - delete [] m_blocks; - } - m_blocks = new_blocks; - m_max_blocks += m_block_ptr_inc; - } - m_blocks[m_num_blocks] = m_buf_ptr = new int8u [size]; - m_num_blocks++; - m_rest = size; - } - - unsigned m_block_size; - unsigned m_block_ptr_inc; - unsigned m_num_blocks; - unsigned m_max_blocks; - int8u** m_blocks; - int8u* m_buf_ptr; - unsigned m_rest; - }; - - - - - - - - - //------------------------------------------------------------------------ - enum - { - quick_sort_threshold = 9 - }; - - - //-----------------------------------------------------------swap_elements - template inline void swap_elements(T& a, T& b) - { - T temp = a; - a = b; - b = temp; - } - - - //--------------------------------------------------------------quick_sort - template - void quick_sort(Array& arr, Less less) - { - if(arr.size() < 2) return; - - typename Array::value_type* e1; - typename Array::value_type* e2; - - int stack[80]; - int* top = stack; - int limit = arr.size(); - int base = 0; - - for(;;) - { - int len = limit - base; - - int i; - int j; - int pivot; - - if(len > quick_sort_threshold) - { - // we use base + len/2 as the pivot - pivot = base + len / 2; - swap_elements(arr[base], arr[pivot]); - - i = base + 1; - j = limit - 1; - - // now ensure that *i <= *base <= *j - e1 = &(arr[j]); - e2 = &(arr[i]); - if(less(*e1, *e2)) swap_elements(*e1, *e2); - - e1 = &(arr[base]); - e2 = &(arr[i]); - if(less(*e1, *e2)) swap_elements(*e1, *e2); - - e1 = &(arr[j]); - e2 = &(arr[base]); - if(less(*e1, *e2)) swap_elements(*e1, *e2); - - for(;;) - { - do i++; while( less(arr[i], arr[base]) ); - do j--; while( less(arr[base], arr[j]) ); - - if( i > j ) - { - break; - } - - swap_elements(arr[i], arr[j]); - } - - swap_elements(arr[base], arr[j]); - - // now, push the largest sub-array - if(j - base > limit - i) - { - top[0] = base; - top[1] = j; - base = i; - } - else - { - top[0] = i; - top[1] = limit; - limit = j; - } - top += 2; - } - else - { - // the sub-array is small, perform insertion sort - j = base; - i = j + 1; - - for(; i < limit; j = i, i++) - { - for(; less(*(e1 = &(arr[j + 1])), *(e2 = &(arr[j]))); j--) - { - swap_elements(*e1, *e2); - if(j == base) - { - break; - } - } - } - if(top > stack) - { - top -= 2; - base = top[0]; - limit = top[1]; - } - else - { - break; - } - } - } - } - - - - - //------------------------------------------------------remove_duplicates - // Remove duplicates from a sorted array. It doesn't cut the the - // tail of the array, it just returns the number of remaining elements. - //----------------------------------------------------------------------- - template - unsigned remove_duplicates(Array& arr, Equal equal) - { - if(arr.size() < 2) return arr.size(); - - unsigned i, j; - for(i = 1, j = 1; i < arr.size(); i++) - { - typename Array::value_type& e = arr[i]; - if(!equal(e, arr[i - 1])) - { - arr[j++] = e; - } - } - return j; - } - - - - -} - -#endif diff --git a/agg2/include/agg_basics.h b/agg2/include/agg_basics.h deleted file mode 100644 index 3c91a91..0000000 --- a/agg2/include/agg_basics.h +++ /dev/null @@ -1,283 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_BASICS_INCLUDED -#define AGG_BASICS_INCLUDED - -namespace agg -{ - //------------------------------------------------------------------------- - typedef signed char int8; //----int8 - typedef unsigned char int8u; //----int8u - typedef signed short int16; //----int16 - typedef unsigned short int16u; //----int16u - typedef signed int int32; //----int32 - typedef unsigned int int32u; //----int32u - - - //------------------------------------------------------------------------- - typedef unsigned char cover_type; //----cover_type - enum - { - 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 - }; - - - //-----------------------------------------------------------------------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 struct rect_base - { - typedef rect_base self_type; - T x1; - T y1; - T x2; - T y2; - - rect_base() {} - rect_base(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; - } - }; - - //-----------------------------------------------------intersect_rectangles - template - 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 - 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 rect; //----rect - typedef rect_base 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_end_poly = 6, //----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_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_type - struct point_type - { - double x, y; - - point_type() {} - point_type(double x_, double y_) : x(x_), y(y_) {} - }; - - //-------------------------------------------------------------vertex_type - struct vertex_type - { - double x, y; - unsigned cmd; - - vertex_type() {} - vertex_type(double x_, double y_, unsigned cmd_) : - x(x_), y(y_), cmd(cmd_) {} - }; - - -} - - -#endif - diff --git a/agg2/include/agg_color_rgba.h b/agg2/include/agg_color_rgba.h deleted file mode 100644 index fce76f4..0000000 --- a/agg2/include/agg_color_rgba.h +++ /dev/null @@ -1,252 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// color type rgba -// -//---------------------------------------------------------------------------- - -#ifndef AGG_COLOR_RGBA_INCLUDED -#define AGG_COLOR_RGBA_INCLUDED - -#include -#include "agg_basics.h" - -namespace agg -{ - //====================================================================rgba - struct rgba - { - enum premul { pre }; - - double r; - double g; - double b; - double a; - - //-------------------------------------------------------------------- - rgba() {} - - //-------------------------------------------------------------------- - rgba(double r_, double g_, double b_, double a_=1.0) : - r(r_), g(g_), b(b_), a(a_) {} - - //-------------------------------------------------------------------- - rgba(premul, double r_, double g_, double b_, double a_=1.0) : - r(r_), g(g_), b(b_), a(a_) - { - premultiply(); - } - - //-------------------------------------------------------------------- - rgba(premul, const rgba& c) : r(c.r), g(c.g), b(c.b), a(c.a) - { - premultiply(); - } - - //-------------------------------------------------------------------- - rgba(const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) {} - - //-------------------------------------------------------------------- - rgba(premul, const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) - { - premultiply(); - } - - //-------------------------------------------------------------------- - void clear() - { - r = g = b = a = 0; - } - - //-------------------------------------------------------------------- - const rgba& transparent() - { - a = 0.0; - return *this; - } - - //-------------------------------------------------------------------- - const rgba& transparent(premul) - { - clear(); - return *this; - } - - //-------------------------------------------------------------------- - const rgba& opacity(double a_) - { - if(a_ < 0.0) a_ = 0.0; - if(a_ > 1.0) a_ = 1.0; - a = a_; - return *this; - } - - //-------------------------------------------------------------------- - const rgba& opacity(premul, double a_) - { - if(a_ < 0.0) a_ = 0.0; - if(a_ > 1.0) a_ = 1.0; - premultiply(a_); - return *this; - } - - //-------------------------------------------------------------------- - double opacity() const - { - return a; - } - - //-------------------------------------------------------------------- - const rgba& premultiply() - { - r *= a; - g *= a; - b *= a; - return *this; - } - - //-------------------------------------------------------------------- - const rgba& premultiply(double a_) - { - if(a == 0.0 || a_ == 0.0) - { - r = g = b = a = 0.0; - return *this; - } - a_ /= a; - r *= a_; - g *= a_; - b *= a_; - a = a_; - return *this; - } - - //-------------------------------------------------------------------- - const rgba& demultiply() - { - if(a == 0) - { - r = g = b = 0; - return *this; - } - double a_ = 1.0 / a; - r *= a_; - g *= a_; - b *= a_; - return *this; - } - - - //-------------------------------------------------------------------- - rgba gradient(rgba c, double k) const - { - rgba ret; - ret.r = r + (c.r - r) * k; - ret.g = g + (c.g - g) * k; - ret.b = b + (c.b - b) * k; - ret.a = a + (c.a - a) * k; - return ret; - } - - //-------------------------------------------------------------------- - static rgba no_color() { return rgba(0,0,0,0); } - - //-------------------------------------------------------------------- - static rgba from_wavelength(double wl, double gamma = 1.0); - - //-------------------------------------------------------------------- - rgba(double wavelen, double gamma=1.0) - { - *this = from_wavelength(wavelen, gamma); - } - - }; - - - //------------------------------------------------------------------------ - inline rgba rgba_pre(double r, double g, double b, double a=1.0) - { - return rgba(rgba::pre, r, g, b, a); - } - - //-------------------------------------------------------------------- - inline rgba rgba_pre(const rgba& c) - { - return rgba(rgba::pre, c); - } - - //-------------------------------------------------------------------- - inline rgba rgba_pre(const rgba& c, double a) - { - return rgba(rgba::pre, c, a); - } - - - //------------------------------------------------------------------------ - inline rgba rgba::from_wavelength(double wl, double gamma) - { - rgba t(0.0, 0.0, 0.0); - - if(wl >= 380.0 && wl <= 440.0) - { - t.r = -1.0 * (wl - 440.0) / (440.0 - 380.0); - t.b = 1.0; - } - else - if(wl >= 440.0 && wl <= 490.0) - { - t.g = (wl - 440.0) / (490.0 - 440.0); - t.b = 1.0; - } - else - if(wl >= 490.0 && wl <= 510.0) - { - t.g = 1.0; - t.b = -1.0 * (wl - 510.0) / (510.0 - 490.0); - } - else - if(wl >= 510.0 && wl <= 580.0) - { - t.r = (wl - 510.0) / (580.0 - 510.0); - t.g = 1.0; - } - else - if(wl >= 580.0 && wl <= 645.0) - { - t.r = 1.0; - t.g = -1.0 * (wl - 645.0) / (645.0 - 580.0); - } - else - if(wl >= 645.0 && wl <= 780.0) - { - t.r = 1.0; - } - - double s = 1.0; - if(wl > 700.0) s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0); - else if(wl < 420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0); - - t.r = pow(t.r * s, gamma); - t.g = pow(t.g * s, gamma); - t.b = pow(t.b * s, gamma); - return t; - } - - - -} - - -#endif diff --git a/agg2/include/agg_color_rgba8.h b/agg2/include/agg_color_rgba8.h deleted file mode 100644 index e85c4eb..0000000 --- a/agg2/include/agg_color_rgba8.h +++ /dev/null @@ -1,256 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// color type rgba8 -// -//---------------------------------------------------------------------------- - -#ifndef AGG_COLOR_RGBA8_INCLUDED -#define AGG_COLOR_RGBA8_INCLUDED - -#include "agg_basics.h" -#include "agg_color_rgba.h" - -namespace agg -{ - - // Supported byte orders for RGB and RGBA pixel formats - //======================================================================= - struct order_rgb24 { enum { R=0, G=1, B=2, rgb24_tag }; }; //----order_rgb24 - struct order_bgr24 { enum { B=0, G=1, R=2, rgb24_tag }; }; //----order_bgr24 - struct order_rgba32 { enum { R=0, G=1, B=2, A=3, rgba32_tag }; }; //----order_rgba32 - struct order_argb32 { enum { A=0, R=1, G=2, B=3, rgba32_tag }; }; //----order_argb32 - struct order_abgr32 { enum { A=0, B=1, G=2, R=3, rgba32_tag }; }; //----order_abgr32 - struct order_bgra32 { enum { B=0, G=1, R=2, A=3, rgba32_tag }; }; //----order_bgra32 - - //==================================================================rgba8 - struct rgba8 - { - enum order { rgb, bgr }; - enum premul { pre }; - - int8u r; - int8u g; - int8u b; - int8u a; - - //-------------------------------------------------------------------- - rgba8() {} - - //-------------------------------------------------------------------- - rgba8(unsigned r_, unsigned g_, unsigned b_, unsigned a_=255) : - r(int8u(r_)), g(int8u(g_)), b(int8u(b_)), a(int8u(a_)) {} - - //-------------------------------------------------------------------- - rgba8(premul, unsigned r_, unsigned g_, unsigned b_, unsigned a_=255) : - r(int8u(r_)), g(int8u(g_)), b(int8u(b_)), a(int8u(a_)) - { - premultiply(); - } - - //-------------------------------------------------------------------- - rgba8(const rgba& c) : - r(int8u(c.r * 255.0 + 0.5)), - g(int8u(c.g * 255.0 + 0.5)), - b(int8u(c.b * 255.0 + 0.5)), - a(int8u(c.a * 255.0 + 0.5)) {} - - //-------------------------------------------------------------------- - rgba8(premul, const rgba8& c) : - r(int8u(c.r)), g(int8u(c.g)), b(int8u(c.b)), a(int8u(c.a)) - { - premultiply(); - } - - //-------------------------------------------------------------------- - rgba8(const rgba8& c, unsigned a_) : - r(int8u(c.r)), g(int8u(c.g)), b(int8u(c.b)), a(int8u(a_)) {} - - //-------------------------------------------------------------------- - rgba8(premul, const rgba8& c, unsigned a_) : - r(int8u(c.r)), g(int8u(c.g)), b(int8u(c.b)), a(int8u(a_)) - { - premultiply(); - } - - //-------------------------------------------------------------------- - rgba8(unsigned packed, order o) : - r(int8u((o == rgb) ? ((packed >> 16) & 0xFF) : (packed & 0xFF))), - g(int8u((packed >> 8) & 0xFF)), - b(int8u((o == rgb) ? (packed & 0xFF) : ((packed >> 16) & 0xFF))), - a(255) {} - - //-------------------------------------------------------------------- - rgba8(premul, unsigned packed, order o) : - r(int8u((o == rgb) ? ((packed >> 16) & 0xFF) : (packed & 0xFF))), - g(int8u((packed >> 8) & 0xFF)), - b(int8u((o == rgb) ? (packed & 0xFF) : ((packed >> 16) & 0xFF))), - a(255) - { - premultiply(); - } - - //-------------------------------------------------------------------- - void clear() - { - r = g = b = a = 0; - } - - //-------------------------------------------------------------------- - const rgba8& transparent() - { - a = 0; - return *this; - } - - //-------------------------------------------------------------------- - const rgba8& transparent(premul) - { - clear(); - return *this; - } - - //-------------------------------------------------------------------- - const rgba8& opacity(double a_) - { - if(a_ < 0.0) a_ = 0.0; - if(a_ > 1.0) a_ = 1.0; - a = int8u(a_ * 255.0 + 0.5); - return *this; - } - - //-------------------------------------------------------------------- - const rgba8& opacity(premul, double a_) - { - if(a_ < 0.0) a_ = 0.0; - if(a_ > 1.0) a_ = 1.0; - a = int8u(a_ * 255.0 + 0.5); - premultiply(int8u(a_ * 255.0)); - return *this; - } - - //-------------------------------------------------------------------- - double opacity() const - { - return double(a) / 255.0; - } - - //-------------------------------------------------------------------- - const rgba8& premultiply() - { - if(a == 255) return *this; - if(a == 0) - { - r = g = b = 0; - return *this; - } - r = (r * a) >> 8; - g = (g * a) >> 8; - b = (b * a) >> 8; - return *this; - } - - //-------------------------------------------------------------------- - const rgba8& premultiply(unsigned a_) - { - if(a == 255 && a_ >= 255) return *this; - if(a == 0 || a_ == 0) - { - r = g = b = a = 0; - return *this; - } - unsigned r_ = (r * a_) / a; - unsigned g_ = (g * a_) / a; - unsigned b_ = (b * a_) / a; - r = int8u((r_ > a_) ? a_ : r_); - g = int8u((g_ > a_) ? a_ : g_); - b = int8u((b_ > a_) ? a_ : b_); - a = int8u(a_); - return *this; - } - - //-------------------------------------------------------------------- - const rgba8& demultiply() - { - if(a == 255) return *this; - if(a == 0) - { - r = g = b = 0; - return *this; - } - unsigned r_ = (r * 255) / a; - unsigned g_ = (g * 255) / a; - unsigned b_ = (b * 255) / a; - r = (r_ > 255) ? 255 : r_; - g = (g_ > 255) ? 255 : g_; - b = (b_ > 255) ? 255 : b_; - return *this; - } - - //-------------------------------------------------------------------- - rgba8 gradient(rgba8 c, double k) const - { - rgba8 ret; - int ik = int(k * 256); - ret.r = int8u(int(r) + (((int(c.r) - int(r)) * ik) >> 8)); - ret.g = int8u(int(g) + (((int(c.g) - int(g)) * ik) >> 8)); - ret.b = int8u(int(b) + (((int(c.b) - int(b)) * ik) >> 8)); - ret.a = int8u(int(a) + (((int(c.a) - int(a)) * ik) >> 8)); - return ret; - } - - //-------------------------------------------------------------------- - static rgba8 no_color() { return rgba8(0,0,0,0); } - - - //-------------------------------------------------------------------- - static rgba8 from_wavelength(double wl, double gamma = 1.0) - { - return rgba8(rgba::from_wavelength(wl, gamma)); - } - - //-------------------------------------------------------------------- - rgba8(double wavelen, double gamma=1.0) - { - *this = from_wavelength(wavelen, gamma); - } - }; - - - //------------------------------------------------------------------------ - inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b, unsigned a=1.0) - { - return rgba8(rgba8::pre, r, g, b, a); - } - - //-------------------------------------------------------------------- - inline rgba8 rgba8_pre(const rgba& c) - { - return rgba8(rgba8::pre, c); - } - - //-------------------------------------------------------------------- - inline rgba8 rgba8_pre(const rgba8& c, unsigned a) - { - return rgba8(rgba8::pre, c, a); - } - - -} - - - - -#endif diff --git a/agg2/include/agg_curves.h b/agg2/include/agg_curves.h deleted file mode 100644 index 68b4024..0000000 --- a/agg2/include/agg_curves.h +++ /dev/null @@ -1,150 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// classes curve3 and curve4 -// -//---------------------------------------------------------------------------- - -#ifndef AGG_CURVES_INCLUDED -#define AGG_CURVES_INCLUDED - -#include "agg_basics.h" -#include "agg_vertex_iterator.h" - -namespace agg -{ - - // See Implemantation agg_curves.cpp - - - //------------------------------------------------------------------curve3 - class curve3 - { - public: - curve3() : - m_num_steps(0), m_step(0), m_scale(1.0) { } - - curve3(double x1, double y1, - double x2, double y2, - double x3, double y3) : - m_num_steps(0), m_step(0), m_scale(1.0) - { - init(x1, y1, x2, y2, x3, y3); - } - - void reset() { m_num_steps = 0; m_step = -1; } - void init(double x1, double y1, - double x2, double y2, - double x3, double y3); - void approximation_scale(double s) { m_scale = s; } - double approximation_scale() const { return m_scale; } - - void rewind(unsigned id); - unsigned vertex(double* x, double* y); - - typedef curve3 source_type; - typedef vertex_iterator iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - - private: - int m_num_steps; - int m_step; - double m_scale; - double m_start_x; - double m_start_y; - double m_end_x; - double m_end_y; - double m_fx; - double m_fy; - double m_dfx; - double m_dfy; - double m_ddfx; - double m_ddfy; - double m_saved_fx; - double m_saved_fy; - double m_saved_dfx; - double m_saved_dfy; - }; - - - - - - - - //-----------------------------------------------------------------curve4 - class curve4 - { - public: - curve4() : - m_num_steps(0), m_step(0), m_scale(1.0) { } - - curve4(double x1, double y1, - double x2, double y2, - double x3, double y3, - double x4, double y4) : - m_num_steps(0), m_step(0), m_scale(1.0) - { - init(x1, y1, x2, y2, x3, y3, x4, y4); - } - - void reset() { m_num_steps = 0; m_step = -1; } - void init(double x1, double y1, - double x2, double y2, - double x3, double y3, - double x4, double y4); - - void approximation_scale(double s) { m_scale = s; } - double approximation_scale() const { return m_scale; } - - void rewind(unsigned id); - unsigned vertex(double* x, double* y); - - typedef curve4 source_type; - typedef vertex_iterator iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - - private: - int m_num_steps; - int m_step; - double m_scale; - double m_start_x; - double m_start_y; - double m_end_x; - double m_end_y; - double m_fx; - double m_fy; - double m_dfx; - double m_dfy; - double m_ddfx; - double m_ddfy; - double m_dddfx; - double m_dddfy; - double m_saved_fx; - double m_saved_fy; - double m_saved_dfx; - double m_saved_dfy; - double m_saved_ddfx; - double m_saved_ddfy; - }; - - - - -} - -#endif diff --git a/agg2/include/agg_gamma_lut.h b/agg2/include/agg_gamma_lut.h deleted file mode 100644 index a87ef0a..0000000 --- a/agg2/include/agg_gamma_lut.h +++ /dev/null @@ -1,114 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_GAMMA_LUT_INCLUDED -#define AGG_GAMMA_LUT_INCLUDED - -#include -#include "agg_basics.h" - -namespace agg -{ - template class gamma_lut - { - public: - enum - { - gamma_shift = GammaShift, - gamma_size = 1 << gamma_shift, - gamma_mask = gamma_size - 1 - }; - - enum - { - hi_res_shift = HiResShift, - hi_res_size = 1 << hi_res_shift, - hi_res_mask = hi_res_size - 1 - }; - - ~gamma_lut() - { - delete [] m_inv_gamma; - delete [] m_dir_gamma; - } - - gamma_lut() : - m_gamma(1.0), - m_dir_gamma(new HiResT[gamma_size]), - m_inv_gamma(new LoResT[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(new HiResT[gamma_size]), - m_inv_gamma(new LoResT[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)(pow(double(i) / double(gamma_mask), m_gamma) * double(hi_res_mask) + 0.5); - } - - double inv_g = 1.0 / g; - for(i = 0; i < hi_res_size; i++) - { - m_inv_gamma[i] = (LoResT)(pow(double(i) / double(hi_res_mask), inv_g) * double(gamma_mask) + 0.5); - } - } - - 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: - double m_gamma; - HiResT* m_dir_gamma; - LoResT* m_inv_gamma; - }; -} - -#endif diff --git a/agg2/include/agg_gray8.h b/agg2/include/agg_gray8.h deleted file mode 100644 index e5bac0e..0000000 --- a/agg2/include/agg_gray8.h +++ /dev/null @@ -1,107 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// color type gray8 -// -//---------------------------------------------------------------------------- - -#ifndef AGG_GRAY8_INCLUDED -#define AGG_GRAY8_INCLUDED - -#include "agg_basics.h" -#include "agg_color_rgba.h" -#include "agg_color_rgba8.h" - -namespace agg -{ - - //===================================================================gray8 - struct gray8 - { - int8u v; - int8u a; - - //-------------------------------------------------------------------- - gray8() {} - - //-------------------------------------------------------------------- - gray8(unsigned v_, unsigned a_=255) : - v(int8u(v_)), a(int8u(a_)) {} - - //-------------------------------------------------------------------- - gray8(const rgba& c) : - v(int8u((0.299*c.r + 0.587*c.g + 0.114*c.b) * 255.0 + 0.5)), - a(int8u(c.a*255.0)) {} - - //-------------------------------------------------------------------- - gray8(const rgba8& c) : - v((c.r*77 + c.g*150 + c.b*29) >> 8), - a(c.a) {} - - //-------------------------------------------------------------------- - void clear() - { - v = a = 0; - } - - //-------------------------------------------------------------------- - const gray8& transparent() - { - a = 0; - return *this; - } - - //-------------------------------------------------------------------- - void opacity(double a_) - { - if(a_ < 0.0) a_ = 0.0; - if(a_ > 1.0) a_ = 1.0; - a = int8u(a_ * 255.0); - } - - //-------------------------------------------------------------------- - double opacity() const - { - return double(a) / 255.0; - } - - //-------------------------------------------------------------------- - gray8 gradient(gray8 c, double k) const - { - gray8 ret; - int ik = int(k * 256); - ret.v = int8u(int(v) + (((int(c.v) - int(v)) * ik) >> 8)); - ret.a = int8u(int(a) + (((int(c.a) - int(a)) * ik) >> 8)); - return ret; - } - - //-------------------------------------------------------------------- - gray8 pre() const - { - return gray8((v*a) >> 8, a); - - } - - //-------------------------------------------------------------------- - static gray8 no_color() { return gray8(0,0); } - }; - - -} - - - - -#endif diff --git a/agg2/include/agg_image_filters.h b/agg2/include/agg_image_filters.h deleted file mode 100644 index 9666ff0..0000000 --- a/agg2/include/agg_image_filters.h +++ /dev/null @@ -1,367 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// Image transformation filters, -// Filtering classes (image_filter_base, image_filter), -// Basic filter shape classes: -// image_filter_bilinear, -// image_filter_bicubic, -// image_filter_spline16, -// image_filter_spline36, -// image_filter_sinc64, -// image_filter_sinc144, -// image_filter_sinc196, -// image_filter_sinc256 -// -//---------------------------------------------------------------------------- -#ifndef AGG_IMAGE_FILTERS_INCLUDED -#define AGG_IMAGE_FILTERS_INCLUDED - -#include -#include "agg_basics.h" - -namespace agg -{ - - // See Implementation agg_image_filters.cpp - - enum - { - image_filter_shift = 14, //----image_filter_shift - image_filter_size = 1 << image_filter_shift, //----image_filter_size - image_filter_mask = image_filter_size - 1, //----image_filter_mask - - image_subpixel_shift = 8, //----image_subpixel_shift - image_subpixel_size = 1 << image_subpixel_shift, //----image_subpixel_size - image_subpixel_mask = image_subpixel_size - 1 //----image_subpixel_mask - }; - - - //-----------------------------------------------------image_filter_base - class image_filter_base - { - public: - ~image_filter_base(); - - image_filter_base(unsigned dimension); - - unsigned dimension() const { return m_dimension; } - int start() const { return m_start; } - const double* weight_array_dbl() const { return m_weight_array_dbl; } - const int* weight_array_int() const { return m_weight_array_int; } - - protected: - void weight(unsigned idx, double val); - double calc_x(unsigned idx) const; - void normalize(); - - private: - image_filter_base(const image_filter_base&); - const image_filter_base& operator = (const image_filter_base&); - - unsigned m_dimension; - int m_start; - double* m_weight_array_dbl; - int* m_weight_array_int; - }; - - - - //--------------------------------------------------------image_filter - template class image_filter : public image_filter_base - { - public: - image_filter() : - image_filter_base(FilterF::dimension()), - m_filter_function() - { - unsigned i; - unsigned dim = dimension() << image_subpixel_shift; - for(i = 0; i < dim; i++) - { - weight(i, m_filter_function.calc_weight(calc_x(i))); - } - normalize(); - } - private: - FilterF m_filter_function; - }; - - - //-----------------------------------------------image_filter_bilinear - class image_filter_bilinear - { - public: - static unsigned dimension() { return 2; } - - static double calc_weight(double x) - { - return (x <= 0.0) ? x + 1.0 : 1.0 - x; - } - }; - - - - //------------------------------------------------image_filter_bicubic - class image_filter_bicubic - { - static double pow3(double x) - { - return (x <= 0.0) ? 0.0 : x * x * x; - } - - public: - static unsigned dimension() { return 4; } - - 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_spline16 - class image_filter_spline16 - { - public: - static unsigned dimension() { return 4; } - static double calc_weight(double x) - { - if(x < 0.0) x = -x; - if(x < 1.0) - { - return ((x - 9.0/5.0 ) * x - 1.0/5.0 ) * x + 1.0; - } - return ((-1.0/3.0 * (x-1) + 4.0/5.0) * (x-1) - 7.0/15.0 ) * (x-1); - } - }; - - - - //---------------------------------------------image_filter_spline36 - class image_filter_spline36 - { - public: - static unsigned dimension() { return 6; } - static double calc_weight(double x) - { - if(x < 0.0) x = -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_sinc36 - class image_filter_sinc36 - { - public: - static unsigned dimension() { return 6; } - static double calc_weight(double x) - { - if(x == 0.0) return 1.0; - x *= pi; - double x3 = x * (1.0/3.0); - return (sin(x) / x) * (sin(x3) / x3); - } - }; - - - - //------------------------------------------------image_filter_sinc64 - class image_filter_sinc64 - { - public: - static unsigned dimension() { return 8; } - static double calc_weight(double x) - { - if(x == 0.0) return 1.0; - x *= pi; - double x4 = x * 0.25; - return (sin(x) / x) * (sin(x4) / x4); - } - }; - - - //-----------------------------------------------image_filter_sinc100 - class image_filter_sinc100 - { - public: - static unsigned dimension() { return 10; } - static double calc_weight(double x) - { - if(x == 0.0) return 1.0; - x *= pi; - double x5 = x * 0.2; - return (sin(x) / x) * (sin(x5) / x5); - } - }; - - - //-----------------------------------------------image_filter_sinc144 - class image_filter_sinc144 - { - public: - static unsigned dimension() { return 12; } - static double calc_weight(double x) - { - if(x == 0.0) return 1.0; - x *= pi; - double x6 = x * (1.0/6.0); - return (sin(x) / x) * (sin(x6) / x6); - } - }; - - - - //-----------------------------------------------image_filter_sinc196 - class image_filter_sinc196 - { - public: - static unsigned dimension() { return 14; } - static double calc_weight(double x) - { - if(x == 0.0) return 1.0; - x *= pi; - double x7 = x * (1.0/7.0); - return (sin(x) / x) * (sin(x7) / x7); - } - }; - - - - //-----------------------------------------------image_filter_sinc256 - class image_filter_sinc256 - { - public: - static unsigned dimension() { return 16; } - static double calc_weight(double x) - { - if(x == 0.0) return 1.0; - x *= pi; - double x8 = x * 0.125; - return (sin(x) / x) * (sin(x8) / x8); - } - }; - - - //--------------------------------------------image_filter_blackman36 - class image_filter_blackman36 - { - public: - static unsigned dimension() { return 6; } - static double calc_weight(double x) - { - if(x == 0.0) return 1.0; - x *= pi; - double x3 = x * (1.0/3.0); - return (sin(x) / x) * (0.42 + 0.5*cos(x3) + 0.08*cos(2*x3)); - } - }; - - - //--------------------------------------------image_filter_blackman64 - class image_filter_blackman64 - { - public: - static unsigned dimension() { return 8; } - static double calc_weight(double x) - { - if(x == 0.0) return 1.0; - x *= pi; - double x4 = x * 0.25; - return (sin(x) / x) * (0.42 + 0.5*cos(x4) + 0.08*cos(2*x4)); - } - }; - - - //-------------------------------------------image_filter_blackman100 - class image_filter_blackman100 - { - public: - static unsigned dimension() { return 10; } - static double calc_weight(double x) - { - if(x == 0.0) return 1.0; - x *= pi; - double x5 = x * 0.2; - return (sin(x) / x) * (0.42 + 0.5*cos(x5) + 0.08*cos(2*x5)); - } - }; - - - //-------------------------------------------image_filter_blackman144 - class image_filter_blackman144 - { - public: - static unsigned dimension() { return 12; } - static double calc_weight(double x) - { - if(x == 0.0) return 1.0; - x *= pi; - double x6 = x * (1.0/6.0); - return (sin(x) / x) * (0.42 + 0.5*cos(x6) + 0.08*cos(2*x6)); - } - }; - - - - //-------------------------------------------image_filter_blackman196 - class image_filter_blackman196 - { - public: - static unsigned dimension() { return 14; } - static double calc_weight(double x) - { - if(x == 0.0) return 1.0; - x *= pi; - double x7 = x * (1.0/7.0); - return (sin(x) / x) * (0.42 + 0.5*cos(x7) + 0.08*cos(2*x7)); - } - }; - - - - //-------------------------------------------image_filter_blackman256 - class image_filter_blackman256 - { - public: - static unsigned dimension() { return 16; } - static double calc_weight(double x) - { - if(x == 0.0) return 1.0; - x *= pi; - double x8 = x * 0.125; - return (sin(x) / x) * (0.42 + 0.5*cos(x8) + 0.08*cos(2*x8)); - } - }; - - -} - -#endif diff --git a/agg2/include/agg_math.h b/agg2/include/agg_math.h deleted file mode 100644 index 917e552..0000000 --- a/agg2/include/agg_math.h +++ /dev/null @@ -1,247 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_MATH_INCLUDED -#define AGG_MATH_INCLUDED - -#include -#include "agg_basics.h" - -namespace agg -{ - - const double intersection_epsilon = 1.0e-8; - - //------------------------------------------------------calc_point_location - inline double calc_point_location(double x1, double y1, - double x2, double y2, - double x, double y) - { - return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1); - } - - - //--------------------------------------------------------point_in_triangle - inline bool point_in_triangle(double x1, double y1, - double x2, double y2, - double x3, double y3, - double x, double y) - { - bool cp1 = calc_point_location(x1, y1, x2, y2, x, y) < 0.0; - bool cp2 = calc_point_location(x2, y2, x3, y3, x, y) < 0.0; - bool cp3 = calc_point_location(x3, y3, x1, y1, x, y) < 0.0; - return cp1 == cp2 && cp2 == cp3 && cp3 == cp1; - } - - - //-----------------------------------------------------------calc_distance - inline double calc_distance(double x1, double y1, double x2, double y2) - { - double dx = x2-x1; - double dy = y2-y1; - return sqrt(dx * dx + dy * dy); - } - - - //------------------------------------------------calc_point_line_distance - inline double calc_point_line_distance(double x1, double y1, - double x2, double y2, - double x, double y) - { - double dx = x2-x1; - double dy = y2-y1; - return ((x - x2) * dy - (y - y2) * dx) / sqrt(dx * dx + dy * dy); - } - - - //-------------------------------------------------------calc_intersection - inline bool calc_intersection(double ax, double ay, double bx, double by, - double cx, double cy, double dx, double dy, - double* x, double* y) - { - double num = (ay-cy) * (dx-cx) - (ax-cx) * (dy-cy); - double den = (bx-ax) * (dy-cy) - (by-ay) * (dx-cx); - if(fabs(den) < intersection_epsilon) return false; - double r = num / den; - *x = ax + r * (bx-ax); - *y = ay + r * (by-ay); - return true; - } - - - //--------------------------------------------------------calc_orthogonal - 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 - 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 = calc_point_location(x1, y1, x2, y2, x3, y3); - if(fabs(loc) > intersection_epsilon) - { - if(calc_point_location(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_polygon_area - template 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 - inline unsigned fast_sqrt(unsigned val) - { - #if defined(_M_IX86) && defined(_MSC_VER) && !defined(AGG_NO_ASM) - //For Ix86 family processors this assembler code is used. - //The key command here is bsr - determination the number of the most - //significant bit of the value. For other processors - //(and maybe compilers) the pure C "#else" section is used. - __asm - { - mov ebx, val - mov edx, 11 - bsr ecx, ebx - sub ecx, 9 - jle less_than_9_bits - shr ecx, 1 - adc ecx, 0 - sub edx, ecx - shl ecx, 1 - shr ebx, cl - less_than_9_bits: - xor eax, eax - mov ax, g_sqrt_table[ebx*2] - mov ecx, edx - shr eax, cl - } - #else - - //This code is actually pure C and portable to most - //arcitectures including 64bit ones. - unsigned t = val; - int bit=0; - unsigned shift = 11; - - //The following piece of code is just an emulation of the - //Ix86 assembler command "bsr" (see above). However on old - //Intels (like Intel MMX 233MHz) this code is about twice - //faster (sic!) then just one "bsr". On PIII and PIV the - //bsr is optimized quite well. - bit = t >> 24; - if(bit) - { - bit = g_elder_bit_table[bit] + 24; - } - else - { - bit = (t >> 16) & 0xFF; - if(bit) - { - bit = g_elder_bit_table[bit] + 16; - } - else - { - bit = (t >> 8) & 0xFF; - if(bit) - { - bit = g_elder_bit_table[bit] + 8; - } - else - { - bit = g_elder_bit_table[t]; - } - } - } - - //This is calculation sqrt itself. - 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 - - - - -} - - -#endif diff --git a/agg2/include/agg_path_storage.h b/agg2/include/agg_path_storage.h deleted file mode 100644 index 8fbc4d4..0000000 --- a/agg2/include/agg_path_storage.h +++ /dev/null @@ -1,369 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_PATH_STORAGE_INCLUDED -#define AGG_PATH_STORAGE_INCLUDED - -#include "agg_basics.h" - -namespace agg -{ - - //------------------------------------------------------------path_storage - // A container to store vertices with their flags. - // A path consists of a number of contours separated with "move_to" - // commands. The path storage can keep and maintain more than one - // path. - // To navigate to the beginning of a particular path, use rewind(path_id); - // Where path_id is what start_new_path() returns. So, when you call - // start_new_path() you need to store its return value somewhere else - // to navigate to the path afterwards. - // - // See Implementation: agg_path_storage.cpp - // See also: vertex_source concept - //------------------------------------------------------------------------ - class path_storage - { - // Allocation parameters - enum - { - block_shift = 8, - block_size = 1 << block_shift, - block_mask = block_size - 1, - block_pool = 256 - }; - - public: - - //-------------------------------------------------------------------- - class const_iterator - { - void vertex() - { - if(m_vertex_idx < m_path->total_vertices()) - { - m_vertex.cmd = m_path->vertex(m_vertex_idx, &m_vertex.x, &m_vertex.y); - } - else - { - m_vertex.cmd = path_cmd_stop; - m_vertex.x = m_vertex.y = 0.0; - } - } - - public: - const_iterator() {} - const_iterator(unsigned cmd) { m_vertex.cmd = cmd; } - const_iterator(const const_iterator& i) : - m_path(i.m_path), - m_vertex_idx(i.m_vertex_idx), - m_vertex(i.m_vertex) - { - } - - const_iterator(const path_storage& p, unsigned id) : - m_path(&p), - m_vertex_idx(id) - { - vertex(); - } - - const_iterator& operator++() - { - ++m_vertex_idx; - vertex(); - return *this; - } - - const vertex_type& operator*() const { return m_vertex; } - const vertex_type* operator->() const { return &m_vertex; } - - bool operator != (const const_iterator& i) - { - return m_vertex.cmd != i.m_vertex.cmd; - } - - private: - const path_storage* m_path; - unsigned m_vertex_idx; - vertex_type m_vertex; - }; - - ~path_storage(); - path_storage(); - path_storage(const path_storage& ps); - - void remove_all(); - - unsigned last_vertex(double* x, double* y) const; - unsigned prev_vertex(double* x, double* y) const; - - void rel_to_abs(double* x, double* y) const; - - void move_to(double x, double y); - void move_rel(double dx, double dy); - - void line_to(double x, double y); - void line_rel(double dx, double dy); - - void arc_to(double rx, double ry, - double angle, - bool large_arc_flag, - bool sweep_flag, - double x, double y); - - void arc_rel(double rx, double ry, - double angle, - bool large_arc_flag, - bool sweep_flag, - double dx, double dy); - - void curve3(double x_ctrl, double y_ctrl, - double x_to, double y_to); - - void curve3_rel(double dx_ctrl, double dy_ctrl, - double dx_to, double dy_to); - - void curve3(double x_to, double y_to); - - void curve3_rel(double dx_to, double dy_to); - - void curve4(double x_ctrl1, double y_ctrl1, - double x_ctrl2, double y_ctrl2, - double x_to, double y_to); - - void curve4_rel(double dx_ctrl1, double dy_ctrl1, - double dx_ctrl2, double dy_ctrl2, - double dx_to, double dy_to); - - void curve4(double x_ctrl2, double y_ctrl2, - double x_to, double y_to); - - void curve4_rel(double x_ctrl2, double y_ctrl2, - double x_to, double y_to); - - - void end_poly(unsigned flags = path_flags_close); - - void close_polygon(unsigned flags = path_flags_none) - { - end_poly(path_flags_close | flags); - } - - void add_poly(const double* vertices, unsigned num, - bool solid_path = false, - unsigned end_flags = path_flags_none); - - void add_vertices(const double* vertices, unsigned num) - { - add_poly(vertices, num, path_flags_none); - } - - template - void add_path(VertexSource& vs, - unsigned path_id = 0, - bool solid_path = true) - { - double x, y; - unsigned cmd; - vs.rewind(path_id); - while(!is_stop(cmd = vs.vertex(&x, &y))) - { - if(is_move_to(cmd) && solid_path && m_total_vertices) - { - cmd = path_cmd_line_to; - } - add_vertex(x, y, cmd); - } - } - - unsigned start_new_path(); - - void copy_from(const path_storage& ps); - const path_storage& operator = (const path_storage& ps) - { - copy_from(ps); - return *this; - } - - - unsigned total_vertices() const { return m_total_vertices; } - unsigned vertex(unsigned idx, double* x, double* y) const - { - unsigned nb = idx >> block_shift; - const double* pv = m_coord_blocks[nb] + ((idx & block_mask) << 1); - *x = *pv++; - *y = *pv; - return m_cmd_blocks[nb][idx & block_mask]; - } - unsigned command(unsigned idx) const - { - return m_cmd_blocks[idx >> block_shift][idx & block_mask]; - } - - void rewind(unsigned path_id); - unsigned vertex(double* x, double* y); - - const_iterator begin(unsigned id) const { return const_iterator(*this, id); } - const_iterator begin() const { return const_iterator(*this, 0); } - const_iterator end() const { return const_iterator(path_cmd_stop); } - - // Arrange the orientation of all the polygons. After calling this - // method all the polygons will have the same orientation - // determined by the new_orientation flag, i.e., - // path_flags_cw or path_flags_ccw - unsigned arrange_orientations(unsigned path_id, path_flags_e new_orientation); - void arrange_orientations_all_paths(path_flags_e new_orientation); - - // Flip all the vertices horizontally or vertically - void flip_x(double x1, double x2); - void flip_y(double y1, double y2); - - // This function adds a vertex with its flags directly. Since there's no - // checking for errors, keeping proper path integrity is the responsibility - // of the caller. It can be said the function is "not very public". - void add_vertex(double x, double y, unsigned cmd); - - // Allows you to modify vertex coordinates. The caller must know - // the index of the vertex. - void modify_vertex(unsigned idx, double x, double y) - { - double* pv = m_coord_blocks[idx >> block_shift] + ((idx & block_mask) << 1); - *pv++ = x; - *pv = y; - } - - // Allows you to modify vertex command. The caller must know - // the index of the vertex. - void modify_command(unsigned idx, unsigned cmd) - { - m_cmd_blocks[idx >> block_shift][idx & block_mask] = (unsigned char)cmd; - } - - - private: - void allocate_block(unsigned nb); - unsigned char* storage_ptrs(double** xy_ptr); - unsigned perceive_polygon_orientation(unsigned idx, - double xs, double ys, - unsigned* orientation); - void reverse_polygon(unsigned start, unsigned end); - - private: - unsigned m_total_vertices; - unsigned m_total_blocks; - unsigned m_max_blocks; - double** m_coord_blocks; - unsigned char** m_cmd_blocks; - unsigned m_iterator; - }; - - - //------------------------------------------------------------------------ - inline unsigned path_storage::vertex(double* x, double* y) - { - if(m_iterator >= m_total_vertices) return path_cmd_stop; - return vertex(m_iterator++, x, y); - } - - //------------------------------------------------------------------------ - inline unsigned path_storage::prev_vertex(double* x, double* y) const - { - if(m_total_vertices > 1) - { - return vertex(m_total_vertices - 2, x, y); - } - return path_cmd_stop; - } - - //------------------------------------------------------------------------ - inline unsigned path_storage::last_vertex(double* x, double* y) const - { - if(m_total_vertices) - { - return vertex(m_total_vertices - 1, x, y); - } - return path_cmd_stop; - } - - //------------------------------------------------------------------------ - inline void path_storage::rel_to_abs(double* x, double* y) const - { - if(m_total_vertices) - { - double x2; - double y2; - if(is_vertex(vertex(m_total_vertices - 1, &x2, &y2))) - { - *x += x2; - *y += y2; - } - } - } - - //------------------------------------------------------------------------ - inline unsigned char* path_storage::storage_ptrs(double** xy_ptr) - { - unsigned nb = m_total_vertices >> block_shift; - if(nb >= m_total_blocks) - { - allocate_block(nb); - } - *xy_ptr = m_coord_blocks[nb] + ((m_total_vertices & block_mask) << 1); - return m_cmd_blocks[nb] + (m_total_vertices & block_mask); - } - - - //------------------------------------------------------------------------ - inline void path_storage::add_vertex(double x, double y, unsigned cmd) - { - double* coord_ptr = 0; - unsigned char* cmd_ptr = storage_ptrs(&coord_ptr); - *cmd_ptr = (unsigned char)cmd; - *coord_ptr++ = x; - *coord_ptr = y; - m_total_vertices++; - } - - //------------------------------------------------------------------------ - inline void path_storage::move_to(double x, double y) - { - add_vertex(x, y, path_cmd_move_to); - } - - //------------------------------------------------------------------------ - inline void path_storage::move_rel(double dx, double dy) - { - rel_to_abs(&dx, &dy); - add_vertex(dx, dy, path_cmd_move_to); - } - - //------------------------------------------------------------------------ - inline void path_storage::line_to(double x, double y) - { - add_vertex(x, y, path_cmd_line_to); - } - - //------------------------------------------------------------------------ - inline void path_storage::line_rel(double dx, double dy) - { - rel_to_abs(&dx, &dy); - add_vertex(dx, dy, path_cmd_line_to); - } -} - - - -#endif diff --git a/agg2/include/agg_pixfmt_gray8.h b/agg2/include/agg_pixfmt_gray8.h deleted file mode 100644 index 20346ac..0000000 --- a/agg2/include/agg_pixfmt_gray8.h +++ /dev/null @@ -1,312 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_PIXFMT_GRAY8_INCLUDED -#define AGG_PIXFMT_GRAY8_INCLUDED - -#include -#include "agg_basics.h" -#include "agg_gray8.h" -#include "agg_rendering_buffer.h" - -namespace agg -{ - - //======================================================pixfmt_gray8_base - template - class pixfmt_gray8_base - { - public: - typedef gray8 color_type; - - //-------------------------------------------------------------------- - pixfmt_gray8_base(rendering_buffer& rb) - : m_rbuf(&rb) - { - } - - //-------------------------------------------------------------------- - unsigned width() const { return m_rbuf->width(); } - unsigned height() const { return m_rbuf->height(); } - - //-------------------------------------------------------------------- - color_type pixel(int x, int y) - { - return color_type(m_rbuf->row(y)[x * Step + Offset]); - } - - //-------------------------------------------------------------------- - void copy_pixel(int x, int y, const color_type& c) - { - m_rbuf->row(y)[x * Step + Offset] = (int8u)c.v; - } - - //-------------------------------------------------------------------- - void blend_pixel(int x, int y, const color_type& c, int8u cover) - { - int8u* p = m_rbuf->row(y) + x * Step + Offset; - int v = *p; - int alpha = int(cover) * c.a; - *p = (int8u)((((c.v - v) * alpha) + (v << 16)) >> 16); - } - - - //-------------------------------------------------------------------- - void copy_hline(int x, int y, unsigned len, const color_type& c) - { - int8u* p = m_rbuf->row(y) + x * Step + Offset; - do - { - *p = (int8u)c.v; - p += Step; - } - while(--len); - } - - - //-------------------------------------------------------------------- - void copy_vline(int x, int y, unsigned len, const color_type& c) - { - int8u* p = m_rbuf->row(y) + x * Step + Offset; - do - { - *p = (int8u)c.v; - p += m_rbuf->stride(); - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_hline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { - int8u* p = m_rbuf->row(y) + x * Step + Offset; - int alpha = int(cover) * c.a; - if(alpha == 255*255) - { - do - { - *p = (int8u)c.v; - p += Step; - } - while(--len); - } - else - { - do - { - int v = *p; - *p = (int8u)((((c.v - v) * alpha) + (v << 16)) >> 16); - p += Step; - } - while(--len); - } - } - - - //-------------------------------------------------------------------- - void blend_vline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { - int8u* p = m_rbuf->row(y) + x * Step + Offset; - int alpha = int(cover) * c.a; - if(alpha == 255*255) - { - do - { - *p = (int8u)c.v; - p += m_rbuf->stride(); - } - while(--len); - } - else - { - do - { - int v = *p; - *p = (int8u)((((c.v - v) * alpha) + (v << 16)) >> 16); - p += m_rbuf->stride(); - } - while(--len); - } - } - - - //-------------------------------------------------------------------- - void copy_from(const rendering_buffer& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) - { - memmove(m_rbuf->row(ydst) + xdst * Step + Offset, - (const void*)(from.row(ysrc) + xsrc * Step + Offset), - len * Step); - } - - - //-------------------------------------------------------------------- - void blend_solid_hspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - int8u* p = m_rbuf->row(y) + x * Step + Offset; - do - { - int alpha = int(*covers++) * c.a; - - if(alpha) - { - if(alpha == 255*255) - { - *p = (int8u)c.v; - } - else - { - int v = *p; - *p = (int8u)((((c.v - v) * alpha) + (v << 16)) >> 16); - } - } - p += Step; - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_solid_vspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - int8u* p = m_rbuf->row(y) + x * Step + Offset; - do - { - int alpha = int(*covers++) * c.a; - - if(alpha) - { - if(alpha == 255*255) - { - *p = (int8u)c.v; - } - else - { - int v = *p; - *p = (int8u)((((c.v - v) * alpha) + (v << 16)) >> 16); - } - } - p += m_rbuf->stride(); - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - int8u* p = m_rbuf->row(y) + x * Step + Offset; - do - { - int alpha = colors->a * (covers ? int(*covers++) : int(cover)); - - if(alpha) - { - if(alpha == 255*255) - { - *p = (int8u)colors->v; - } - else - { - int v = *p; - *p = (int8u)((((colors->v - v) * alpha) + (v << 16)) >> 16); - } - } - p += Step; - ++colors; - } - while(--len); - } - - - - //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - int8u* p = m_rbuf->row(y) + x * Step + Offset; - do - { - int alpha = colors->a * (covers ? int(*covers++) : int(cover)); - - if(alpha) - { - if(alpha == 255*255) - { - *p = (int8u)colors->v; - } - else - { - int v = *p; - *p = (int8u)((((colors->v - v) * alpha) + (v << 16)) >> 16); - } - } - p += m_rbuf->stride(); - ++colors; - } - while(--len); - } - - private: - rendering_buffer* m_rbuf; - }; - - - typedef pixfmt_gray8_base<1, 0> pixfmt_gray8; //----pixfmt_gray8 - - typedef pixfmt_gray8_base<3, 0> pixfmt_gray8_rgb24r; //----pixfmt_gray8_rgb24r - typedef pixfmt_gray8_base<3, 1> pixfmt_gray8_rgb24g; //----pixfmt_gray8_rgb24g - typedef pixfmt_gray8_base<3, 2> pixfmt_gray8_rgb24b; //----pixfmt_gray8_rgb24b - - typedef pixfmt_gray8_base<3, 2> pixfmt_gray8_bgr24r; //----pixfmt_gray8_bgr24r - typedef pixfmt_gray8_base<3, 1> pixfmt_gray8_bgr24g; //----pixfmt_gray8_bgr24g - typedef pixfmt_gray8_base<3, 0> pixfmt_gray8_bgr24b; //----pixfmt_gray8_bgr24b - - typedef pixfmt_gray8_base<4, 0> pixfmt_gray8_rgba32r; //----pixfmt_gray8_rgba32r - typedef pixfmt_gray8_base<4, 1> pixfmt_gray8_rgba32g; //----pixfmt_gray8_rgba32g - typedef pixfmt_gray8_base<4, 2> pixfmt_gray8_rgba32b; //----pixfmt_gray8_rgba32b - typedef pixfmt_gray8_base<4, 3> pixfmt_gray8_rgba32a; //----pixfmt_gray8_rgba32a - - typedef pixfmt_gray8_base<4, 1> pixfmt_gray8_argb32r; //----pixfmt_gray8_argb32r - typedef pixfmt_gray8_base<4, 2> pixfmt_gray8_argb32g; //----pixfmt_gray8_argb32g - typedef pixfmt_gray8_base<4, 3> pixfmt_gray8_argb32b; //----pixfmt_gray8_argb32b - typedef pixfmt_gray8_base<4, 0> pixfmt_gray8_argb32a; //----pixfmt_gray8_argb32a - - typedef pixfmt_gray8_base<4, 2> pixfmt_gray8_bgra32r; //----pixfmt_gray8_bgra32r - typedef pixfmt_gray8_base<4, 1> pixfmt_gray8_bgra32g; //----pixfmt_gray8_bgra32g - typedef pixfmt_gray8_base<4, 0> pixfmt_gray8_bgra32b; //----pixfmt_gray8_bgra32b - typedef pixfmt_gray8_base<4, 3> pixfmt_gray8_bgra32a; //----pixfmt_gray8_bgra32a - - typedef pixfmt_gray8_base<4, 3> pixfmt_gray8_abgr32r; //----pixfmt_gray8_abgr32r - typedef pixfmt_gray8_base<4, 2> pixfmt_gray8_abgr32g; //----pixfmt_gray8_abgr32g - typedef pixfmt_gray8_base<4, 1> pixfmt_gray8_abgr32b; //----pixfmt_gray8_abgr32b - typedef pixfmt_gray8_base<4, 0> pixfmt_gray8_abgr32a; //----pixfmt_gray8_abgr32a - -} - -#endif - diff --git a/agg2/include/agg_pixfmt_rgb24.h b/agg2/include/agg_pixfmt_rgb24.h deleted file mode 100644 index 513f4bf..0000000 --- a/agg2/include/agg_pixfmt_rgb24.h +++ /dev/null @@ -1,355 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_PIXFMT_RGB24_INCLUDED -#define AGG_PIXFMT_RGB24_INCLUDED - -#include -#include "agg_basics.h" -#include "agg_color_rgba8.h" -#include "agg_rendering_buffer.h" - -namespace agg -{ - - //=====================================================pixel_formats_rgb24 - template class pixel_formats_rgb24 - { - public: - typedef rgba8 color_type; - - //-------------------------------------------------------------------- - pixel_formats_rgb24(rendering_buffer& rb) - : m_rbuf(&rb) - { - } - - //-------------------------------------------------------------------- - unsigned width() const { return m_rbuf->width(); } - unsigned height() const { return m_rbuf->height(); } - - //-------------------------------------------------------------------- - color_type pixel(int x, int y) - { - int8u* p = m_rbuf->row(y) + x + x + x; - return color_type(p[Order::R], p[Order::G], p[Order::B]); - } - - //-------------------------------------------------------------------- - void copy_pixel(int x, int y, const color_type& c) - { - int8u* p = m_rbuf->row(y) + x + x + x; - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - } - - //-------------------------------------------------------------------- - void blend_pixel(int x, int y, const color_type& c, int8u cover) - { - int8u* p = m_rbuf->row(y) + x + x + x; - int alpha = int(cover) * c.a; - if(alpha == 255*255) - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - } - else - { - int r = p[Order::R]; - int g = p[Order::G]; - int b = p[Order::B]; - p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16); - p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16); - p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16); - } - } - - - //-------------------------------------------------------------------- - void copy_hline(int x, int y, - unsigned len, - const color_type& c) - { - int8u* p = m_rbuf->row(y) + x + x + x; - do - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p += 3; - } - while(--len); - } - - - //-------------------------------------------------------------------- - void copy_vline(int x, int y, - unsigned len, - const color_type& c) - { - int8u* p = m_rbuf->row(y) + x + x + x; - do - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p += m_rbuf->stride(); - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_hline(int x, int y, - unsigned len, - const color_type& c, - int8u cover) - { - int8u* p = m_rbuf->row(y) + x + x + x; - int alpha = int(cover) * c.a; - if(alpha == 255*255) - { - do - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p += 3; - } - while(--len); - } - else - { - do - { - int r = p[Order::R]; - int g = p[Order::G]; - int b = p[Order::B]; - p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16); - p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16); - p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16); - p += 3; - } - while(--len); - } - } - - - //-------------------------------------------------------------------- - void blend_vline(int x, int y, - unsigned len, - const color_type& c, - int8u cover) - { - int8u* p = m_rbuf->row(y) + x + x + x; - int alpha = int(cover) * c.a; - if(alpha == 255*255) - { - do - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p += m_rbuf->stride(); - } - while(--len); - } - else - { - do - { - int r = p[Order::R]; - int g = p[Order::G]; - int b = p[Order::B]; - p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16); - p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16); - p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16); - p += m_rbuf->stride(); - } - while(--len); - } - } - - - //-------------------------------------------------------------------- - void copy_from(const rendering_buffer& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) - { - memmove(m_rbuf->row(ydst) + xdst * 3, - (const void*)(from.row(ysrc) + xsrc * 3), len * 3); - } - - - //-------------------------------------------------------------------- - void blend_solid_hspan(int x, int y, - unsigned len, - const color_type& c, - const int8u* covers) - { - int8u* p = m_rbuf->row(y) + x + x + x; - do - { - int alpha = int(*covers++) * c.a; - - if(alpha) - { - if(alpha == 255*255) - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - } - else - { - int r = (int8u)p[Order::R]; - int g = (int8u)p[Order::G]; - int b = (int8u)p[Order::B]; - p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16); - p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16); - p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16); - } - } - p += 3; - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_solid_vspan(int x, int y, - unsigned len, - const color_type& c, - const int8u* covers) - { - int8u* p = m_rbuf->row(y) + x + x + x; - do - { - int alpha = int(*covers++) * c.a; - - if(alpha) - { - if(alpha == 255*255) - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - } - else - { - int r = p[Order::R]; - int g = p[Order::G]; - int b = p[Order::B]; - p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16); - p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16); - p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16); - } - } - p += m_rbuf->stride(); - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - const int8u cover) - { - int8u* p = m_rbuf->row(y) + x + x + x; - do - { - int alpha = colors->a * (covers ? int(*covers++) : int(cover)); - - if(alpha) - { - if(alpha == 255*255) - { - p[Order::R] = (int8u)colors->r; - p[Order::G] = (int8u)colors->g; - p[Order::B] = (int8u)colors->b; - } - else - { - int r = p[Order::R]; - int g = p[Order::G]; - int b = p[Order::B]; - p[Order::R] = (int8u)((((colors->r - r) * alpha) + (r << 16)) >> 16); - p[Order::G] = (int8u)((((colors->g - g) * alpha) + (g << 16)) >> 16); - p[Order::B] = (int8u)((((colors->b - b) * alpha) + (b << 16)) >> 16); - } - } - p += 3; - ++colors; - } - while(--len); - } - - - - //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - const int8u cover) - { - int8u* p = m_rbuf->row(y) + x + x + x; - do - { - int alpha = colors->a * (covers ? int(*covers++) : int(cover)); - - if(alpha) - { - if(alpha == 255*255) - { - p[Order::R] = (int8u)colors->r; - p[Order::G] = (int8u)colors->g; - p[Order::B] = (int8u)colors->b; - } - else - { - int r = p[Order::R]; - int g = p[Order::G]; - int b = p[Order::B]; - p[Order::R] = (int8u)((((colors->r - r) * alpha) + (r << 16)) >> 16); - p[Order::G] = (int8u)((((colors->g - g) * alpha) + (g << 16)) >> 16); - p[Order::B] = (int8u)((((colors->b - b) * alpha) + (b << 16)) >> 16); - } - } - p += m_rbuf->stride(); - ++colors; - } - while(--len); - } - - private: - rendering_buffer* m_rbuf; - - }; - - - typedef pixel_formats_rgb24 pixfmt_rgb24; //----pixfmt_rgb24 - typedef pixel_formats_rgb24 pixfmt_bgr24; //----pixfmt_bgr24 - -} - -#endif - diff --git a/agg2/include/agg_pixfmt_rgb24_gamma.h b/agg2/include/agg_pixfmt_rgb24_gamma.h deleted file mode 100644 index 1a92229..0000000 --- a/agg2/include/agg_pixfmt_rgb24_gamma.h +++ /dev/null @@ -1,331 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_PIXFMT_RGB24_GAMMA_INCLUDED -#define AGG_PIXFMT_RGB24_GAMMA_INCLUDED - -#include -#include "agg_basics.h" -#include "agg_color_rgba8.h" -#include "agg_rendering_buffer.h" -#include "agg_gamma_lut.h" - - -namespace agg -{ - - //================================================pixel_formats_rgb24_gamma - template class pixel_formats_rgb24_gamma - { - public: - typedef rgba8 color_type; - typedef Gamma gamma_type; - - private: - //-------------------------------------------------------------------- - inline void blend_pix(int8u* p, const color_type& c, int alpha) - { - int r = m_gamma->dir(p[Order::R]); - int g = m_gamma->dir(p[Order::G]); - int b = m_gamma->dir(p[Order::B]); - p[Order::R] = m_gamma->inv((((m_gamma->dir(c.r) - r) * alpha) + (r << 16)) >> 16); - p[Order::G] = m_gamma->inv((((m_gamma->dir(c.g) - g) * alpha) + (g << 16)) >> 16); - p[Order::B] = m_gamma->inv((((m_gamma->dir(c.b) - b) * alpha) + (b << 16)) >> 16); - } - - //-------------------------------------------------------------------- - inline void copy_or_blend_pix(int8u* p, const color_type& c, int cover) - { - int alpha = int(c.a) * cover; - if(alpha) - { - if(alpha == 255*255) - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - } - else - { - blend_pix(p, c, alpha); - } - } - } - - //-------------------------------------------------------------------- - inline void copy_or_blend_pix(int8u* p, const color_type& c) - { - if(c.a) - { - if(c.a == 255) - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - } - else - { - int r = m_gamma->dir(p[Order::R]); - int g = m_gamma->dir(p[Order::G]); - int b = m_gamma->dir(p[Order::B]); - p[Order::R] = m_gamma->inv((((m_gamma->dir(c.r) - r) * c.a) + (r << 8)) >> 8); - p[Order::G] = m_gamma->inv((((m_gamma->dir(c.g) - g) * c.a) + (g << 8)) >> 8); - p[Order::B] = m_gamma->inv((((m_gamma->dir(c.b) - b) * c.a) + (b << 8)) >> 8); - } - } - } - - - - public: - //-------------------------------------------------------------------- - pixel_formats_rgb24_gamma(rendering_buffer& rb, const gamma_type& g) : - m_rbuf(&rb), - m_gamma(&g) - {} - - //-------------------------------------------------------------------- - void gamma(const gamma_type& g) { m_gamma = &g; } - const gamma_type& gamma() const { return *m_gamma; } - - //-------------------------------------------------------------------- - unsigned width() const { return m_rbuf->width(); } - unsigned height() const { return m_rbuf->height(); } - - //-------------------------------------------------------------------- - color_type pixel(int x, int y) - { - int8u* p = m_rbuf->row(y) + x + x + x; - return color_type(p[Order::R], p[Order::G], p[Order::B]); - } - - //-------------------------------------------------------------------- - void copy_pixel(int x, int y, const color_type& c) - { - int8u* p = m_rbuf->row(y) + x + x + x; - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - } - - //-------------------------------------------------------------------- - void blend_pixel(int x, int y, const color_type& c, int8u cover) - { - copy_or_blend_pix(m_rbuf->row(y) + x + x + x, c, cover); - } - - - //-------------------------------------------------------------------- - void copy_hline(int x, int y, - unsigned len, - const color_type& c) - { - int8u* p = m_rbuf->row(y) + x + x + x; - do - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p += 3; - } - while(--len); - } - - - //-------------------------------------------------------------------- - void copy_vline(int x, int y, - unsigned len, - const color_type& c) - { - int8u* p = m_rbuf->row(y) + x + x + x; - do - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p += m_rbuf->stride(); - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_hline(int x, int y, - unsigned len, - const color_type& c, - int8u cover) - { - int8u* p = m_rbuf->row(y) + x + x + x; - int alpha = int(cover) * c.a; - if(alpha == 255*255) - { - do - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p += 3; - } - while(--len); - } - else - { - do - { - blend_pix(p, c, alpha); - p += 3; - } - while(--len); - } - } - - - //-------------------------------------------------------------------- - void blend_vline(int x, int y, - unsigned len, - const color_type& c, - int8u cover) - { - int8u* p = m_rbuf->row(y) + x + x + x; - int alpha = int(cover) * c.a; - if(alpha == 255*255) - { - do - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p += m_rbuf->stride(); - } - while(--len); - } - else - { - do - { - blend_pix(p, c, alpha); - p += m_rbuf->stride(); - } - while(--len); - } - } - - - //-------------------------------------------------------------------- - void copy_from(const rendering_buffer& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) - { - memmove(m_rbuf->row(ydst) + xdst * 3, - (const void*)(from.row(ysrc) + xsrc * 3), len * 3); - } - - - //-------------------------------------------------------------------- - void blend_solid_hspan(int x, int y, - unsigned len, - const color_type& c, - const int8u* covers) - { - int8u* p = m_rbuf->row(y) + x + x + x; - do - { - copy_or_blend_pix(p, c, *covers++); - p += 3; - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_solid_vspan(int x, int y, - unsigned len, - const color_type& c, - const int8u* covers) - { - int8u* p = m_rbuf->row(y) + x + x + x; - do - { - copy_or_blend_pix(p, c, *covers++); - p += m_rbuf->stride(); - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - int8u* p = m_rbuf->row(y) + x + x + x; - do - { - copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover); - p += 3; - } - while(--len); - } - - - - //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - int8u* p = m_rbuf->row(y) + x + x + x; - do - { - copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover); - p += m_rbuf->stride(); - } - while(--len); - } - - private: - rendering_buffer* m_rbuf; - const gamma_type* m_gamma; - }; - - - //-----------------------------------------------------pixfmt_rgb24_gamma - template class pixfmt_rgb24_gamma : - public pixel_formats_rgb24_gamma - { - public: - pixfmt_rgb24_gamma(rendering_buffer& rb, const Gamma& g) : - pixel_formats_rgb24_gamma(rb, g) {} - }; - - //-----------------------------------------------------pixfmt_bgr24_gamma - template class pixfmt_bgr24_gamma : - public pixel_formats_rgb24_gamma - { - public: - pixfmt_bgr24_gamma(rendering_buffer& rb, const Gamma& g) : - pixel_formats_rgb24_gamma(rb, g) {} - }; - - - -} - -#endif diff --git a/agg2/include/agg_pixfmt_rgb24_pre.h b/agg2/include/agg_pixfmt_rgb24_pre.h deleted file mode 100644 index 5edc92f..0000000 --- a/agg2/include/agg_pixfmt_rgb24_pre.h +++ /dev/null @@ -1,292 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_PIXFMT_RGB24_PRE_INCLUDED -#define AGG_PIXFMT_RGB24_PRE_INCLUDED - -#include -#include "agg_basics.h" -#include "agg_color_rgba8.h" -#include "agg_rendering_buffer.h" - -namespace agg -{ - - - //==================================================pixel_formats_rgb24_pre - template class pixel_formats_rgb24_pre - { - public: - typedef rgba8 color_type; - - - private: - //-------------------------------------------------------------------- - static inline void copy_pix(int8u* p, const color_type& c) - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - } - - //-------------------------------------------------------------------- - static inline void blend_pix(int8u* p, const color_type& c, - unsigned cover, unsigned alpha) - { - p[Order::R] = (int8u)((p[Order::R] * alpha + ((c.r * cover) << 8)) >> 16); - p[Order::G] = (int8u)((p[Order::G] * alpha + ((c.g * cover) << 8)) >> 16); - p[Order::B] = (int8u)((p[Order::B] * alpha + ((c.b * cover) << 8)) >> 16); - } - - //-------------------------------------------------------------------- - static inline void copy_or_blend_pix(int8u* p, const color_type& c, unsigned cover) - { - unsigned alpha = 65535 - cover * c.a; - - if(alpha < 65535) - { - if(alpha <= 65535-255*255) - { - copy_pix(p, c); - } - else - { - blend_pix(p, c, cover, alpha); - } - } - } - - //-------------------------------------------------------------------- - static inline void copy_or_blend_pix(int8u* p, const color_type& c) - { - unsigned alpha = 255 - c.a; - if(alpha < 255) - { - if(alpha == 0) - { - copy_pix(p, c); - } - else - { - p[Order::R] = (int8u)((p[Order::R] * alpha + (c.r << 8)) >> 8); - p[Order::G] = (int8u)((p[Order::G] * alpha + (c.g << 8)) >> 8); - p[Order::B] = (int8u)((p[Order::B] * alpha + (c.b << 8)) >> 8); - } - } - } - - - - public: - //-------------------------------------------------------------------- - pixel_formats_rgb24_pre(rendering_buffer& rb) - : m_rbuf(&rb) - { - } - - //-------------------------------------------------------------------- - unsigned width() const { return m_rbuf->width(); } - unsigned height() const { return m_rbuf->height(); } - - //-------------------------------------------------------------------- - color_type pixel(int x, int y) - { - int8u* p = m_rbuf->row(y) + x + x + x; - return color_type(p[Order::R], p[Order::G], p[Order::B]); - } - - //-------------------------------------------------------------------- - void copy_pixel(int x, int y, const color_type& c) - { - int8u* p = m_rbuf->row(y) + x + x + x; - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - } - - //-------------------------------------------------------------------- - void blend_pixel(int x, int y, const color_type& c, int8u cover) - { - copy_or_blend_pix(m_rbuf->row(y) + x + x + x, c, cover); - } - - //-------------------------------------------------------------------- - void copy_hline(int x, int y, unsigned len, const color_type& c) - { - int8u* p = m_rbuf->row(y) + x + x + x; - do - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p += 3; - } - while(--len); - } - - //-------------------------------------------------------------------- - void copy_vline(int x, int y, unsigned len, const color_type& c) - { - int8u* p = m_rbuf->row(y) + x + x + x; - do - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p += m_rbuf->stride(); - } - while(--len); - } - - //-------------------------------------------------------------------- - void blend_hline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { - int8u* p = m_rbuf->row(y) + x + x + x; - unsigned alpha = unsigned(cover) * c.a; - if(alpha == 255*255) - { - do - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p += 3; - } - while(--len); - } - else - { - alpha = 65535 - alpha; - do - { - blend_pix(p, c, cover, alpha); - p += 3; - } - while(--len); - } - } - - //-------------------------------------------------------------------- - void blend_vline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { - int8u* p = m_rbuf->row(y) + x + x + x; - unsigned alpha = unsigned(cover) * c.a; - if(alpha == 255*255) - { - do - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p += m_rbuf->stride(); - } - while(--len); - } - else - { - alpha = 65535 - alpha; - do - { - blend_pix(p, c, cover, alpha); - p += m_rbuf->stride(); - } - while(--len); - } - } - - - //-------------------------------------------------------------------- - void copy_from(const rendering_buffer& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) - { - memmove(m_rbuf->row(ydst) + xdst * 3, - (const void*)(from.row(ysrc) + xsrc * 3), len * 3); - } - - - //-------------------------------------------------------------------- - void blend_solid_hspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - int8u* p = m_rbuf->row(y) + x + x + x; - do - { - copy_or_blend_pix(p, c, *covers++); - p += 3; - } - while(--len); - } - - - - //-------------------------------------------------------------------- - void blend_solid_vspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - int8u* p = m_rbuf->row(y) + x + x + x; - do - { - copy_or_blend_pix(p, c, *covers++); - p += m_rbuf->stride(); - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - int8u* p = m_rbuf->row(y) + x + x + x; - do - { - copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover); - p += 3; - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - int8u* p = m_rbuf->row(y) + x + x + x; - do - { - copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover); - p += m_rbuf->stride(); - } - while(--len); - } - - private: - rendering_buffer* m_rbuf; - }; - - typedef pixel_formats_rgb24_pre pixfmt_rgb24_pre; //----pixfmt_rgb24_pre - typedef pixel_formats_rgb24_pre pixfmt_bgr24_pre; //----pixfmt_bgr24_pre -} - - -#endif diff --git a/agg2/include/agg_pixfmt_rgb555.h b/agg2/include/agg_pixfmt_rgb555.h deleted file mode 100644 index ab0eab8..0000000 --- a/agg2/include/agg_pixfmt_rgb555.h +++ /dev/null @@ -1,326 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_PIXFMT_RGB555_INCLUDED -#define AGG_PIXFMT_RGB555_INCLUDED - -#include -#include "agg_basics.h" -#include "agg_color_rgba8.h" -#include "agg_rendering_buffer.h" - -namespace agg -{ - - //------------------------------------------------------------------rgb555 - inline int16u rgb555(unsigned r, unsigned g, unsigned b) - { - return (int16u)(((r & 0xF8) << 7) | ((g & 0xF8) << 2) | (b >> 3)); - } - - - //===========================================================pixfmt_rgb555 - class pixfmt_rgb555 - { - public: - typedef rgba8 color_type; - - //-------------------------------------------------------------------- - pixfmt_rgb555(rendering_buffer& rb) - : m_rbuf(&rb) - { - } - - //-------------------------------------------------------------------- - unsigned width() const { return m_rbuf->width(); } - unsigned height() const { return m_rbuf->height(); } - - //-------------------------------------------------------------------- - color_type pixel(int x, int y) - { - unsigned rgb = ((int16u*)(m_rbuf->row(y)))[x]; - return color_type((rgb >> 7) & 0xF8, - (rgb >> 2) & 0xF8, - (rgb << 3) & 0xF8); - } - - //-------------------------------------------------------------------- - void copy_pixel(int x, int y, const color_type& c) - { - ((int16u*)(m_rbuf->row(y)))[x] = rgb555(c.r, c.g, c.b); - } - - //-------------------------------------------------------------------- - void blend_pixel(int x, int y, const color_type& c, int8u cover) - { - int alpha = int(cover) * c.a; - int16u* p = (int16u*)(m_rbuf->row(y)) + x; - if(alpha == 255*255) - { - *p = rgb555(c.r, c.g, c.b); - } - else - { - int16u rgb = *p; - int r = (rgb >> 7) & 0xF8; - int g = (rgb >> 2) & 0xF8; - int b = (rgb << 3) & 0xF8; - *p = (int16u) - ((((((c.r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) | - (((((c.g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) | - ((((c.b - b) * alpha) + (b << 16)) >> 19)); - } - } - - //-------------------------------------------------------------------- - void copy_hline(int x, int y, unsigned len, const color_type& c) - { - int16u* p = (int16u*)(m_rbuf->row(y)) + x; - int16u v = rgb555(c.r, c.g, c.b); - do - { - *p++ = v; - } - while(--len); - } - - //-------------------------------------------------------------------- - void copy_vline(int x, int y, unsigned len, const color_type& c) - { - int8u* p = m_rbuf->row(y) + (x << 1); - int16u v = rgb555(c.r, c.g, c.b); - do - { - *(int16u*)p = v; - p += m_rbuf->stride(); - } - while(--len); - } - - //-------------------------------------------------------------------- - void blend_hline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { - int16u* p = (int16u*)(m_rbuf->row(y)) + x; - int alpha = int(cover) * c.a; - if(alpha == 255*255) - { - int16u v = rgb555(c.r, c.g, c.b); - do - { - *p++ = v; - } - while(--len); - } - else - { - do - { - int16u rgb = *p; - int r = (rgb >> 7) & 0xF8; - int g = (rgb >> 2) & 0xF8; - int b = (rgb << 3) & 0xF8; - *p++ = (int16u) - ((((((c.r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) | - (((((c.g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) | - ((((c.b - b) * alpha) + (b << 16)) >> 19)); - } - while(--len); - } - } - - //-------------------------------------------------------------------- - void blend_vline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { - int8u* p = m_rbuf->row(y) + (x << 1); - int alpha = int(cover) * c.a; - if(alpha == 255*255) - { - int16u v = rgb555(c.r, c.g, c.b); - do - { - *(int16u*)p = v; - p += m_rbuf->stride(); - } - while(--len); - } - else - { - do - { - int16u rgb = *(int16u*)p; - int r = (rgb >> 7) & 0xF8; - int g = (rgb >> 2) & 0xF8; - int b = (rgb << 3) & 0xF8; - *(int16u*)p = (int16u) - ((((((c.r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) | - (((((c.g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) | - ((((c.b - b) * alpha) + (b << 16)) >> 19)); - p += m_rbuf->stride(); - } - while(--len); - } - } - - //-------------------------------------------------------------------- - void copy_from(const rendering_buffer& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) - { - memmove(m_rbuf->row(ydst) + xdst * 2, - (const void*)(from.row(ysrc) + xsrc * 2), len * 2); - } - - //-------------------------------------------------------------------- - void blend_solid_hspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - int16u* p = (int16u*)(m_rbuf->row(y)) + x; - do - { - int alpha = int(*covers++) * c.a; - if(alpha) - { - if(alpha == 255*255) - { - *p = rgb555(c.r, c.g, c.b); - } - else - { - int16u rgb = *p; - int r = (rgb >> 7) & 0xF8; - int g = (rgb >> 2) & 0xF8; - int b = (rgb << 3) & 0xF8; - *p = (int16u) - ((((((c.r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) | - (((((c.g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) | - ((((c.b - b) * alpha) + (b << 16)) >> 19)); - } - } - ++p; - } - while(--len); - } - - //-------------------------------------------------------------------- - void blend_solid_vspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - int8u* p = m_rbuf->row(y) + (x << 1); - do - { - int alpha = int(*covers++) * c.a; - - if(alpha) - { - if(alpha == 255*255) - { - *(int16u*)p = rgb555(c.r, c.g, c.b); - } - else - { - int16u rgb = *(int16u*)p; - int r = (rgb >> 7) & 0xF8; - int g = (rgb >> 2) & 0xF8; - int b = (rgb << 3) & 0xF8; - *(int16u*)p = (int16u) - ((((((c.r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) | - (((((c.g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) | - ((((c.b - b) * alpha) + (b << 16)) >> 19)); - } - } - p += m_rbuf->stride(); - } - while(--len); - } - - //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - int16u* p = (int16u*)(m_rbuf->row(y)) + x; - do - { - int alpha = colors->a * (covers ? int(*covers++) : int(cover)); - if(alpha) - { - if(alpha == 255*255) - { - *(int16u*)p = rgb555(colors->r, colors->g, colors->b); - } - else - { - int16u rgb = *p; - int r = (rgb >> 7) & 0xF8; - int g = (rgb >> 2) & 0xF8; - int b = (rgb << 3) & 0xF8; - *(int16u*)p = (int16u) - ((((((colors->r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) | - (((((colors->g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) | - ((((colors->b - b) * alpha) + (b << 16)) >> 19)); - } - } - ++p; - ++colors; - } - while(--len); - } - - //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - int8u* p = m_rbuf->row(y) + (x << 1); - do - { - int alpha = colors->a * (covers ? int(*covers++) : int(cover)); - if(alpha) - { - if(alpha == 255*255) - { - *(int16u*)p = rgb555(colors->r, colors->g, colors->b); - } - else - { - int16u rgb = *(int16u*)p; - int r = (rgb >> 7) & 0xF8; - int g = (rgb >> 2) & 0xF8; - int b = (rgb << 3) & 0xF8; - *(int16u*)p = (int16u) - ((((((colors->r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) | - (((((colors->g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) | - ((((colors->b - b) * alpha) + (b << 16)) >> 19)); - } - } - p += m_rbuf->stride(); - ++colors; - } - while(--len); - } - - private: - rendering_buffer* m_rbuf; - }; - -} - -#endif - diff --git a/agg2/include/agg_pixfmt_rgb565.h b/agg2/include/agg_pixfmt_rgb565.h deleted file mode 100644 index 45713a2..0000000 --- a/agg2/include/agg_pixfmt_rgb565.h +++ /dev/null @@ -1,326 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_PIXFMT_RGB565_INCLUDED -#define AGG_PIXFMT_RGB565_INCLUDED - -#include -#include "agg_basics.h" -#include "agg_color_rgba8.h" -#include "agg_rendering_buffer.h" - -namespace agg -{ - - //------------------------------------------------------------------rgb565 - inline int16u rgb565(unsigned r, unsigned g, unsigned b) - { - return (int16u)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); - } - - - //===========================================================pixfmt_rgb565 - class pixfmt_rgb565 - { - public: - typedef rgba8 color_type; - - //-------------------------------------------------------------------- - pixfmt_rgb565(rendering_buffer& rb) - : m_rbuf(&rb) - { - } - - //-------------------------------------------------------------------- - unsigned width() const { return m_rbuf->width(); } - unsigned height() const { return m_rbuf->height(); } - - //-------------------------------------------------------------------- - color_type pixel(int x, int y) - { - unsigned rgb = ((int16u*)(m_rbuf->row(y)))[x]; - return color_type((rgb >> 8) & 0xF8, - (rgb >> 3) & 0xFC, - (rgb << 3) & 0xF8); - } - - //-------------------------------------------------------------------- - void copy_pixel(int x, int y, const color_type& c) - { - ((int16u*)(m_rbuf->row(y)))[x] = rgb565(c.r, c.g, c.b); - } - - //-------------------------------------------------------------------- - void blend_pixel(int x, int y, const color_type& c, int8u cover) - { - int alpha = int(cover) * c.a; - int16u* p = (int16u*)(m_rbuf->row(y)) + x; - if(alpha == 255*255) - { - *p = rgb565(c.r, c.g, c.b); - } - else - { - int16u rgb = *p; - int r = (rgb >> 8) & 0xF8; - int g = (rgb >> 3) & 0xFC; - int b = (rgb << 3) & 0xF8; - *p = (int16u) - ((((((c.r - r) * alpha) + (r << 16)) >> 8) & 0xF800) | - (((((c.g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) | - ((((c.b - b) * alpha) + (b << 16)) >> 19)); - } - } - - //-------------------------------------------------------------------- - void copy_hline(int x, int y, unsigned len, const color_type& c) - { - int16u* p = (int16u*)(m_rbuf->row(y)) + x; - int16u v = rgb565(c.r, c.g, c.b); - do - { - *p++ = v; - } - while(--len); - } - - //-------------------------------------------------------------------- - void copy_vline(int x, int y, unsigned len, const color_type& c) - { - int8u* p = m_rbuf->row(y) + (x << 1); - int16u v = rgb565(c.r, c.g, c.b); - do - { - *(int16u*)p = v; - p += m_rbuf->stride(); - } - while(--len); - } - - //-------------------------------------------------------------------- - void blend_hline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { - int16u* p = (int16u*)(m_rbuf->row(y)) + x; - int alpha = int(cover) * c.a; - if(alpha == 255*255) - { - int16u v = rgb565(c.r, c.g, c.b); - do - { - *p++ = v; - } - while(--len); - } - else - { - do - { - int16u rgb = *p; - int r = (rgb >> 8) & 0xF8; - int g = (rgb >> 3) & 0xFC; - int b = (rgb << 3) & 0xF8; - *p++ = (int16u) - ((((((c.r - r) * alpha) + (r << 16)) >> 8) & 0xF800) | - (((((c.g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) | - ((((c.b - b) * alpha) + (b << 16)) >> 19)); - - } - while(--len); - } - } - - //-------------------------------------------------------------------- - void blend_vline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { - int8u* p = m_rbuf->row(y) + (x << 1); - int alpha = int(cover) * c.a; - if(alpha == 255*255) - { - int16u v = rgb565(c.r, c.g, c.b); - do - { - *(int16u*)p = v; - p += m_rbuf->stride(); - } - while(--len); - } - else - { - do - { - int16u rgb = *(int16u*)p; - int r = (rgb >> 8) & 0xF8; - int g = (rgb >> 3) & 0xFC; - int b = (rgb << 3) & 0xF8; - *(int16u*)p = (int16u) - ((((((c.r - r) * alpha) + (r << 16)) >> 8) & 0xF800) | - (((((c.g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) | - ((((c.b - b) * alpha) + (b << 16)) >> 19)); - p += m_rbuf->stride(); - } - while(--len); - } - } - - //-------------------------------------------------------------------- - void copy_from(const rendering_buffer& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) - { - memmove(m_rbuf->row(ydst) + xdst * 2, - (const void*)(from.row(ysrc) + xsrc * 2), len * 2); - } - - //-------------------------------------------------------------------- - void blend_solid_hspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - int16u* p = (int16u*)(m_rbuf->row(y)) + x; - do - { - int alpha = int(*covers++) * c.a; - if(alpha) - { - if(alpha == 255*255) - { - *p = rgb565(c.r, c.g, c.b); - } - else - { - int16u rgb = *p; - int r = (rgb >> 8) & 0xF8; - int g = (rgb >> 3) & 0xFC; - int b = (rgb << 3) & 0xF8; - *p = (int16u) - ((((((c.r - r) * alpha) + (r << 16)) >> 8) & 0xF800) | - (((((c.g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) | - ((((c.b - b) * alpha) + (b << 16)) >> 19)); - } - } - ++p; - } - while(--len); - } - - //-------------------------------------------------------------------- - void blend_solid_vspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - int8u* p = m_rbuf->row(y) + (x << 1); - do - { - int alpha = int(*covers++) * c.a; - if(alpha) - { - if(alpha == 255*255) - { - *(int16u*)p = rgb565(c.r, c.g, c.b); - } - else - { - int16u rgb = *(int16u*)p; - int r = (rgb >> 8) & 0xF8; - int g = (rgb >> 3) & 0xFC; - int b = (rgb << 3) & 0xF8; - *(int16u*)p = (int16u) - ((((((c.r - r) * alpha) + (r << 16)) >> 8) & 0xF800) | - (((((c.g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) | - ((((c.b - b) * alpha) + (b << 16)) >> 19)); - } - } - p += m_rbuf->stride(); - } - while(--len); - } - - //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - int16u* p = (int16u*)(m_rbuf->row(y)) + x; - do - { - int alpha = colors->a * (covers ? int(*covers++) : int(cover)); - if(alpha) - { - if(alpha == 255*255) - { - *(int16u*)p = rgb565(colors->r, colors->g, colors->b); - } - else - { - int16u rgb = *p; - int r = (rgb >> 8) & 0xF8; - int g = (rgb >> 3) & 0xFC; - int b = (rgb << 3) & 0xF8; - *p = (int16u) - ((((((colors->r - r) * alpha) + (r << 16)) >> 8) & 0xF800) | - (((((colors->g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) | - ((((colors->b - b) * alpha) + (b << 16)) >> 19)); - } - } - ++p; - ++colors; - } - while(--len); - } - - //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - int8u* p = m_rbuf->row(y) + (x << 1); - do - { - int alpha = colors->a * (covers ? int(*covers++) : int(cover)); - if(alpha) - { - if(alpha == 255*255) - { - *(int16u*)p = rgb565(colors->r, colors->g, colors->b); - } - else - { - int16u rgb = *(int16u*)p; - int r = (rgb >> 8) & 0xF8; - int g = (rgb >> 3) & 0xFC; - int b = (rgb << 3) & 0xF8; - *(int16u*)p = (int16u) - ((((((colors->r - r) * alpha) + (r << 16)) >> 8) & 0xF800) | - (((((colors->g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) | - ((((colors->b - b) * alpha) + (b << 16)) >> 19)); - } - } - p += m_rbuf->stride(); - ++colors; - } - while(--len); - } - - private: - rendering_buffer* m_rbuf; - }; - -} - -#endif - diff --git a/agg2/include/agg_pixfmt_rgba32.h b/agg2/include/agg_pixfmt_rgba32.h deleted file mode 100644 index 236eea5..0000000 --- a/agg2/include/agg_pixfmt_rgba32.h +++ /dev/null @@ -1,371 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_PIXFMT_RGBA32_INCLUDED -#define AGG_PIXFMT_RGBA32_INCLUDED - -#include -#include "agg_basics.h" -#include "agg_color_rgba8.h" -#include "agg_rendering_buffer.h" - -namespace agg -{ - - //====================================================pixel_formats_rgba32 - template class pixel_formats_rgba32 - { - public: - typedef rgba8 color_type; - - //-------------------------------------------------------------------- - pixel_formats_rgba32(rendering_buffer& rb) - : m_rbuf(&rb) - { - } - - //-------------------------------------------------------------------- - unsigned width() const { return m_rbuf->width(); } - unsigned height() const { return m_rbuf->height(); } - - //-------------------------------------------------------------------- - color_type pixel(int x, int y) - { - int8u* p = m_rbuf->row(y) + (x << 2); - return color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]); - } - - //-------------------------------------------------------------------- - void copy_pixel(int x, int y, const color_type& c) - { - int8u* p = m_rbuf->row(y) + (x << 2); - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p[Order::A] = (int8u)c.a; - } - - //-------------------------------------------------------------------- - void blend_pixel(int x, int y, const color_type& c, int8u cover) - { - int8u* p = m_rbuf->row(y) + (x << 2); - int alpha = int(cover) * int(c.a); - if(alpha == 255*255) - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p[Order::A] = (int8u)c.a; - } - else - { - int r = p[Order::R]; - int g = p[Order::G]; - int b = p[Order::B]; - int a = p[Order::A]; - p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16); - p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16); - p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16); - p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8); - } - } - - //-------------------------------------------------------------------- - void copy_hline(int x, int y, unsigned len, const color_type& c) - { - int32u v; - int8u* p8 = (int8u*)&v; - p8[Order::R] = (int8u)c.r; - p8[Order::G] = (int8u)c.g; - p8[Order::B] = (int8u)c.b; - p8[Order::A] = (int8u)c.a; - int32u* p32 = (int32u*)(m_rbuf->row(y)) + x; - do - { - *p32++ = v; - } - while(--len); - } - - //-------------------------------------------------------------------- - void copy_vline(int x, int y, unsigned len, const color_type& c) - { - int32u v; - int8u* p8 = (int8u*)&v; - p8[Order::R] = (int8u)c.r; - p8[Order::G] = (int8u)c.g; - p8[Order::B] = (int8u)c.b; - p8[Order::A] = (int8u)c.a; - int8u* p = m_rbuf->row(y) + (x << 2); - do - { - *(int32u*)p = v; - p += m_rbuf->stride(); - } - while(--len); - } - - //-------------------------------------------------------------------- - void blend_hline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { - int alpha = int(cover) * int(c.a); - if(alpha == 255*255) - { - int32u v; - int8u* p8 = (int8u*)&v; - p8[Order::R] = (int8u)c.r; - p8[Order::G] = (int8u)c.g; - p8[Order::B] = (int8u)c.b; - p8[Order::A] = (int8u)c.a; - int32u* p32 = (int32u*)(m_rbuf->row(y)) + x; - do - { - *p32++ = v; - } - while(--len); - } - else - { - int8u* p = m_rbuf->row(y) + (x << 2); - do - { - int r = p[Order::R]; - int g = p[Order::G]; - int b = p[Order::B]; - int a = p[Order::A]; - p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16); - p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16); - p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16); - p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8); - p += 4; - } - while(--len); - } - } - - //-------------------------------------------------------------------- - void blend_vline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { - int8u* p = m_rbuf->row(y) + (x << 2); - int alpha = int(cover) * c.a; - if(alpha == 255*255) - { - int32u v; - int8u* p8 = (int8u*)&v; - p8[Order::R] = (int8u)c.r; - p8[Order::G] = (int8u)c.g; - p8[Order::B] = (int8u)c.b; - p8[Order::A] = (int8u)c.a; - do - { - *(int32u*)p = v; - p += m_rbuf->stride(); - } - while(--len); - } - else - { - do - { - int r = p[Order::R]; - int g = p[Order::G]; - int b = p[Order::B]; - int a = p[Order::A]; - p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16); - p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16); - p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16); - p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8); - p += m_rbuf->stride(); - } - while(--len); - } - } - - - //-------------------------------------------------------------------- - void copy_from(const rendering_buffer& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) - { - memmove(m_rbuf->row(ydst) + xdst * 4, - (const void*)(from.row(ysrc) + xsrc * 4), len * 4); - } - - - //-------------------------------------------------------------------- - void blend_solid_hspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - int8u* p = m_rbuf->row(y) + (x << 2); - do - { - int alpha = int(*covers++) * c.a; - - if(alpha) - { - if(alpha == 255*255) - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p[Order::A] = (int8u)c.a; - } - else - { - int r = p[Order::R]; - int g = p[Order::G]; - int b = p[Order::B]; - int a = p[Order::A]; - p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16); - p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16); - p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16); - p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8); - } - } - p += 4; - } - while(--len); - } - - - - //-------------------------------------------------------------------- - void blend_solid_vspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - int8u* p = m_rbuf->row(y) + (x << 2); - do - { - int alpha = int(*covers++) * c.a; - - if(alpha) - { - if(alpha == 255*255) - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p[Order::A] = (int8u)c.a; - } - else - { - int r = p[Order::R]; - int g = p[Order::G]; - int b = p[Order::B]; - int a = p[Order::A]; - p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16); - p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16); - p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16); - p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8); - } - } - p += m_rbuf->stride(); - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - int8u* p = m_rbuf->row(y) + (x << 2); - do - { - int alpha = colors->a * (covers ? int(*covers++) : int(cover)); - - if(alpha) - { - if(alpha == 255*255) - { - p[Order::R] = (int8u)colors->r; - p[Order::G] = (int8u)colors->g; - p[Order::B] = (int8u)colors->b; - p[Order::A] = (int8u)colors->a; - } - else - { - int r = p[Order::R]; - int g = p[Order::G]; - int b = p[Order::B]; - int a = p[Order::A]; - p[Order::R] = (int8u)((((colors->r - r) * alpha) + (r << 16)) >> 16); - p[Order::G] = (int8u)((((colors->g - g) * alpha) + (g << 16)) >> 16); - p[Order::B] = (int8u)((((colors->b - b) * alpha) + (b << 16)) >> 16); - p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8); - } - } - p += 4; - ++colors; - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - int8u* p = m_rbuf->row(y) + (x << 2); - do - { - int alpha = colors->a * (covers ? int(*covers++) : int(cover)); - - if(alpha) - { - if(alpha == 255*255) - { - p[Order::R] = (int8u)colors->r; - p[Order::G] = (int8u)colors->g; - p[Order::B] = (int8u)colors->b; - p[Order::A] = (int8u)colors->a; - } - else - { - int r = p[Order::R]; - int g = p[Order::G]; - int b = p[Order::B]; - int a = p[Order::A]; - p[Order::R] = (int8u)((((colors->r - r) * alpha) + (r << 16)) >> 16); - p[Order::G] = (int8u)((((colors->g - g) * alpha) + (g << 16)) >> 16); - p[Order::B] = (int8u)((((colors->b - b) * alpha) + (b << 16)) >> 16); - p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8); - } - } - p += m_rbuf->stride(); - ++colors; - } - while(--len); - } - - private: - rendering_buffer* m_rbuf; - }; - - typedef pixel_formats_rgba32 pixfmt_rgba32; //----pixfmt_rgba32 - typedef pixel_formats_rgba32 pixfmt_argb32; //----pixfmt_argb32 - typedef pixel_formats_rgba32 pixfmt_abgr32; //----pixfmt_abgr32 - typedef pixel_formats_rgba32 pixfmt_bgra32; //----pixfmt_bgra32 -} - -#endif - diff --git a/agg2/include/agg_pixfmt_rgba32_plain.h b/agg2/include/agg_pixfmt_rgba32_plain.h deleted file mode 100644 index 2b49e67..0000000 --- a/agg2/include/agg_pixfmt_rgba32_plain.h +++ /dev/null @@ -1,315 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_PIXFMT_RGBA32_PLAIN_INCLUDED -#define AGG_PIXFMT_RGBA32_PLAIN_INCLUDED - -#include -#include "agg_basics.h" -#include "agg_color_rgba8.h" -#include "agg_rendering_buffer.h" - -namespace agg -{ - - - //===============================================pixel_formats_rgba32_plain - template class pixel_formats_rgba32_plain - { - public: - typedef rgba8 color_type; - - - private: - //-------------------------------------------------------------------- - static inline void copy_pix(int8u* p, const color_type& c) - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p[Order::A] = (int8u)c.a; - } - - //-------------------------------------------------------------------- - static inline void blend_pix(int8u* p, const color_type& c, unsigned alpha) - { - int a = p[Order::A]; - int r = p[Order::R] * a; - int g = p[Order::G] * a; - int b = p[Order::B] * a; - a = ((alpha << 8) + (a << 16)) - alpha * a; - p[Order::A] = (int8u)(a >> 16); - p[Order::R] = (int8u)((((((c.r << 8) - r) * alpha) + (r << 16)) / a)); - p[Order::G] = (int8u)((((((c.g << 8) - g) * alpha) + (g << 16)) / a)); - p[Order::B] = (int8u)((((((c.b << 8) - b) * alpha) + (b << 16)) / a)); - } - - //-------------------------------------------------------------------- - static inline void copy_or_blend_pix(int8u* p, const color_type& c, unsigned cover) - { - unsigned alpha = cover * c.a; -// For testing -//color_type c2 = c; -//c2.a = alpha >> 8; -//copy_or_blend_pix(p, c2); - - if(alpha) - { - if(alpha == 255*255) - { - copy_pix(p, c); - } - else - { - blend_pix(p, c, alpha); - } - } - } - - //-------------------------------------------------------------------- - static inline void copy_or_blend_pix(int8u* p, const color_type& c) - { - unsigned alpha = c.a; - if(alpha) - { - if(alpha == 255) - { - copy_pix(p, c); - } - else - { - int a = p[Order::A]; - int r = p[Order::R] * a; - int g = p[Order::G] * a; - int b = p[Order::B] * a; - a = ((alpha + a) << 8) - alpha * a; - p[Order::A] = (int8u)(a >> 8); - p[Order::R] = (int8u)((((((c.r << 8) - r) * alpha) + (r << 8)) / a)); - p[Order::G] = (int8u)((((((c.g << 8) - g) * alpha) + (g << 8)) / a)); - p[Order::B] = (int8u)((((((c.b << 8) - b) * alpha) + (b << 8)) / a)); - } - } - } - - - - public: - //-------------------------------------------------------------------- - pixel_formats_rgba32_plain(rendering_buffer& rb) - : m_rbuf(&rb) - { - } - - //-------------------------------------------------------------------- - unsigned width() const { return m_rbuf->width(); } - unsigned height() const { return m_rbuf->height(); } - - //-------------------------------------------------------------------- - color_type pixel(int x, int y) - { - int8u* p = m_rbuf->row(y) + (x << 2); - return color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]); - } - - //-------------------------------------------------------------------- - void copy_pixel(int x, int y, const color_type& c) - { - int8u* p = m_rbuf->row(y) + (x << 2); - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p[Order::A] = (int8u)c.a; - } - - //-------------------------------------------------------------------- - void blend_pixel(int x, int y, const color_type& c, int8u cover) - { - copy_or_blend_pix(m_rbuf->row(y) + (x << 2), c, cover); - } - - //-------------------------------------------------------------------- - void copy_hline(int x, int y, unsigned len, const color_type& c) - { - int32u v; - copy_pix((int8u*)&v, c); - int32u* p32 = (int32u*)(m_rbuf->row(y)) + x; - do - { - *p32++ = v; - } - while(--len); - } - - //-------------------------------------------------------------------- - void copy_vline(int x, int y, unsigned len, const color_type& c) - { - int32u v; - copy_pix((int8u*)&v, c); - int8u* p = m_rbuf->row(y) + (x << 2); - do - { - *(int32u*)p = v; - p += m_rbuf->stride(); - } - while(--len); - } - - //-------------------------------------------------------------------- - void blend_hline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { - unsigned alpha = unsigned(cover) * c.a; - if(alpha) - { - if(alpha == 255*255) - { - int32u v; - copy_pix((int8u*)&v, c); - int32u* p32 = (int32u*)(m_rbuf->row(y)) + x; - do - { - *p32++ = v; - } - while(--len); - } - else - { - int8u* p = m_rbuf->row(y) + (x << 2); - do - { - blend_pix(p, c, alpha); - p += 4; - } - while(--len); - } - } - } - - //-------------------------------------------------------------------- - void blend_vline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { - int8u* p = m_rbuf->row(y) + (x << 2); - unsigned alpha = unsigned(cover) * c.a; - if(alpha) - { - unsigned alpha = unsigned(cover) * c.a; - if(alpha == 255*255) - { - int32u v; - copy_pix((int8u*)&v, c); - do - { - *(int32u*)p = v; - p += m_rbuf->stride(); - } - while(--len); - } - else - { - do - { - blend_pix(p, c, alpha); - p += m_rbuf->stride(); - } - while(--len); - } - } - } - - - //-------------------------------------------------------------------- - void copy_from(const rendering_buffer& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) - { - memmove(m_rbuf->row(ydst) + xdst * 4, - (const void*)(from.row(ysrc) + xsrc * 4), len * 4); - } - - - //-------------------------------------------------------------------- - void blend_solid_hspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - int8u* p = m_rbuf->row(y) + (x << 2); - do - { - copy_or_blend_pix(p, c, *covers++); - p += 4; - } - while(--len); - } - - - - //-------------------------------------------------------------------- - void blend_solid_vspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - int8u* p = m_rbuf->row(y) + (x << 2); - do - { - copy_or_blend_pix(p, c, *covers++); - p += m_rbuf->stride(); - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - int8u* p = m_rbuf->row(y) + (x << 2); - do - { - copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover); - p += 4; - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - int8u* p = m_rbuf->row(y) + (x << 2); - do - { - copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover); - p += m_rbuf->stride(); - } - while(--len); - } - - private: - rendering_buffer* m_rbuf; - }; - - typedef pixel_formats_rgba32_plain pixfmt_rgba32_plain; //----pixfmt_rgba32_plain - typedef pixel_formats_rgba32_plain pixfmt_argb32_plain; //----pixfmt_argb32_plain - typedef pixel_formats_rgba32_plain pixfmt_abgr32_plain; //----pixfmt_abgr32_plain - typedef pixel_formats_rgba32_plain pixfmt_bgra32_plain; //----pixfmt_bgra32_plain -} - - -#endif diff --git a/agg2/include/agg_pixfmt_rgba32_pre.h b/agg2/include/agg_pixfmt_rgba32_pre.h deleted file mode 100644 index f0c6409..0000000 --- a/agg2/include/agg_pixfmt_rgba32_pre.h +++ /dev/null @@ -1,297 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_PIXFMT_RGBA32_PRE_INCLUDED -#define AGG_PIXFMT_RGBA32_PRE_INCLUDED - -#include -#include "agg_basics.h" -#include "agg_color_rgba8.h" -#include "agg_rendering_buffer.h" - -namespace agg -{ - - - //=================================================pixel_formats_rgba32_pre - template class pixel_formats_rgba32_pre - { - public: - typedef rgba8 color_type; - - - private: - //-------------------------------------------------------------------- - static inline void copy_pix(int8u* p, const color_type& c) - { - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p[Order::A] = (int8u)c.a; - } - - //-------------------------------------------------------------------- - static inline void blend_pix(int8u* p, const color_type& c, - unsigned cover, unsigned alpha) - { - p[Order::R] = (int8u)((p[Order::R] * alpha + ((c.r * cover) << 8)) >> 16); - p[Order::G] = (int8u)((p[Order::G] * alpha + ((c.g * cover) << 8)) >> 16); - p[Order::B] = (int8u)((p[Order::B] * alpha + ((c.b * cover) << 8)) >> 16); - p[Order::A] = (int8u)(255 - ((alpha * (255 - p[Order::A])) >> 16)); - } - - //-------------------------------------------------------------------- - static inline void copy_or_blend_pix(int8u* p, const color_type& c, unsigned cover) - { - unsigned alpha = 65535 - cover * c.a; - - if(alpha < 65535) - { - if(alpha <= 65535-255*255) - { - copy_pix(p, c); - } - else - { - blend_pix(p, c, cover, alpha); - } - } - } - - //-------------------------------------------------------------------- - static inline void copy_or_blend_pix(int8u* p, const color_type& c) - { - unsigned alpha = 255 - c.a; - if(alpha < 255) - { - if(alpha == 0) - { - copy_pix(p, c); - } - else - { - p[Order::R] = (int8u)((p[Order::R] * alpha + (c.r << 8)) >> 8); - p[Order::G] = (int8u)((p[Order::G] * alpha + (c.g << 8)) >> 8); - p[Order::B] = (int8u)((p[Order::B] * alpha + (c.b << 8)) >> 8); - p[Order::A] = (int8u)(255 - ((alpha * (255 - p[Order::A])) >> 8)); - } - } - } - - - - public: - //-------------------------------------------------------------------- - pixel_formats_rgba32_pre(rendering_buffer& rb) - : m_rbuf(&rb) - { - } - - //-------------------------------------------------------------------- - unsigned width() const { return m_rbuf->width(); } - unsigned height() const { return m_rbuf->height(); } - - //-------------------------------------------------------------------- - color_type pixel(int x, int y) - { - int8u* p = m_rbuf->row(y) + (x << 2); - return color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]); - } - - //-------------------------------------------------------------------- - void copy_pixel(int x, int y, const color_type& c) - { - int8u* p = m_rbuf->row(y) + (x << 2); - p[Order::R] = (int8u)c.r; - p[Order::G] = (int8u)c.g; - p[Order::B] = (int8u)c.b; - p[Order::A] = (int8u)c.a; - } - - //-------------------------------------------------------------------- - void blend_pixel(int x, int y, const color_type& c, int8u cover) - { - copy_or_blend_pix(m_rbuf->row(y) + (x << 2), c, cover); - } - - //-------------------------------------------------------------------- - void copy_hline(int x, int y, unsigned len, const color_type& c) - { - int32u v; - copy_pix((int8u*)&v, c); - int32u* p32 = (int32u*)(m_rbuf->row(y)) + x; - do - { - *p32++ = v; - } - while(--len); - } - - //-------------------------------------------------------------------- - void copy_vline(int x, int y, unsigned len, const color_type& c) - { - int32u v; - copy_pix((int8u*)&v, c); - int8u* p = m_rbuf->row(y) + (x << 2); - do - { - *(int32u*)p = v; - p += m_rbuf->stride(); - } - while(--len); - } - - //-------------------------------------------------------------------- - void blend_hline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { - unsigned alpha = unsigned(cover) * c.a; - if(alpha == 255*255) - { - int32u v; - copy_pix((int8u*)&v, c); - int32u* p32 = (int32u*)(m_rbuf->row(y)) + x; - do - { - *p32++ = v; - } - while(--len); - } - else - { - int8u* p = m_rbuf->row(y) + (x << 2); - alpha = 65535 - alpha; - do - { - blend_pix(p, c, cover, alpha); - p += 4; - } - while(--len); - } - } - - //-------------------------------------------------------------------- - void blend_vline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { - int8u* p = m_rbuf->row(y) + (x << 2); - unsigned alpha = unsigned(cover) * c.a; - if(alpha == 255*255) - { - int32u v; - copy_pix((int8u*)&v, c); - do - { - *(int32u*)p = v; - p += m_rbuf->stride(); - } - while(--len); - } - else - { - alpha = 65535 - alpha; - do - { - blend_pix(p, c, cover, alpha); - p += m_rbuf->stride(); - } - while(--len); - } - } - - - //-------------------------------------------------------------------- - void copy_from(const rendering_buffer& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) - { - memmove(m_rbuf->row(ydst) + xdst * 4, - (const void*)(from.row(ysrc) + xsrc * 4), len * 4); - } - - - //-------------------------------------------------------------------- - void blend_solid_hspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - int8u* p = m_rbuf->row(y) + (x << 2); - do - { - copy_or_blend_pix(p, c, *covers++); - p += 4; - } - while(--len); - } - - - - //-------------------------------------------------------------------- - void blend_solid_vspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - int8u* p = m_rbuf->row(y) + (x << 2); - do - { - copy_or_blend_pix(p, c, *covers++); - p += m_rbuf->stride(); - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - int8u* p = m_rbuf->row(y) + (x << 2); - do - { - copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover); - p += 4; - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - int8u* p = m_rbuf->row(y) + (x << 2); - do - { - copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover); - p += m_rbuf->stride(); - } - while(--len); - } - - private: - rendering_buffer* m_rbuf; - }; - - typedef pixel_formats_rgba32_pre pixfmt_rgba32_pre; //----pixfmt_rgba32_pre - typedef pixel_formats_rgba32_pre pixfmt_argb32_pre; //----pixfmt_argb32_pre - typedef pixel_formats_rgba32_pre pixfmt_abgr32_pre; //----pixfmt_abgr32_pre - typedef pixel_formats_rgba32_pre pixfmt_bgra32_pre; //----pixfmt_bgra32_pre -} - - -#endif diff --git a/agg2/include/agg_rasterizer_scanline_aa.h b/agg2/include/agg_rasterizer_scanline_aa.h deleted file mode 100644 index 15902c4..0000000 --- a/agg2/include/agg_rasterizer_scanline_aa.h +++ /dev/null @@ -1,771 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of David Turner, -// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType -// libray - in producing this work. See http://www.freetype.org for details. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// Class rasterizer_scanline_aa -// -// -//---------------------------------------------------------------------------- -#ifndef AGG_RASTERIZER_SCANLINE_AA_INCLUDED -#define AGG_RASTERIZER_SCANLINE_AA_INCLUDED - -#include -#include -#include "agg_basics.h" -#include "agg_math.h" -#include "agg_gamma_functions.h" -#include "agg_clip_liang_barsky.h" -#include "agg_render_scanlines.h" - - -namespace agg -{ - - //------------------------------------------------------------------------ - // 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_base_shift * 2, i.e, for 32-bit integers and - // 8-bits fractional part the capacity is 16 bits or [-32768...32767]. - enum - { - poly_base_shift = 8, //----poly_base_shift - poly_base_size = 1 << poly_base_shift, //----poly_base_size - poly_base_mask = poly_base_size - 1 //----poly_base_mask - }; - - //--------------------------------------------------------------poly_coord - inline int poly_coord(double c) - { - return int(c * poly_base_size); - } - - //-----------------------------------------------------------------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 - { - int16 x; - int16 y; - int packed_coord; - int cover; - int area; - - void set(int x, int y, int c, int a); - void set_coord(int x, int y); - void set_cover(int c, int a); - void add_cover(int c, int a); - }; - - - //--------------------------------------------------------------outline_aa - // An internal class that implements the main rasterization algorithm. - // Used in the rasterizer. Should not be used direcly. - class outline_aa - { - enum - { - cell_block_shift = 12, - cell_block_size = 1 << cell_block_shift, - cell_block_mask = cell_block_size - 1, - cell_block_pool = 256, - cell_block_limit = 1024 - }; - - public: - - ~outline_aa(); - outline_aa(); - - void reset(); - - void move_to(int x, int y); - void line_to(int x, int y); - - int min_x() const { return m_min_x; } - int min_y() const { return m_min_y; } - int max_x() const { return m_max_x; } - int max_y() const { return m_max_y; } - - const cell_aa* const* cells(); - unsigned num_cells() { cells(); return m_num_cells; } - bool sorted() const { return m_sorted; } - - private: - outline_aa(const outline_aa&); - const outline_aa& operator = (const outline_aa&); - - void set_cur_cell(int x, int y); - void add_cur_cell(); - void sort_cells(); - void render_hline(int ey, int x1, int y1, int x2, int y2); - void render_line(int x1, int y1, int x2, int y2); - void allocate_block(); - - static void qsort_cells(cell_aa** start, unsigned num); - - private: - unsigned m_num_blocks; - unsigned m_max_blocks; - unsigned m_cur_block; - unsigned m_num_cells; - cell_aa** m_cells; - cell_aa* m_cur_cell_ptr; - cell_aa** m_sorted_cells; - unsigned m_sorted_size; - cell_aa m_cur_cell; - int m_cur_x; - int m_cur_y; - int m_min_x; - int m_min_y; - int m_max_x; - int m_max_y; - bool m_sorted; - }; - - - //----------------------------------------------------------filling_rule_e - enum filling_rule_e - { - fill_non_zero, - fill_even_odd - }; - - - - //----------------------------------------------------------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 - // - // - inline unsigned clipping_flags(int x, int y, const rect& clip_box) - { - return (x > clip_box.x2) | - ((y > clip_box.y2) << 1) | - ((x < clip_box.x1) << 2) | - ((y < clip_box.y1) << 3); - } - - - //==================================================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_base_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 rasterizer_scanline_aa - { - enum status - { - status_initial, - status_line_to, - status_closed - }; - - struct iterator - { - const cell_aa* const* cells; - int cover; - int last_y; - }; - - public: - enum - { - aa_shift = AA_Shift, - aa_num = 1 << aa_shift, - aa_mask = aa_num - 1, - aa_2num = aa_num * 2, - aa_2mask = aa_2num - 1 - }; - - //-------------------------------------------------------------------- - rasterizer_scanline_aa() : - m_filling_rule(fill_non_zero), - m_clipped_start_x(0), - m_clipped_start_y(0), - m_start_x(0), - m_start_y(0), - m_prev_x(0), - m_prev_y(0), - m_prev_flags(0), - m_status(status_initial), - m_clipping(false) - { - int i; - for(i = 0; i < aa_num; i++) m_gamma[i] = i; - } - - //-------------------------------------------------------------------- - template - rasterizer_scanline_aa(const GammaF& gamma_function) : - m_filling_rule(fill_non_zero), - m_clipped_start_x(0), - m_clipped_start_y(0), - m_start_x(0), - m_start_y(0), - m_prev_x(0), - m_prev_y(0), - m_prev_flags(0), - m_status(status_initial), - m_clipping(false) - { - gamma(gamma_function); - } - - //-------------------------------------------------------------------- - void reset(); - void filling_rule(filling_rule_e filling_rule); - void clip_box(double x1, double y1, double x2, double y2); - void reset_clipping(); - - //-------------------------------------------------------------------- - template void gamma(const GammaF& gamma_function) - { - int i; - for(i = 0; i < aa_num; i++) - { - m_gamma[i] = int(floor(gamma_function(double(i) / aa_mask) * aa_mask + 0.5)); - } - } - - //-------------------------------------------------------------------- - unsigned apply_gamma(unsigned cover) const - { - return m_gamma[cover]; - } - - //-------------------------------------------------------------------- - void add_vertex(double x, double y, unsigned cmd); - void move_to(int x, int y); - void line_to(int x, int y); - void close_polygon(); - void move_to_d(double x, double y); - void line_to_d(double x, double y); - - //-------------------------------------------------------------------- - 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(); } - - //-------------------------------------------------------------------- - unsigned calculate_alpha(int area) const - { - int cover = area >> (poly_base_shift*2 + 1 - aa_shift); - - if(cover < 0) cover = -cover; - if(m_filling_rule == fill_even_odd) - { - cover &= aa_2mask; - if(cover > aa_num) - { - cover = aa_2num - cover; - } - } - if(cover > aa_mask) cover = aa_mask; - return m_gamma[cover]; - } - - //-------------------------------------------------------------------- - void sort() - { - m_outline.cells(); - } - - - //-------------------------------------------------------------------- - bool rewind_scanlines() - { - close_polygon(); - m_iterator.cells = m_outline.cells(); - if(m_outline.num_cells() == 0) - { - return false; - } - m_iterator.cover = 0; - m_iterator.last_y = (*m_iterator.cells)->y; - return true; - } - - - //-------------------------------------------------------------------- - template bool sweep_scanline(Scanline& sl) - { - sl.reset_spans(); - for(;;) - { - const cell_aa* cur_cell = *m_iterator.cells; - if(cur_cell == 0) return false; - ++m_iterator.cells; - m_iterator.last_y = cur_cell->y; - - for(;;) - { - int coord = cur_cell->packed_coord; - int area = cur_cell->area; - int last_x = cur_cell->x; - - m_iterator.cover += cur_cell->cover; - - //accumulate all cells with the same coordinates - for(; (cur_cell = *m_iterator.cells) != 0; ++m_iterator.cells) - { - if(cur_cell->packed_coord != coord) break; - area += cur_cell->area; - m_iterator.cover += cur_cell->cover; - } - - int alpha; - if(cur_cell == 0 || cur_cell->y != m_iterator.last_y) - { - - if(area) - { - alpha = calculate_alpha((m_iterator.cover << (poly_base_shift + 1)) - area); - if(alpha) - { - sl.add_cell(last_x, alpha); - } - ++last_x; - } - break; - } - - ++m_iterator.cells; - - if(area) - { - alpha = calculate_alpha((m_iterator.cover << (poly_base_shift + 1)) - area); - if(alpha) - { - sl.add_cell(last_x, alpha); - } - ++last_x; - } - - if(cur_cell->x > last_x) - { - alpha = calculate_alpha(m_iterator.cover << (poly_base_shift + 1)); - if(alpha) - { - sl.add_span(last_x, cur_cell->x - last_x, alpha); - } - } - } - if(sl.num_spans()) - { - sl.finalize(m_iterator.last_y); - break; - } - } - return true; - } - - - //-------------------------------------------------------------------- - bool hit_test(int tx, int ty); - - - //-------------------------------------------------------------------- - void add_xy(const double* x, const double* y, unsigned n) - { - if(n > 2) - { - move_to_d(*x++, *y++); - --n; - do - { - line_to_d(*x++, *y++); - } - while(--n); - } - } - - //------------------------------------------------------------------- - template - void add_path(VertexSource& vs, unsigned id=0) - { - double x; - double y; - - unsigned cmd; - vs.rewind(id); - while(!is_stop(cmd = vs.vertex(&x, &y))) - { - add_vertex(x, y, cmd); - } - } - - - private: - //-------------------------------------------------------------------- - // Disable copying - rasterizer_scanline_aa(const rasterizer_scanline_aa&); - const rasterizer_scanline_aa& - operator = (const rasterizer_scanline_aa&); - - //-------------------------------------------------------------------- - void move_to_no_clip(int x, int y); - void line_to_no_clip(int x, int y); - void close_polygon_no_clip(); - void clip_segment(int x, int y); - - private: - outline_aa m_outline; - int m_gamma[aa_num]; - filling_rule_e m_filling_rule; - int m_clipped_start_x; - int m_clipped_start_y; - int m_start_x; - int m_start_y; - int m_prev_x; - int m_prev_y; - unsigned m_prev_flags; - unsigned m_status; - rect m_clip_box; - bool m_clipping; - iterator m_iterator; - }; - - - - - - - - - - - //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::reset() - { - m_outline.reset(); - m_status = status_initial; - } - - //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::filling_rule(filling_rule_e filling_rule) - { - m_filling_rule = filling_rule; - } - - //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::clip_box(double x1, double y1, double x2, double y2) - { - reset(); - m_clip_box = rect(poly_coord(x1), poly_coord(y1), - poly_coord(x2), poly_coord(y2)); - m_clip_box.normalize(); - m_clipping = true; - } - - //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::reset_clipping() - { - reset(); - m_clipping = false; - } - - - - //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::move_to_no_clip(int x, int y) - { - if(m_status == status_line_to) - { - close_polygon_no_clip(); - } - m_outline.move_to(x, y); - m_clipped_start_x = x; - m_clipped_start_y = y; - m_status = status_line_to; - } - - - //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::line_to_no_clip(int x, int y) - { - if(m_status != status_initial) - { - m_outline.line_to(x, y); - m_status = status_line_to; - } - } - - - //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::close_polygon_no_clip() - { - if(m_status == status_line_to) - { - m_outline.line_to(m_clipped_start_x, m_clipped_start_y); - m_status = status_closed; - } - } - - - //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::clip_segment(int x, int y) - { - unsigned flags = clipping_flags(x, y, m_clip_box); - if(m_prev_flags == flags) - { - if(flags == 0) - { - if(m_status == status_initial) - { - move_to_no_clip(x, y); - } - else - { - line_to_no_clip(x, y); - } - } - } - else - { - int cx[4]; - int cy[4]; - unsigned n = clip_liang_barsky(m_prev_x, m_prev_y, - x, y, - m_clip_box, - cx, cy); - const int* px = cx; - const int* py = cy; - while(n--) - { - if(m_status == status_initial) - { - move_to_no_clip(*px++, *py++); - } - else - { - line_to_no_clip(*px++, *py++); - } - } - } - m_prev_flags = flags; - m_prev_x = x; - m_prev_y = y; - } - - - - //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::add_vertex(double x, double y, unsigned cmd) - { - if(is_close(cmd)) - { - close_polygon(); - } - else - { - if(is_move_to(cmd)) - { - move_to(poly_coord(x), poly_coord(y)); - } - else - { - if(is_vertex(cmd)) - { - line_to(poly_coord(x), poly_coord(y)); - } - } - } - } - - - - //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::move_to(int x, int y) - { - if(m_clipping) - { - if(m_outline.sorted()) - { - reset(); - } - if(m_status == status_line_to) - { - close_polygon(); - } - m_prev_x = m_start_x = x; - m_prev_y = m_start_y = y; - m_status = status_initial; - m_prev_flags = clipping_flags(x, y, m_clip_box); - if(m_prev_flags == 0) - { - move_to_no_clip(x, y); - } - } - else - { - move_to_no_clip(x, y); - } - } - - //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::line_to(int x, int y) - { - if(m_clipping) - { - clip_segment(x, y); - } - else - { - line_to_no_clip(x, y); - } - } - - //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::close_polygon() - { - if(m_clipping) - { - clip_segment(m_start_x, m_start_y); - } - close_polygon_no_clip(); - } - - //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::move_to_d(double x, double y) - { - move_to(poly_coord(x), poly_coord(y)); - } - - //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::line_to_d(double x, double y) - { - line_to(poly_coord(x), poly_coord(y)); - } - - - //------------------------------------------------------------------------ - template - bool rasterizer_scanline_aa::hit_test(int tx, int ty) - { - close_polygon(); - const cell_aa* const* cells = m_outline.cells(); - if(m_outline.num_cells() == 0) return false; - - int cover = 0; - - const cell_aa* cur_cell = *cells++; - for(;;) - { - int alpha; - int coord = cur_cell->packed_coord; - int x = cur_cell->x; - int y = cur_cell->y; - - if(y > ty) return false; - - int area = cur_cell->area; - cover += cur_cell->cover; - - while((cur_cell = *cells++) != 0) - { - if(cur_cell->packed_coord != coord) break; - area += cur_cell->area; - cover += cur_cell->cover; - } - - if(area) - { - alpha = calculate_alpha((cover << (poly_base_shift + 1)) - area); - if(alpha) - { - if(tx == x && ty == y) return true; - } - x++; - } - - if(!cur_cell) break; - - if(cur_cell->x > x) - { - alpha = calculate_alpha(cover << (poly_base_shift + 1)); - if(alpha) - { - if(ty == y && tx >= x && tx <= cur_cell->x) return true; - } - } - } - return false; - } - -} - - - -#endif - diff --git a/agg2/include/agg_render_scanlines.h b/agg2/include/agg_render_scanlines.h deleted file mode 100644 index de9f345..0000000 --- a/agg2/include/agg_render_scanlines.h +++ /dev/null @@ -1,66 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_RENDER_SCANLINES_INCLUDED -#define AGG_RENDER_SCANLINES_INCLUDED - -#include "agg_basics.h" - -namespace agg -{ - //========================================================render_scanlines - template - void render_scanlines(Rasterizer& ras, Scanline& sl, Renderer& ren) - { - if(ras.rewind_scanlines()) - { - sl.reset(ras.min_x(), ras.max_x()); - ren.prepare(unsigned(ras.max_x() - ras.min_x() + 2)); - - while(ras.sweep_scanline(sl)) - { - ren.render(sl); - } - } - } - - - //========================================================render_all_paths - template - void render_all_paths(Rasterizer& ras, - Scanline& sl, - Renderer& r, - VertexSource& vs, - const ColorStorage& as, - const PathId& id, - unsigned num_paths) - { - for(unsigned i = 0; i < num_paths; i++) - { - ras.reset(); - ras.add_path(vs, id[i]); - r.color(as[i]); - render_scanlines(ras, sl, r); - } - } - - -} - -#endif - - - diff --git a/agg2/include/agg_renderer_base.h b/agg2/include/agg_renderer_base.h deleted file mode 100644 index f83406d..0000000 --- a/agg2/include/agg_renderer_base.h +++ /dev/null @@ -1,420 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// class renderer_base -// -//---------------------------------------------------------------------------- - -#ifndef AGG_RENDERER_BASE_INCLUDED -#define AGG_RENDERER_BASE_INCLUDED - -#include "agg_basics.h" -#include "agg_rendering_buffer.h" - -namespace agg -{ - //-----------------------------------------------------------renderer_base - template class renderer_base - { - public: - typedef PixelFormat pixfmt_type; - typedef typename pixfmt_type::color_type color_type; - - //-------------------------------------------------------------------- - renderer_base(pixfmt_type& ren) : - m_ren(&ren), - m_clip_box(0, 0, ren.width() - 1, ren.height() - 1) - { - } - - //-------------------------------------------------------------------- - const pixfmt_type& ren() const { return *m_ren; } - pixfmt_type& ren() { return *m_ren; } - - //-------------------------------------------------------------------- - unsigned width() const { return m_ren->width(); } - unsigned height() const { return m_ren->height(); } - - //-------------------------------------------------------------------- - bool clip_box(int x1, int y1, int x2, int y2) - { - rect cb(x1, y1, x2, y2); - cb.normalize(); - if(cb.clip(rect(0, 0, width() - 1, height() - 1))) - { - m_clip_box = cb; - return true; - } - m_clip_box.x1 = 1; - m_clip_box.y1 = 1; - m_clip_box.x2 = 0; - m_clip_box.y2 = 0; - return false; - } - - //-------------------------------------------------------------------- - void reset_clipping(bool visibility) - { - if(visibility) - { - m_clip_box.x1 = 0; - m_clip_box.y1 = 0; - m_clip_box.x2 = width() - 1; - m_clip_box.y2 = height() - 1; - } - else - { - m_clip_box.x1 = 1; - m_clip_box.y1 = 1; - m_clip_box.x2 = 0; - m_clip_box.y2 = 0; - } - } - - //-------------------------------------------------------------------- - void clip_box_naked(int x1, int y1, int x2, int y2) - { - m_clip_box.x1 = x1; - m_clip_box.y1 = y1; - m_clip_box.x2 = x2; - m_clip_box.y2 = y2; - } - - //-------------------------------------------------------------------- - bool inbox(int x, int y) const - { - return x >= m_clip_box.x1 && y >= m_clip_box.y1 && - x <= m_clip_box.x2 && y <= m_clip_box.y2; - } - - //-------------------------------------------------------------------- - void first_clip_box() {} - bool next_clip_box() { return false; } - - //-------------------------------------------------------------------- - const rect& clip_box() const { return m_clip_box; } - int xmin() const { return m_clip_box.x1; } - int ymin() const { return m_clip_box.y1; } - int xmax() const { return m_clip_box.x2; } - int ymax() const { return m_clip_box.y2; } - - //-------------------------------------------------------------------- - const rect& bounding_clip_box() const { return m_clip_box; } - int bounding_xmin() const { return m_clip_box.x1; } - int bounding_ymin() const { return m_clip_box.y1; } - int bounding_xmax() const { return m_clip_box.x2; } - int bounding_ymax() const { return m_clip_box.y2; } - - //-------------------------------------------------------------------- - void clear(const color_type& c) - { - unsigned y; - if(width()) - { - for(y = 0; y < height(); y++) - { - m_ren->copy_hline(0, y, width(), c); - } - } - } - - //-------------------------------------------------------------------- - void copy_pixel(int x, int y, const color_type& c) - { - if(inbox(x, y)) - { - m_ren->copy_pixel(x, y, c); - } - } - - //-------------------------------------------------------------------- - void blend_pixel(int x, int y, const color_type& c, cover_type cover) - { - if(inbox(x, y)) - { - m_ren->blend_pixel(x, y, c, cover); - } - } - - //-------------------------------------------------------------------- - color_type pixel(int x, int y) const - { - return inbox(x, y) ? - m_ren->pixel(x, y) : - color_type::no_color(); - } - - //-------------------------------------------------------------------- - void copy_hline(int x1, int y, int x2, const color_type& c) - { - if(x1 > x2) { int t = x2; x2 = x1; x1 = t; } - if(y > ymax()) return; - if(y < ymin()) return; - if(x1 > xmax()) return; - if(x2 < xmin()) return; - - if(x1 < xmin()) x1 = xmin(); - if(x2 > xmax()) x2 = xmax(); - - m_ren->copy_hline(x1, y, x2 - x1 + 1, c); - } - - //-------------------------------------------------------------------- - void copy_vline(int x, int y1, int y2, const color_type& c) - { - if(y1 > y2) { int t = y2; y2 = y1; y1 = t; } - if(x > xmax()) return; - if(x < xmin()) return; - if(y1 > ymax()) return; - if(y2 < ymin()) return; - - if(y1 < ymin()) y1 = ymin(); - if(y2 > ymax()) y2 = ymax(); - - m_ren->copy_vline(x, y1, y2 - y1 + 1, c); - } - - //-------------------------------------------------------------------- - void blend_hline(int x1, int y, int x2, - const color_type& c, cover_type cover) - { - if(x1 > x2) { int t = x2; x2 = x1; x1 = t; } - if(y > ymax()) return; - if(y < ymin()) return; - if(x1 > xmax()) return; - if(x2 < xmin()) return; - - if(x1 < xmin()) x1 = xmin(); - if(x2 > xmax()) x2 = xmax(); - - m_ren->blend_hline(x1, y, x2 - x1 + 1, c, cover); - } - - //-------------------------------------------------------------------- - void blend_vline(int x, int y1, int y2, - const color_type& c, cover_type cover) - { - if(y1 > y2) { int t = y2; y2 = y1; y1 = t; } - if(x > xmax()) return; - if(x < xmin()) return; - if(y1 > ymax()) return; - if(y2 < ymin()) return; - - if(y1 < ymin()) y1 = ymin(); - if(y2 > ymax()) y2 = ymax(); - - m_ren->blend_vline(x, y1, y2 - y1 + 1, c, cover); - } - - - //-------------------------------------------------------------------- - void copy_bar(int x1, int y1, int x2, int y2, const color_type& c) - { - rect rc(x1, y1, x2, y2); - rc.normalize(); - if(rc.clip(clip_box())) - { - int y; - for(y = rc.y1; y <= rc.y2; y++) - { - m_ren->copy_hline(rc.x1, y, unsigned(rc.x2 - rc.x1 + 1), c); - } - } - } - - //-------------------------------------------------------------------- - void blend_bar(int x1, int y1, int x2, int y2, - const color_type& c, cover_type cover) - { - rect rc(x1, y1, x2, y2); - rc.normalize(); - if(rc.clip(clip_box())) - { - int y; - for(y = rc.y1; y <= rc.y2; y++) - { - m_ren->blend_hline(rc.x1, - y, - unsigned(rc.x2 - rc.x1 + 1), - c, - cover); - } - } - } - - - //-------------------------------------------------------------------- - void blend_solid_hspan(int x, int y, int len, - const color_type& c, - const cover_type* covers) - { - if(y > ymax()) return; - if(y < ymin()) return; - - if(x < xmin()) - { - len -= xmin() - x; - if(len <= 0) return; - covers += xmin() - x; - x = xmin(); - } - if(x + len > xmax()) - { - len = xmax() - x + 1; - if(len <= 0) return; - } - m_ren->blend_solid_hspan(x, y, len, c, covers); - } - - //-------------------------------------------------------------------- - void blend_solid_vspan(int x, int y, int len, - const color_type& c, - const cover_type* covers) - { - if(x > xmax()) return; - if(x < xmin()) return; - - if(y < ymin()) - { - len -= ymin() - y; - if(len <= 0) return; - covers += ymin() - y; - y = ymin(); - } - if(y + len > ymax()) - { - len = ymax() - y + 1; - if(len <= 0) return; - } - m_ren->blend_solid_vspan(x, y, len, c, covers); - } - - //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) - { - if(y > ymax()) return; - if(y < ymin()) return; - - if(x < xmin()) - { - int d = xmin() - x; - len -= d; - if(len <= 0) return; - if(covers) covers += d; - colors += d; - x = xmin(); - } - if(x + len > xmax()) - { - len = xmax() - x + 1; - if(len <= 0) return; - } - m_ren->blend_color_hspan(x, y, len, colors, covers, cover); - } - - //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) - { - if(x > xmax()) return; - if(x < xmin()) return; - - if(y < ymin()) - { - int d = ymin() - y; - len -= d; - if(len <= 0) return; - if(covers) covers += d; - colors += d; - y = ymin(); - } - if(y + len > ymax()) - { - len = ymax() - y + 1; - if(len <= 0) return; - } - m_ren->blend_color_vspan(x, y, len, colors, covers, cover); - } - - //-------------------------------------------------------------------- - void blend_color_hspan_no_clip(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) - { - m_ren->blend_color_hspan(x, y, len, colors, covers, cover); - } - - //-------------------------------------------------------------------- - void blend_color_vspan_no_clip(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) - { - m_ren->blend_color_vspan(x, y, len, colors, covers, cover); - } - - //-------------------------------------------------------------------- - void copy_from(const rendering_buffer& from, - const rect* rc=0, - int x_to=0, - int y_to=0) - { - rect tmp_rect(0, 0, from.width(), from.height()); - if(rc == 0) - { - rc = &tmp_rect; - } - - rect rc2(*rc); - rc2.normalize(); - if(rc2.clip(rect(0, 0, from.width() - 1, from.height() - 1))) - { - rect rc3(x_to + rc2.x1 - rc->x1, - y_to + rc2.y1 - rc->y1, - x_to + rc2.x2 - rc->x1, - y_to + rc2.y2 - rc->y1); - rc3.normalize(); - - if(rc3.clip(clip_box())) - { - while(rc3.y1 <= rc3.y2) - { - m_ren->copy_from(from, - rc3.x1, rc3.y1, - rc2.x1, rc2.y1, - rc3.x2 - rc3.x1 + 1); - ++rc2.y1; - ++rc3.y1; - } - } - } - } - - - private: - pixfmt_type* m_ren; - rect m_clip_box; - }; - - -} - -#endif diff --git a/agg2/include/agg_renderer_scanline.h b/agg2/include/agg_renderer_scanline.h deleted file mode 100644 index d928b37..0000000 --- a/agg2/include/agg_renderer_scanline.h +++ /dev/null @@ -1,285 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_RENDERER_SCANLINE_INCLUDED -#define AGG_RENDERER_SCANLINE_INCLUDED - -#include "agg_basics.h" -#include "agg_renderer_base.h" -#include "agg_render_scanlines.h" - -namespace agg -{ - - //====================================================renderer_scanline_aa - template class renderer_scanline_aa - { - public: - typedef BaseRenderer base_ren_type; - - //-------------------------------------------------------------------- - renderer_scanline_aa(base_ren_type& ren, SpanGenerator& span_gen) : - m_ren(&ren), - m_span_gen(&span_gen) - { - } - - //-------------------------------------------------------------------- - void prepare(unsigned max_span_len) - { - m_span_gen->prepare(max_span_len); - } - - //-------------------------------------------------------------------- - template void render(const Scanline& sl) - { - int y = sl.y(); - m_ren->first_clip_box(); - do - { - int xmin = m_ren->xmin(); - int xmax = m_ren->xmax(); - - if(y >= m_ren->ymin() && y <= m_ren->ymax()) - { - unsigned num_spans = sl.num_spans(); - typename Scanline::const_iterator span = sl.begin(); - do - { - int x = span->x; - int len = span->len; - bool solid = false; - const typename Scanline::cover_type* covers = span->covers; - - if(len < 0) - { - solid = true; - len = -len; - } - - if(x < xmin) - { - len -= xmin - x; - covers += xmin - x; - x = xmin; - } - if(len > 0) - { - if(x + len > xmax) - { - len = xmax - x + 1; - } - if(len > 0) - { - m_ren->blend_color_hspan_no_clip( - x, y, len, - m_span_gen->generate(x, y, len), - solid ? 0 : covers, - *covers); - } - } - ++span; - } - while(--num_spans); - } - } - while(m_ren->next_clip_box()); - } - - private: - base_ren_type* m_ren; - SpanGenerator* m_span_gen; - }; - - - - //==============================================renderer_scanline_aa_solid - template class renderer_scanline_aa_solid - { - public: - typedef BaseRenderer base_ren_type; - typedef typename base_ren_type::color_type color_type; - - //-------------------------------------------------------------------- - renderer_scanline_aa_solid(base_ren_type& ren) : - m_ren(&ren) - { - } - - //-------------------------------------------------------------------- - void color(const color_type& c) { m_color = c; } - const color_type& color() const { return m_color; } - - //-------------------------------------------------------------------- - void prepare(unsigned) {} - - //-------------------------------------------------------------------- - template void render(const Scanline& sl) - { - int y = sl.y(); - unsigned num_spans = sl.num_spans(); - typename Scanline::const_iterator span = sl.begin(); - - do - { - int x = span->x; - if(span->len > 0) - { - m_ren->blend_solid_hspan(x, y, (unsigned)span->len, - m_color, - span->covers); - } - else - { - m_ren->blend_hline(x, y, (unsigned)(x - span->len - 1), - m_color, - *(span->covers)); - } - ++span; - } - while(--num_spans); - } - - private: - base_ren_type* m_ren; - color_type m_color; - }; - - - - - - - - //===================================================renderer_scanline_bin - template class renderer_scanline_bin - { - public: - typedef BaseRenderer base_ren_type; - - //-------------------------------------------------------------------- - renderer_scanline_bin(base_ren_type& ren, SpanGenerator& span_gen) : - m_ren(&ren), - m_span_gen(&span_gen) - { - } - - //-------------------------------------------------------------------- - void prepare(unsigned max_span_len) - { - m_span_gen->prepare(max_span_len); - } - - //-------------------------------------------------------------------- - template void render(const Scanline& sl) - { - int y = sl.y(); - m_ren->first_clip_box(); - do - { - int xmin = m_ren->xmin(); - int xmax = m_ren->xmax(); - - if(y >= m_ren->ymin() && y <= m_ren->ymax()) - { - unsigned num_spans = sl.num_spans(); - typename Scanline::const_iterator span = sl.begin(); - do - { - int x = span->x; - int len = span->len; - - if(len < 0) len = -len; - if(x < xmin) - { - len -= xmin - x; - x = xmin; - } - if(len > 0) - { - if(x + len > xmax) - { - len = xmax - x + 1; - } - if(len > 0) - { - m_ren->blend_color_hspan_no_clip( - x, y, len, - m_span_gen->generate(x, y, len), - 0); - } - } - ++span; - } - while(--num_spans); - } - } - while(m_ren->next_clip_box()); - } - - private: - base_ren_type* m_ren; - SpanGenerator* m_span_gen; - }; - - - - //=============================================renderer_scanline_bin_solid - template class renderer_scanline_bin_solid - { - public: - typedef BaseRenderer base_ren_type; - typedef typename base_ren_type::color_type color_type; - - //-------------------------------------------------------------------- - renderer_scanline_bin_solid(base_ren_type& ren) : - m_ren(&ren) - { - } - - //-------------------------------------------------------------------- - void color(const color_type& c) { m_color = c; } - const color_type& color() const { return m_color; } - - //-------------------------------------------------------------------- - void prepare(unsigned) {} - - //-------------------------------------------------------------------- - template void render(const Scanline& sl) - { - unsigned num_spans = sl.num_spans(); - typename Scanline::const_iterator span = sl.begin(); - do - { - m_ren->blend_hline(span->x, - sl.y(), - span->x - 1 + ((span->len < 0) ? - -span->len : - span->len), - m_color, - cover_full); - ++span; - } - while(--num_spans); - } - - private: - base_ren_type* m_ren; - color_type m_color; - }; - -} - -#endif diff --git a/agg2/include/agg_rendering_buffer.h b/agg2/include/agg_rendering_buffer.h deleted file mode 100644 index d11c083..0000000 --- a/agg2/include/agg_rendering_buffer.h +++ /dev/null @@ -1,149 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// class rendering_buffer -// -//---------------------------------------------------------------------------- - -#ifndef AGG_RENDERING_BUFFER_INCLUDED -#define AGG_RENDERING_BUFFER_INCLUDED - -#include "agg_basics.h" - -namespace agg -{ - - //==========================================================row_ptr_cache - template class row_ptr_cache - { - public: - //------------------------------------------------------------------- - ~row_ptr_cache() - { - delete [] m_rows; - } - - //------------------------------------------------------------------- - row_ptr_cache() : - m_buf(0), - m_rows(0), - m_width(0), - m_height(0), - m_stride(0), - m_max_height(0) - { - } - - //-------------------------------------------------------------------- - row_ptr_cache(T* buf, unsigned width, unsigned height, int stride) : - m_buf(0), - m_rows(0), - m_width(0), - m_height(0), - m_stride(0), - m_max_height(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_max_height) - { - delete [] m_rows; - m_rows = new T* [m_max_height = height]; - } - - T* row_ptr = m_buf; - - if(stride < 0) - { - row_ptr = m_buf - int(height - 1) * stride; - } - - T** rows = m_rows; - - while(height--) - { - *rows++ = row_ptr; - row_ptr += stride; - } - } - - //-------------------------------------------------------------------- - const T* buf() const { return m_buf; } - unsigned width() const { return m_width; } - unsigned height() const { return m_height; } - int stride() const { return m_stride; } - unsigned stride_abs() const - { - return (m_stride < 0) ? - unsigned(-m_stride) : - unsigned(m_stride); - } - - //-------------------------------------------------------------------- - T* row(unsigned y) { return m_rows[y]; } - const T* row(unsigned y) const { return m_rows[y]; } - T const* const* rows() const { return m_rows; } - - //-------------------------------------------------------------------- - void copy_from(const row_ptr_cache& mtx) - { - unsigned h = height(); - if(mtx.height() < h) h = mtx.height(); - - unsigned l = stride_abs(); - if(mtx.stride_abs() < l) l = mtx.stride_abs(); - - l *= sizeof(T); - - unsigned y; - for (y = 0; y < h; y++) - { - memcpy(row(y), mtx.row(y), l); - } - } - - private: - //-------------------------------------------------------------------- - // Prohibit copying - row_ptr_cache(const row_ptr_cache&); - const row_ptr_cache& operator = (const row_ptr_cache&); - - private: - //-------------------------------------------------------------------- - T* m_buf; // Pointer to renrdering buffer - 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 - unsigned m_max_height; // The maximal height (currently allocated) - }; - - - - //========================================================rendering_buffer - typedef row_ptr_cache rendering_buffer; - -} - - -#endif diff --git a/agg2/include/agg_scanline_bin.h b/agg2/include/agg_scanline_bin.h deleted file mode 100644 index ea7cc52..0000000 --- a/agg2/include/agg_scanline_bin.h +++ /dev/null @@ -1,171 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// Class scanline_bin - binary scanline. -// -//---------------------------------------------------------------------------- -#ifndef AGG_SCANLINE_BIN_INCLUDED -#define AGG_SCANLINE_BIN_INCLUDED - -#include "agg_basics.h" - -namespace agg -{ - - //=============================================================scanline_bin - // - // This is binary scaline container which supports the interface - // used in the rasterizer::render(). See description of agg_scanline_u8 - // for details. - // - // Rendering: - //------------------------------------------------------------------------- - // - // int y = sl.y(); - // - // ************************************ - // ...Perform vertical clipping here... - // ************************************ - // - // unsigned num_spans = sl.num_spans(); - // const agg::scanline_bin::span* cur_span = sl.spans(); - // - // do - // { - // x = cur_span->x; - // len = cur_span->len; - // - // ************************************** - // ...Perform horizontal clipping here... - // ************************************** - // - // hor_line(x, y, len) - // ++cur_span; - // } - // while(--num_spans); - // - //------------------------------------------------------------------------ - class scanline_bin - { - public: - struct span - { - int16 x; - int16 len; - }; - - typedef const span* const_iterator; - - ~scanline_bin() - { - delete [] m_spans; - } - - scanline_bin() : - m_max_len(0), - m_last_x(0x7FFF), - m_spans(0), - m_cur_span(0) - { - } - - void reset(int min_x, int max_x); - void add_cell(int x, unsigned); - void add_cells(int x, unsigned len, const void*); - void add_span(int x, unsigned len, unsigned); - void finalize(int y) { m_y = y; } - void reset_spans(); - - int y() const { return m_y; } - unsigned num_spans() const { return unsigned(m_cur_span - m_spans); } - const_iterator begin() const { return m_spans + 1; } - - private: - scanline_bin(const scanline_bin&); - const scanline_bin operator = (const scanline_bin&); - - unsigned m_max_len; - int m_last_x; - int m_y; - span* m_spans; - span* m_cur_span; - }; - - - //------------------------------------------------------------------------ - inline void scanline_bin::reset(int min_x, int max_x) - { - unsigned max_len = max_x - min_x + 3; - if(max_len > m_max_len) - { - delete [] m_spans; - m_spans = new span [max_len]; - m_max_len = max_len; - } - m_last_x = 0x7FFF; - m_cur_span = m_spans; - } - - - //------------------------------------------------------------------------ - inline void scanline_bin::reset_spans() - { - m_last_x = 0x7FFF; - m_cur_span = m_spans; - } - - - //------------------------------------------------------------------------ - inline void scanline_bin::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; - } - - - //------------------------------------------------------------------------ - inline void scanline_bin::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; - } - - //------------------------------------------------------------------------ - inline void scanline_bin::add_cells(int x, unsigned len, const void*) - { - add_span(x, len, 0); - } -} - - -#endif diff --git a/agg2/include/agg_scanline_p.h b/agg2/include/agg_scanline_p.h deleted file mode 100644 index 811efbc..0000000 --- a/agg2/include/agg_scanline_p.h +++ /dev/null @@ -1,197 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// Class scanline_p - a general purpose scanline container with packed spans. -// -//---------------------------------------------------------------------------- -#ifndef AGG_SCANLINE_P_INCLUDED -#define AGG_SCANLINE_P_INCLUDED - -#include "agg_basics.h" - -namespace agg -{ - - //==============================================================scanline_p - // - // This is a general purpose scaline container which supports the interface - // used in the rasterizer::render(). See description of agg_scanline_u - // for details. - // - //------------------------------------------------------------------------ - template class scanline_p - { - public: - typedef T cover_type; - - struct span - { - int16 x; - int16 len; // If negative, it's a solid span, covers is valid - const T* covers; - }; - - typedef span* iterator; - typedef const span* const_iterator; - - ~scanline_p() - { - delete [] m_spans; - delete [] m_covers; - } - - scanline_p() : - m_max_len(0), - m_last_x(0x7FFFFFF0), - m_covers(0), - m_cover_ptr(0), - m_spans(0), - m_cur_span(0) - { - } - - void reset(int min_x, int max_x); - void add_cell(int x, unsigned cover); - void add_cells(int x, unsigned len, const T* covers); - void add_span(int x, unsigned len, unsigned cover); - void finalize(int y) { m_y = y; } - void reset_spans(); - - int y() const { return m_y; } - unsigned num_spans() const { return unsigned(m_cur_span - m_spans); } - const_iterator begin() const { return m_spans + 1; } - - private: - scanline_p(const scanline_p&); - const scanline_p& operator = (const scanline_p&); - - unsigned m_max_len; - int m_last_x; - int m_y; - T* m_covers; - T* m_cover_ptr; - span* m_spans; - span* m_cur_span; - }; - - - //------------------------------------------------------------------------ - template - void scanline_p::reset(int min_x, int max_x) - { - unsigned max_len = max_x - min_x + 3; - if(max_len > m_max_len) - { - delete [] m_spans; - delete [] m_covers; - m_covers = new T [max_len]; - m_spans = new span [max_len]; - m_max_len = max_len; - } - m_last_x = 0x7FFFFFF0; - m_cover_ptr = m_covers; - m_cur_span = m_spans; - m_cur_span->len = 0; - } - - - //------------------------------------------------------------------------ - template - void scanline_p::reset_spans() - { - m_last_x = 0x7FFFFFF0; - m_cover_ptr = m_covers; - m_cur_span = m_spans; - m_cur_span->len = 0; - } - - - //------------------------------------------------------------------------ - template - void scanline_p::add_cell(int x, unsigned cover) - { - *m_cover_ptr = (T)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++; - } - - - //------------------------------------------------------------------------ - template - void scanline_p::add_cells(int x, unsigned len, const T* covers) - { - memcpy(m_cover_ptr, covers, len * sizeof(T)); - 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; - } - - - //------------------------------------------------------------------------ - template - void scanline_p::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 = (T)cover; - m_cur_span++; - m_cur_span->covers = m_cover_ptr++; - m_cur_span->x = (int16)x; - m_cur_span->len = -((int16)len); - } - m_last_x = x + len - 1; - } - - - //=============================================================scanline_p8 - typedef scanline_p scanline_p8; - - //============================================================scanline_p16 - typedef scanline_p scanline_p16; - - //============================================================scanline_p32 - typedef scanline_p scanline_p32; -} - - -#endif - diff --git a/agg2/include/agg_scanline_u.h b/agg2/include/agg_scanline_u.h deleted file mode 100644 index 8dfb6e8..0000000 --- a/agg2/include/agg_scanline_u.h +++ /dev/null @@ -1,323 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_SCANLINE_U_INCLUDED -#define AGG_SCANLINE_U_INCLUDED - -#include -#include "agg_basics.h" - -namespace agg -{ - //==============================================================scanline_u - // - // Unpacked scanline container class - // - // This class is used to transfer data from a scanline rastyerizer - // 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 scaline 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) occures less frequently. - //------------------------------------------------------------------------ - template class scanline_u - { - public: - typedef T cover_type; - - //-------------------------------------------------------------------- - struct span - { - int16 x; - int16 len; - cover_type* covers; - }; - - typedef span* iterator; - typedef const span* const_iterator; - - //-------------------------------------------------------------------- - ~scanline_u(); - scanline_u(); - - void reset(int min_x, int max_x); - void add_cell(int x, unsigned cover); - void add_cells(int x, unsigned len, const T* covers); - void add_span(int x, unsigned len, unsigned cover); - void finalize(int y) { m_y = y; } - void reset_spans(); - - int y() const { return m_y; } - unsigned num_spans() const { return unsigned(m_cur_span - m_spans); } - const_iterator begin() const { return m_spans + 1; } - iterator begin() { return m_spans + 1; } - - private: - scanline_u(const scanline_u&); - const scanline_u& operator = (const scanline_u&); - - private: - int m_min_x; - unsigned m_max_len; - int m_last_x; - int m_y; - cover_type* m_covers; - span* m_spans; - span* m_cur_span; - }; - - - - //------------------------------------------------------------------------ - template scanline_u::~scanline_u() - { - delete [] m_spans; - delete [] m_covers; - } - - - //------------------------------------------------------------------------ - template scanline_u::scanline_u() : - m_min_x(0), - m_max_len(0), - m_last_x(0x7FFFFFF0), - m_covers(0), - m_spans(0), - m_cur_span(0) - { - } - - - //------------------------------------------------------------------------ - template void scanline_u::reset(int min_x, int max_x) - { - unsigned max_len = max_x - min_x + 2; - if(max_len > m_max_len) - { - delete [] m_spans; - delete [] m_covers; - m_covers = new cover_type [max_len]; - m_spans = new span [max_len]; - m_max_len = max_len; - } - m_last_x = 0x7FFFFFF0; - m_min_x = min_x; - m_cur_span = m_spans; - } - - - //------------------------------------------------------------------------ - template inline void scanline_u::reset_spans() - { - m_last_x = 0x7FFFFFF0; - m_cur_span = m_spans; - } - - - //------------------------------------------------------------------------ - template inline void scanline_u::add_cell(int x, unsigned cover) - { - x -= m_min_x; - m_covers[x] = (unsigned char)cover; - if(x == m_last_x+1) - { - m_cur_span->len++; - } - else - { - m_cur_span++; - m_cur_span->x = (int16)(x + m_min_x); - m_cur_span->len = 1; - m_cur_span->covers = m_covers + x; - } - m_last_x = x; - } - - - //------------------------------------------------------------------------ - template void scanline_u::add_cells(int x, unsigned len, const T* covers) - { - x -= m_min_x; - memcpy(m_covers + x, covers, len * sizeof(T)); - if(x == m_last_x+1) - { - m_cur_span->len += (int16)len; - } - else - { - m_cur_span++; - m_cur_span->x = (int16)(x + m_min_x); - m_cur_span->len = (int16)len; - m_cur_span->covers = m_covers + x; - } - m_last_x = x + len - 1; - } - - - //------------------------------------------------------------------------ - template void scanline_u::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 += (int16)len; - } - else - { - m_cur_span++; - m_cur_span->x = (int16)(x + m_min_x); - m_cur_span->len = (int16)len; - m_cur_span->covers = m_covers + x; - } - m_last_x = x + len - 1; - } - - - //=============================================================scanline_u8 - typedef scanline_u scanline_u8; - - //============================================================scanline_u16 - typedef scanline_u scanline_u16; - - //============================================================scanline_u32 - typedef scanline_u scanline_u32; - - - //=============================================================scanline_am - // - // The scanline container with alpha-masking - // - //------------------------------------------------------------------------ - template - class scanline_am : public scanline_u - { - public: - typedef AlphaMask alpha_mask_type; - typedef CoverT cover_type; - typedef scanline_u scanline_type; - - scanline_am() : scanline_type(), m_alpha_mask(0) {} - scanline_am(const AlphaMask& am) : scanline_type(), m_alpha_mask(&am) {} - - //-------------------------------------------------------------------- - void finalize(int span_y) - { - scanline_u::finalize(span_y); - if(m_alpha_mask) - { - typename scanline_type::iterator span = scanline_type::begin(); - unsigned count = scanline_type::num_spans(); - do - { - m_alpha_mask->combine_hspan(span->x, - scanline_type::y(), - span->covers, - span->len); - ++span; - } - while(--count); - } - } - - private: - const AlphaMask* m_alpha_mask; - }; - - - //==========================================================scanline_u8_am - template - class scanline_u8_am : public scanline_am - { - public: - typedef AlphaMask alpha_mask_type; - typedef int8u cover_type; - typedef scanline_am self_type; - - scanline_u8_am() : self_type() {} - scanline_u8_am(const AlphaMask& am) : self_type(am) {} - }; - -} - -#endif - diff --git a/agg2/include/agg_span_allocator.h b/agg2/include/agg_span_allocator.h deleted file mode 100644 index 863bb78..0000000 --- a/agg2/include/agg_span_allocator.h +++ /dev/null @@ -1,72 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_SPAN_ALLOCATOR_INCLUDED -#define AGG_SPAN_ALLOCATOR_INCLUDED - -#include "agg_basics.h" - -namespace agg -{ - //----------------------------------------------------------span_allocator - template class span_allocator - { - public: - typedef ColorT color_type; - - //-------------------------------------------------------------------- - ~span_allocator() - { - delete [] m_span; - } - - //-------------------------------------------------------------------- - span_allocator() : - m_max_span_len(0), - m_span(0) - { - } - - //-------------------------------------------------------------------- - color_type* allocate(unsigned max_span_len) - { - if(max_span_len > m_max_span_len) - { - delete [] m_span; - m_span = new color_type[m_max_span_len = max_span_len]; - } - return m_span; - } - - //-------------------------------------------------------------------- - color_type* span() - { - return m_span; - } - - private: - //-------------------------------------------------------------------- - span_allocator(const span_allocator&); - const span_allocator& operator = (const span_allocator&); - - unsigned m_max_span_len; - color_type* m_span; - }; -} - - -#endif - - diff --git a/agg2/include/agg_span_generator.h b/agg2/include/agg_span_generator.h deleted file mode 100644 index aa8fa46..0000000 --- a/agg2/include/agg_span_generator.h +++ /dev/null @@ -1,50 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_SPAN_GENERATOR_INCLUDED -#define AGG_SPAN_GENERATOR_INCLUDED - -#include "agg_basics.h" -#include "agg_span_allocator.h" - -namespace agg -{ - - //==========================================================span_generator - template class span_generator - { - public: - typedef ColorT color_type; - typedef Allocator alloc_type; - - //-------------------------------------------------------------------- - span_generator(alloc_type& alloc) : m_alloc(&alloc) {} - - //-------------------------------------------------------------------- - void allocator(alloc_type& alloc) { m_alloc = &alloc; } - alloc_type& allocator() { return *m_alloc; } - - //-------------------------------------------------------------------- - void prepare(unsigned max_span_len) - { - m_alloc->allocate(max_span_len); - } - - private: - alloc_type* m_alloc; - }; -} - -#endif diff --git a/agg2/include/agg_span_gouraud_gray8.h b/agg2/include/agg_span_gouraud_gray8.h deleted file mode 100644 index ab05826..0000000 --- a/agg2/include/agg_span_gouraud_gray8.h +++ /dev/null @@ -1,176 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_SPAN_GOURAUD_GRAY8_INCLUDED -#define AGG_SPAN_GOURAUD_GRAY8_INCLUDED - -#include "agg_basics.h" -#include "agg_gray8.h" -#include "agg_dda_line.h" -#include "agg_span_gouraud.h" - -namespace agg -{ - - //======================================================span_gouraud_gray8 - template > - class span_gouraud_gray8 : public span_gouraud - { - public: - typedef Allocator alloc_type; - typedef gray8 color_type; - typedef span_gouraud base_type; - typedef typename base_type::coord_type coord_type; - - private: - //-------------------------------------------------------------------- - struct gray_calc - { - void init(const coord_type& c1, const coord_type& c2) - { - m_x1 = c1.x; - m_y1 = c1.y; - m_dx = c2.x - c1.x; - m_dy = 1.0 / (c2.y - c1.y); - 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(int y) - { - double k = 0.0; - if(y > m_y1) k = (y - m_y1) * m_dy; - gray8 c; - m_v = m_v1 + int(m_dv * k); - m_a = m_a1 + int(m_da * k); - m_x = int(m_x1 + m_dx * k); - } - - double m_x1; - double m_y1; - double m_dx; - double m_dy; - int m_v1; - int m_a1; - int m_dv; - int m_da; - int m_v; - int m_a; - int m_x; - }; - - - public: - //-------------------------------------------------------------------- - span_gouraud_gray8(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_gouraud_gray8(alloc_type& alloc, - 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(alloc, c1, c2, c3, x1, y1, x2, y2, x3, y3, d) - {} - - //-------------------------------------------------------------------- - void prepare(unsigned max_span_len) - { - base_type::prepare(max_span_len); - - coord_type coord[3]; - arrange_vertices(coord); - - m_y2 = int(coord[1].y); - - m_swap = calc_point_location(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]); - } - - //-------------------------------------------------------------------- - color_type* generate(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) - { - m_c2.calc(y+1); - } - else - { - m_c3.calc(y); - pc2 = &m_c3; - } - - if(m_swap) - { - const gray_calc* t = pc2; - pc2 = pc1; - pc1 = t; - } - - int nx = pc1->m_x; - unsigned nlen = pc2->m_x - pc1->m_x + 1; - - if(nlen < len) nlen = len; - - dda_line_interpolator<16> v(pc1->m_v, pc2->m_v, nlen); - dda_line_interpolator<16> a(pc1->m_a, pc2->m_a, nlen); - - if(nx < x) - { - unsigned d = unsigned(x - nx); - v += d; - a += d; - } - - color_type* span = base_type::allocator().span(); - do - { - span->v = v.y(); - span->a = a.y(); - ++v; - ++a; - ++span; - } - while(--len); - return base_type::allocator().span(); - } - - - private: - bool m_swap; - int m_y2; - gray_calc m_c1; - gray_calc m_c2; - gray_calc m_c3; - }; - - -} - -#endif diff --git a/agg2/include/agg_span_gouraud_rgba8.h b/agg2/include/agg_span_gouraud_rgba8.h deleted file mode 100644 index ed23892..0000000 --- a/agg2/include/agg_span_gouraud_rgba8.h +++ /dev/null @@ -1,197 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_SPAN_GOURAUD_RGBA8_INCLUDED -#define AGG_SPAN_GOURAUD_RGBA8_INCLUDED - -#include "agg_basics.h" -#include "agg_color_rgba8.h" -#include "agg_dda_line.h" -#include "agg_span_gouraud.h" - -namespace agg -{ - - //======================================================span_gouraud_rgba8 - template > - class span_gouraud_rgba8 : public span_gouraud - { - public: - typedef Allocator alloc_type; - typedef rgba8 color_type; - typedef span_gouraud base_type; - typedef typename base_type::coord_type coord_type; - - private: - //-------------------------------------------------------------------- - struct rgba_calc - { - void init(const coord_type& c1, const coord_type& c2) - { - m_x1 = c1.x; - m_y1 = c1.y; - m_dx = c2.x - c1.x; - m_dy = 1.0 / (c2.y - c1.y); - m_r1 = c1.color.r; - m_g1 = c1.color.g; - m_b1 = c1.color.b; - m_a1 = c1.color.a; - m_dr = c2.color.r - m_r1; - m_dg = c2.color.g - m_g1; - m_db = c2.color.b - m_b1; - m_da = c2.color.a - m_a1; - } - - void calc(int y) - { - double k = 0.0; - if(y > m_y1) k = (y - m_y1) * m_dy; - rgba8 rgba; - m_r = m_r1 + int(m_dr * k); - m_g = m_g1 + int(m_dg * k); - m_b = m_b1 + int(m_db * k); - m_a = m_a1 + int(m_da * k); - m_x = int(m_x1 + m_dx * k); - } - - double m_x1; - double m_y1; - double m_dx; - double m_dy; - int m_r1; - int m_g1; - int m_b1; - int m_a1; - int m_dr; - int m_dg; - int m_db; - int m_da; - int m_r; - int m_g; - int m_b; - int m_a; - int m_x; - }; - - public: - - //-------------------------------------------------------------------- - span_gouraud_rgba8(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_gouraud_rgba8(alloc_type& alloc, - 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(alloc, c1, c2, c3, x1, y1, x2, y2, x3, y3, d) - {} - - //-------------------------------------------------------------------- - void prepare(unsigned max_span_len) - { - base_type::prepare(max_span_len); - - coord_type coord[3]; - arrange_vertices(coord); - - m_y2 = int(coord[1].y); - - m_swap = calc_point_location(coord[0].x, coord[0].y, - coord[2].x, coord[2].y, - coord[1].x, coord[1].y) < 0.0; - - m_rgba1.init(coord[0], coord[2]); - m_rgba2.init(coord[0], coord[1]); - m_rgba3.init(coord[1], coord[2]); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - m_rgba1.calc(y); - const rgba_calc* pc1 = &m_rgba1; - const rgba_calc* pc2 = &m_rgba2; - - if(y < m_y2) - { - m_rgba2.calc(y+1); - } - else - { - m_rgba3.calc(y); - pc2 = &m_rgba3; - } - - if(m_swap) - { - const rgba_calc* t = pc2; - pc2 = pc1; - pc1 = t; - } - - int nx = pc1->m_x; - unsigned nlen = pc2->m_x - pc1->m_x + 1; - - if(nlen < len) nlen = len; - - dda_line_interpolator<16> r(pc1->m_r, pc2->m_r, nlen); - dda_line_interpolator<16> g(pc1->m_g, pc2->m_g, nlen); - dda_line_interpolator<16> b(pc1->m_b, pc2->m_b, nlen); - dda_line_interpolator<16> a(pc1->m_a, pc2->m_a, nlen); - - if(nx < x) - { - unsigned d = unsigned(x - nx); - r += d; - g += d; - b += d; - a += d; - } - - color_type* span = base_type::allocator().span(); - do - { - span->r = (int8u)r.y(); - span->g = (int8u)g.y(); - span->b = (int8u)b.y(); - span->a = (int8u)a.y(); - ++r; - ++g; - ++b; - ++a; - ++span; - } - while(--len); - return base_type::allocator().span(); - } - - - private: - bool m_swap; - int m_y2; - rgba_calc m_rgba1; - rgba_calc m_rgba2; - rgba_calc m_rgba3; - }; - - - -} - -#endif diff --git a/agg2/include/agg_span_gouraud_rgba8_gamma.h b/agg2/include/agg_span_gouraud_rgba8_gamma.h deleted file mode 100644 index dc4e0d2..0000000 --- a/agg2/include/agg_span_gouraud_rgba8_gamma.h +++ /dev/null @@ -1,207 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_SPAN_GOURAUD_RGBA8_GAMMA_INCLUDED -#define AGG_SPAN_GOURAUD_RGBA8_GAMMA_INCLUDED - -#include "agg_basics.h" -#include "agg_color_rgba8.h" -#include "agg_dda_line.h" -#include "agg_span_gouraud.h" -#include "agg_gamma_lut.h" - -namespace agg -{ - - //======================================================span_gouraud_rgba8 - template, - class Gamma = gamma_lut > - class span_gouraud_rgba8_gamma : public span_gouraud - { - public: - typedef Allocator alloc_type; - typedef rgba8 color_type; - typedef span_gouraud base_type; - typedef typename base_type::coord_type coord_type; - typedef Gamma gamma_type; - - private: - //-------------------------------------------------------------------- - struct rgba_calc - { - void init(const coord_type& c1, const coord_type& c2, const gamma_type& gamma) - { - m_x1 = c1.x; - m_y1 = c1.y; - m_dx = c2.x - c1.x; - m_dy = 1.0 / (c2.y - c1.y); - m_r1 = gamma.dir(c1.color.r); - m_g1 = gamma.dir(c1.color.g); - m_b1 = gamma.dir(c1.color.b); - m_a1 = c1.color.a; - m_dr = gamma.dir(c2.color.r) - m_r1; - m_dg = gamma.dir(c2.color.g) - m_g1; - m_db = gamma.dir(c2.color.b) - m_b1; - m_da = c2.color.a - m_a1; - } - - void calc(int y) - { - double k = 0.0; - if(y > m_y1) k = (y - m_y1) * m_dy; - m_r = m_r1 + int(m_dr * k); - m_g = m_g1 + int(m_dg * k); - m_b = m_b1 + int(m_db * k); - m_a = m_a1 + int(m_da * k); - m_x = int(m_x1 + m_dx * k); - } - - double m_x1; - double m_y1; - double m_dx; - double m_dy; - int m_r1; - int m_g1; - int m_b1; - int m_a1; - int m_dr; - int m_dg; - int m_db; - int m_da; - int m_r; - int m_g; - int m_b; - int m_a; - int m_x; - }; - - public: - - //-------------------------------------------------------------------- - span_gouraud_rgba8_gamma(alloc_type& alloc, const gamma_type& g) : - base_type(alloc), m_gamma(&g) {} - - //-------------------------------------------------------------------- - span_gouraud_rgba8_gamma(alloc_type& alloc, - const gamma_type& g, - 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(alloc, c1, c2, c3, x1, y1, x2, y2, x3, y3, d), - m_gamma(&g) - {} - - //-------------------------------------------------------------------- - void gamma(const gamma_type& g) { m_gamma = &g; } - const gamma_type& gamma() const { return *m_gamma; } - - //-------------------------------------------------------------------- - void prepare(unsigned max_span_len) - { - base_type::prepare(max_span_len); - - coord_type coord[3]; - arrange_vertices(coord); - - m_y2 = int(coord[1].y); - - m_swap = calc_point_location(coord[0].x, coord[0].y, - coord[2].x, coord[2].y, - coord[1].x, coord[1].y) < 0.0; - - m_rgba1.init(coord[0], coord[2], *m_gamma); - m_rgba2.init(coord[0], coord[1], *m_gamma); - m_rgba3.init(coord[1], coord[2], *m_gamma); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - m_rgba1.calc(y); - const rgba_calc* pc1 = &m_rgba1; - const rgba_calc* pc2 = &m_rgba2; - - if(y < m_y2) - { - m_rgba2.calc(y+1); - } - else - { - m_rgba3.calc(y); - pc2 = &m_rgba3; - } - - if(m_swap) - { - const rgba_calc* t = pc2; - pc2 = pc1; - pc1 = t; - } - - int nx = pc1->m_x; - unsigned nlen = pc2->m_x - pc1->m_x + 1; - - if(nlen < len) nlen = len; - - dda_line_interpolator<8> r(pc1->m_r, pc2->m_r, nlen); - dda_line_interpolator<8> g(pc1->m_g, pc2->m_g, nlen); - dda_line_interpolator<8> b(pc1->m_b, pc2->m_b, nlen); - dda_line_interpolator<16> a(pc1->m_a, pc2->m_a, nlen); - - if(nx < x) - { - unsigned d = unsigned(x - nx); - r += d; - g += d; - b += d; - a += d; - } - - color_type* span = base_type::allocator().span(); - do - { - span->r = m_gamma->inv(r.y()); - span->g = m_gamma->inv(g.y()); - span->b = m_gamma->inv(b.y()); - span->a = a.y(); - ++r; - ++g; - ++b; - ++a; - ++span; - } - while(--len); - return base_type::allocator().span(); - } - - - private: - const gamma_type* m_gamma; - bool m_swap; - int m_y2; - rgba_calc m_rgba1; - rgba_calc m_rgba2; - rgba_calc m_rgba3; - }; - - - -} - -#endif diff --git a/agg2/include/agg_span_gradient.h b/agg2/include/agg_span_gradient.h deleted file mode 100644 index be54477..0000000 --- a/agg2/include/agg_span_gradient.h +++ /dev/null @@ -1,231 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_SPAN_GRADIENT_INCLUDED -#define AGG_SPAN_GRADIENT_INCLUDED - -#include -#include -#include "agg_basics.h" -#include "agg_span_generator.h" -#include "agg_math.h" - - -namespace agg -{ - - //==========================================================span_gradient - template > - class span_gradient : public span_generator - { - public: - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef ColorT color_type; - typedef span_generator base_type; - - enum - { - base_shift = 8, - base_size = 1 << base_shift, - base_mask = base_size - 1, - - gradient_shift = 4, - gradient_size = 1 << gradient_shift, - gradient_mask = gradient_size - 1, - - downscale_shift = interpolator_type::subpixel_shift - gradient_shift - }; - - - //-------------------------------------------------------------------- - span_gradient(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_gradient(alloc_type& alloc, - interpolator_type& inter, - const GradientF& gradient_function, - ColorF color_function, - double d1, double d2) : - base_type(alloc), - m_interpolator(&inter), - m_gradient_function(&gradient_function), - m_color_function(color_function), - m_d1(int(d1 * gradient_size)), - m_d2(int(d2 * gradient_size)) - {} - - //-------------------------------------------------------------------- - interpolator_type& interpolator() { return *m_interpolator; } - const GradientF& gradient_function() const { return *m_gradient_function; } - const ColorF color_function() const { return m_color_function; } - double d1() const { return double(m_d1) / gradient_size; } - double d2() const { return double(m_d2) / gradient_size; } - - //-------------------------------------------------------------------- - void interpolator(interpolator_type& i) { m_interpolator = &i; } - void gradient_function(const GradientF& gf) { m_gradient_function = &gf; } - void color_function(ColorF cf) { m_color_function = cf; } - void d1(double v) { m_d1 = int(v * gradient_size); } - void d2(double v) { m_d2 = int(v * gradient_size); } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - color_type* span = base_type::allocator().span(); - int dd = m_d2 - m_d1; - if(dd < 1) dd = 1; - m_interpolator->begin(x+0.5, y+0.5, len); - do - { - m_interpolator->coordinates(&x, &y); - int d = m_gradient_function->calculate(x >> downscale_shift, - y >> downscale_shift, dd); - d = ((d - m_d1) << base_shift) / dd; - if(d < 0) d = 0; - if(d > base_mask) d = base_mask; - *span++ = m_color_function[d]; - ++(*m_interpolator); - } - while(--len); - return base_type::allocator().span(); - } - - private: - interpolator_type* m_interpolator; - const GradientF* m_gradient_function; - ColorF m_color_function; - int m_d1; - int m_d2; - }; - - - - - //=====================================================gradient_linear_color - template - struct gradient_linear_color - { - typedef ColorT color_type; - enum - { - base_shift = BaseShift, - base_size = 1 << base_shift, - base_mask = base_size - 1 - }; - - gradient_linear_color() {} - gradient_linear_color(const color_type& c1, const color_type& c2) : - m_c1(c1), m_c2(c2) {} - - color_type operator [] (unsigned v) const - { - return m_c1.gradient(m_c2, double(v) / double(base_mask)); - } - - void colors(const color_type& c1, const color_type& c2) - { - m_c1 = c1; - m_c2 = c2; - } - - color_type m_c1; - color_type m_c2; - }; - - - - //---------------------------------------------------------gradient_circle - class gradient_circle - { - public: - static int calculate(int x, int y, int) - { - return int(fast_sqrt(x*x + y*y)); - } - }; - - - //--------------------------------------------------------------gradient_x - class gradient_x - { - public: - static int calculate(int x, int, int) { return x; } - }; - - - //--------------------------------------------------------------gradient_y - class gradient_y - { - public: - static int calculate(int, int y, int) { return y; } - }; - - - //--------------------------------------------------------gradient_diamond - class gradient_diamond - { - public: - static int calculate(int x, int y, int) - { - int ax = abs(x); - int ay = abs(y); - return ax > ay ? ax : ay; - } - }; - - - //-------------------------------------------------------------gradient_xy - class gradient_xy - { - public: - static int calculate(int x, int y, int d) - { - return abs(x) * abs(y) / d; - } - }; - - - //--------------------------------------------------------gradient_sqrt_xy - class gradient_sqrt_xy - { - public: - static int calculate(int x, int y, int) - { - return fast_sqrt(abs(x) * abs(y)); - } - }; - - - //----------------------------------------------------------gradient_conic - class gradient_conic - { - public: - static int calculate(int x, int y, int d) - { - return int(fabs(atan2(double(y), double(x))) * double(d) / pi); - } - }; - - - - -} - -#endif diff --git a/agg2/include/agg_span_image_filter.h b/agg2/include/agg_span_image_filter.h deleted file mode 100644 index a8af950..0000000 --- a/agg2/include/agg_span_image_filter.h +++ /dev/null @@ -1,83 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// Image transformations with filtering. Span generator base class -// -//---------------------------------------------------------------------------- -#ifndef AGG_SPAN_IMAGE_FILTER_INCLUDED -#define AGG_SPAN_IMAGE_FILTER_INCLUDED - -#include "agg_basics.h" -#include "agg_image_filters.h" -#include "agg_rendering_buffer.h" -#include "agg_span_generator.h" - - -namespace agg -{ - - //--------------------------------------------------span_image_filter - template - class span_image_filter : public span_generator - { - public: - typedef ColorT color_type; - typedef Allocator alloc_type; - typedef Interpolator interpolator_type; - - //---------------------------------------------------------------- - span_image_filter(alloc_type& alloc) : - span_generator(alloc) - {} - - //---------------------------------------------------------------- - span_image_filter(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& interpolator, - const image_filter_base* filter) : - span_generator(alloc), - m_src(&src), - m_back_color(back_color), - m_interpolator(&interpolator), - m_filter(filter) - {} - - //---------------------------------------------------------------- - const rendering_buffer& source_image() const { return *m_src; } - const color_type& background_color() const { return m_back_color; } - const image_filter_base& filter() const { return *m_filter; } - - //---------------------------------------------------------------- - void source_image(const rendering_buffer& v) { m_src = &v; } - void background_color(const color_type& v) { m_back_color = v; } - void interpolator(interpolator_type& v) { m_interpolator = &v; } - void filter(const image_filter_base& v) { m_filter = &v; } - - //---------------------------------------------------------------- - interpolator_type& interpolator() { return *m_interpolator; } - - //---------------------------------------------------------------- - private: - const rendering_buffer* m_src; - color_type m_back_color; - interpolator_type* m_interpolator; - const image_filter_base* m_filter; - }; - - -} - -#endif diff --git a/agg2/include/agg_span_image_filter_rgb24.h b/agg2/include/agg_span_image_filter_rgb24.h deleted file mode 100644 index 7dd7344..0000000 --- a/agg2/include/agg_span_image_filter_rgb24.h +++ /dev/null @@ -1,531 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_SPAN_IMAGE_FILTER_RGB24_INCLUDED -#define AGG_SPAN_IMAGE_FILTER_RGB24_INCLUDED - -#include "agg_basics.h" -#include "agg_color_rgba8.h" -#include "agg_span_image_filter.h" - - -namespace agg -{ - - - //==============================================span_image_filter_rgb24_nn - template > - class span_image_filter_rgb24_nn : - public span_image_filter - { - public: - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter base_type; - typedef rgba8 color_type; - - //-------------------------------------------------------------------- - span_image_filter_rgb24_nn(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_filter_rgb24_nn(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter) : - base_type(alloc, src, back_color, inter, 0) - {} - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - base_type::interpolator().begin(x, y, len); - - int fg[3]; - int src_alpha; - - const unsigned char *fg_ptr; - color_type* span = base_type::allocator().span(); - - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - - do - { - base_type::interpolator().coordinates(&x, &y); - - x >>= image_subpixel_shift; - y >>= image_subpixel_shift; - - if(x >= 0 && y >= 0 && - x <= maxx && y <= maxy) - { - fg_ptr = base_type::source_image().row(y) + x + x + x; - fg[0] = *fg_ptr++; - fg[1] = *fg_ptr++; - fg[2] = *fg_ptr++; - src_alpha = 255; - } - else - { - fg[Order::R] = base_type::background_color().r; - fg[Order::G] = base_type::background_color().g; - fg[Order::B] = base_type::background_color().b; - src_alpha = base_type::background_color().a; - } - - span->r = (int8u)fg[Order::R]; - span->g = (int8u)fg[Order::G]; - span->b = (int8u)fg[Order::B]; - span->a = (int8u)src_alpha; - ++span; - ++base_type::interpolator(); - - } while(--len); - - return base_type::allocator().span(); - } - }; - - - - - //=========================================span_image_filter_rgb24_bilinear - template > - class span_image_filter_rgb24_bilinear : - public span_image_filter - { - public: - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter base_type; - typedef rgba8 color_type; - - //-------------------------------------------------------------------- - span_image_filter_rgb24_bilinear(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_filter_rgb24_bilinear(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter) : - base_type(alloc, src, back_color, inter, 0) - {} - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - base_type::interpolator().begin(x, y, len); - - int fg[3]; - int src_alpha; - int back_r = base_type::background_color().r; - int back_g = base_type::background_color().g; - int back_b = base_type::background_color().b; - int back_a = base_type::background_color().a; - - const unsigned char *fg_ptr; - - int stride = base_type::source_image().stride() - 2 * 3; - color_type* span = base_type::allocator().span(); - - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - - do - { - int x_hr; - int y_hr; - - base_type::interpolator().coordinates(&x_hr, &y_hr); - - int x_lr = x_hr >> image_subpixel_shift; - int y_lr = y_hr >> image_subpixel_shift; - int weight; - - if(x_lr >= 0 && y_lr >= 0 && - x_lr < maxx && y_lr < maxy) - { - fg[0] = - fg[1] = - fg[2] = image_subpixel_size * image_subpixel_size / 2; - - x_hr &= image_subpixel_mask; - y_hr &= image_subpixel_mask; - fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; - - weight = (image_subpixel_size - x_hr) * - (image_subpixel_size - y_hr); - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - - weight = x_hr * (image_subpixel_size - y_hr); - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - - fg_ptr += stride; - - weight = (image_subpixel_size - x_hr) * y_hr; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - - weight = x_hr * y_hr; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - - fg[0] >>= image_subpixel_shift * 2; - fg[1] >>= image_subpixel_shift * 2; - fg[2] >>= image_subpixel_shift * 2; - src_alpha = 255; - } - else - { - if(x_lr < -1 || y_lr < -1 || - x_lr > maxx || y_lr > maxy) - { - fg[Order::R] = back_r; - fg[Order::G] = back_g; - fg[Order::B] = back_b; - src_alpha = back_a; - } - else - { - fg[0] = - fg[1] = - fg[2] = - src_alpha = image_subpixel_size * image_subpixel_size / 2; - - x_hr &= image_subpixel_mask; - y_hr &= image_subpixel_mask; - - weight = (image_subpixel_size - x_hr) * - (image_subpixel_size - y_hr); - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - src_alpha += weight * 255; - } - else - { - fg[Order::R] += back_r * weight; - fg[Order::G] += back_g * weight; - fg[Order::B] += back_b * weight; - src_alpha += back_a * weight; - } - - x_lr++; - - weight = x_hr * (image_subpixel_size - y_hr); - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - src_alpha += weight * 255; - } - else - { - fg[Order::R] += back_r * weight; - fg[Order::G] += back_g * weight; - fg[Order::B] += back_b * weight; - src_alpha += back_a * weight; - } - - x_lr--; - y_lr++; - - weight = (image_subpixel_size - x_hr) * y_hr; - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - src_alpha += weight * 255; - } - else - { - fg[Order::R] += back_r * weight; - fg[Order::G] += back_g * weight; - fg[Order::B] += back_b * weight; - src_alpha += back_a * weight; - } - - x_lr++; - - weight = x_hr * y_hr; - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - src_alpha += weight * 255; - } - else - { - fg[Order::R] += back_r * weight; - fg[Order::G] += back_g * weight; - fg[Order::B] += back_b * weight; - src_alpha += back_a * weight; - } - - fg[0] >>= image_subpixel_shift * 2; - fg[1] >>= image_subpixel_shift * 2; - fg[2] >>= image_subpixel_shift * 2; - src_alpha >>= image_subpixel_shift * 2; - } - } - - span->r = (int8u)fg[Order::R]; - span->g = (int8u)fg[Order::G]; - span->b = (int8u)fg[Order::B]; - span->a = (int8u)src_alpha; - ++span; - ++base_type::interpolator(); - - } while(--len); - - return base_type::allocator().span(); - } - }; - - - - - - //=================================================span_image_filter_rgb24 - template > - class span_image_filter_rgb24 : - public span_image_filter - { - public: - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter base_type; - typedef rgba8 color_type; - - //-------------------------------------------------------------------- - span_image_filter_rgb24(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_filter_rgb24(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter, - const image_filter_base& filter) : - base_type(alloc, src, back_color, inter, &filter) - {} - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - base_type::interpolator().begin(x, y, len); - - int fg[3]; - int src_alpha; - int back_r = base_type::background_color().r; - int back_g = base_type::background_color().g; - int back_b = base_type::background_color().b; - int back_a = base_type::background_color().a; - - const unsigned char *fg_ptr; - - unsigned dimension = base_type::filter().dimension(); - int start = base_type::filter().start(); - int start1 = start - 1; - const int* weight_array = base_type::filter().weight_array_int(); - - int stride = base_type::source_image().stride() - dimension * 3; - color_type* span = base_type::allocator().span(); - - int maxx = base_type::source_image().width() + start - 2; - int maxy = base_type::source_image().height() + start - 2; - - int maxx2 = base_type::source_image().width() - start - 1; - int maxy2 = base_type::source_image().height() - start - 1; - - int x_count; - int weight_y; - - do - { - base_type::interpolator().coordinates(&x, &y); - - int x_hr = x; - int y_hr = y; - - int x_lr = x_hr >> image_subpixel_shift; - int y_lr = y_hr >> image_subpixel_shift; - - fg[0] = fg[1] = fg[2] = image_filter_size / 2; - - int x_fract = x_hr & image_subpixel_mask; - unsigned y_count = dimension; - - if(x_lr >= -start && y_lr >= -start && - x_lr <= maxx && y_lr <= maxy) - { - y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); - fg_ptr = base_type::source_image().row(y_lr + start) + (x_lr + start) * 3; - do - { - x_count = dimension; - weight_y = weight_array[y_hr]; - x_hr = image_subpixel_mask - x_fract; - - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - image_filter_shift; - - fg[0] += *fg_ptr++ * weight; - fg[1] += *fg_ptr++ * weight; - fg[2] += *fg_ptr++ * weight; - - x_hr += image_subpixel_size; - - } while(--x_count); - - y_hr += image_subpixel_size; - fg_ptr += stride; - - } while(--y_count); - - fg[0] >>= image_filter_shift; - fg[1] >>= image_filter_shift; - fg[2] >>= image_filter_shift; - - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - - if(fg[0] > 255) fg[0] = 255; - if(fg[1] > 255) fg[1] = 255; - if(fg[2] > 255) fg[2] = 255; - src_alpha = 255; - } - else - { - if(x_lr < start1 || y_lr < start1 || - x_lr > maxx2 || y_lr > maxy2) - { - fg[Order::R] = back_r; - fg[Order::G] = back_g; - fg[Order::B] = back_b; - src_alpha = back_a; - } - else - { - src_alpha = image_filter_size / 2; - y_lr = (y >> image_subpixel_shift) + start; - y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); - - do - { - x_count = dimension; - weight_y = weight_array[y_hr]; - x_lr = (x >> image_subpixel_shift) + start; - x_hr = image_subpixel_mask - x_fract; - - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - image_filter_shift; - - if(x_lr >= 0 && y_lr >= 0 && - x_lr < int(base_type::source_image().width()) && - y_lr < int(base_type::source_image().height())) - { - fg_ptr = base_type::source_image().row(y_lr) + x_lr * 3; - fg[0] += *fg_ptr++ * weight; - fg[1] += *fg_ptr++ * weight; - fg[2] += *fg_ptr++ * weight; - src_alpha += 255 * weight; - } - else - { - fg[Order::R] += back_r * weight; - fg[Order::G] += back_g * weight; - fg[Order::B] += back_b * weight; - src_alpha += back_a * weight; - } - x_hr += image_subpixel_size; - x_lr++; - - } while(--x_count); - - y_hr += image_subpixel_size; - y_lr++; - - } while(--y_count); - - - fg[0] >>= image_filter_shift; - fg[1] >>= image_filter_shift; - fg[2] >>= image_filter_shift; - src_alpha >>= image_filter_shift; - - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - if(src_alpha < 0) src_alpha = 0; - - if(fg[0] > 255) fg[0] = 255; - if(fg[1] > 255) fg[1] = 255; - if(fg[2] > 255) fg[2] = 255; - if(src_alpha > 255) src_alpha = 255; - } - } - - span->r = (int8u)fg[Order::R]; - span->g = (int8u)fg[Order::G]; - span->b = (int8u)fg[Order::B]; - span->a = (int8u)src_alpha; - ++span; - ++base_type::interpolator(); - - } while(--len); - - return base_type::allocator().span(); - } - }; - -} - - -#endif - - - diff --git a/agg2/include/agg_span_image_filter_rgb24_gamma.h b/agg2/include/agg_span_image_filter_rgb24_gamma.h deleted file mode 100644 index 4fc746d..0000000 --- a/agg2/include/agg_span_image_filter_rgb24_gamma.h +++ /dev/null @@ -1,475 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_SPAN_IMAGE_FILTER_RGB24_GAMMA_INCLUDED -#define AGG_SPAN_IMAGE_FILTER_RGB24_GAMMA_INCLUDED - -#include "agg_basics.h" -#include "agg_color_rgba8.h" -#include "agg_span_image_filter.h" -#include "agg_gamma_lut.h" - - -namespace agg -{ - - - //===================================span_image_filter_rgb24_gamma_bilinear - template, - class Gamma = gamma_lut > - class span_image_filter_rgb24_gamma_bilinear : - public span_image_filter - { - public: - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter base_type; - typedef rgba8 color_type; - typedef Gamma gamma_type; - - //-------------------------------------------------------------------- - span_image_filter_rgb24_gamma_bilinear(alloc_type& alloc, - const gamma_type& g) : - base_type(alloc), - m_gamma(&g) - {} - - //-------------------------------------------------------------------- - span_image_filter_rgb24_gamma_bilinear(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter, - const gamma_type& g) : - base_type(alloc, src, back_color, inter, 0), - m_gamma(&g) - {} - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - base_type::interpolator().begin(x, y, len); - - int fg[3]; - int src_alpha; - int back_r = m_gamma->dir(base_type::background_color().r); - int back_g = m_gamma->dir(base_type::background_color().g); - int back_b = m_gamma->dir(base_type::background_color().b); - int back_a = base_type::background_color().a; - - const unsigned char *fg_ptr; - - int stride = base_type::source_image().stride() - 2 * 3; - color_type* span = base_type::allocator().span(); - - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - - do - { - int x_hr; - int y_hr; - - base_type::interpolator().coordinates(&x_hr, &y_hr); - - int x_lr = x_hr >> image_subpixel_shift; - int y_lr = y_hr >> image_subpixel_shift; - int weight; - - if(x_lr >= 0 && y_lr >= 0 && - x_lr < maxx && y_lr < maxy) - { - fg[0] = - fg[1] = - fg[2] = image_subpixel_size * image_subpixel_size / 2; - - x_hr &= image_subpixel_mask; - y_hr &= image_subpixel_mask; - fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; - - weight = (image_subpixel_size - x_hr) * - (image_subpixel_size - y_hr); - fg[0] += weight * m_gamma->dir(*fg_ptr++); - fg[1] += weight * m_gamma->dir(*fg_ptr++); - fg[2] += weight * m_gamma->dir(*fg_ptr++); - - weight = x_hr * (image_subpixel_size - y_hr); - fg[0] += weight * m_gamma->dir(*fg_ptr++); - fg[1] += weight * m_gamma->dir(*fg_ptr++); - fg[2] += weight * m_gamma->dir(*fg_ptr++); - - fg_ptr += stride; - - weight = (image_subpixel_size - x_hr) * y_hr; - fg[0] += weight * m_gamma->dir(*fg_ptr++); - fg[1] += weight * m_gamma->dir(*fg_ptr++); - fg[2] += weight * m_gamma->dir(*fg_ptr++); - - weight = x_hr * y_hr; - fg[0] += weight * m_gamma->dir(*fg_ptr++); - fg[1] += weight * m_gamma->dir(*fg_ptr++); - fg[2] += weight * m_gamma->dir(*fg_ptr++); - - fg[0] >>= image_subpixel_shift * 2; - fg[1] >>= image_subpixel_shift * 2; - fg[2] >>= image_subpixel_shift * 2; - src_alpha = 255; - } - else - { - if(x_lr < -1 || y_lr < -1 || - x_lr > maxx || y_lr > maxy) - { - fg[Order::R] = back_r; - fg[Order::G] = back_g; - fg[Order::B] = back_b; - src_alpha = back_a; - } - else - { - fg[0] = - fg[1] = - fg[2] = - src_alpha = image_subpixel_size * image_subpixel_size / 2; - - x_hr &= image_subpixel_mask; - y_hr &= image_subpixel_mask; - - weight = (image_subpixel_size - x_hr) * - (image_subpixel_size - y_hr); - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; - fg[0] += weight * m_gamma->dir(*fg_ptr++); - fg[1] += weight * m_gamma->dir(*fg_ptr++); - fg[2] += weight * m_gamma->dir(*fg_ptr++); - src_alpha += weight * 255; - } - else - { - fg[Order::R] += back_r * weight; - fg[Order::G] += back_g * weight; - fg[Order::B] += back_b * weight; - src_alpha += back_a * weight; - } - - x_lr++; - - weight = x_hr * (image_subpixel_size - y_hr); - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; - fg[0] += weight * m_gamma->dir(*fg_ptr++); - fg[1] += weight * m_gamma->dir(*fg_ptr++); - fg[2] += weight * m_gamma->dir(*fg_ptr++); - src_alpha += weight * 255; - } - else - { - fg[Order::R] += back_r * weight; - fg[Order::G] += back_g * weight; - fg[Order::B] += back_b * weight; - src_alpha += back_a * weight; - } - - x_lr--; - y_lr++; - - weight = (image_subpixel_size - x_hr) * y_hr; - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; - fg[0] += weight * m_gamma->dir(*fg_ptr++); - fg[1] += weight * m_gamma->dir(*fg_ptr++); - fg[2] += weight * m_gamma->dir(*fg_ptr++); - src_alpha += weight * 255; - } - else - { - fg[Order::R] += back_r * weight; - fg[Order::G] += back_g * weight; - fg[Order::B] += back_b * weight; - src_alpha += back_a * weight; - } - - x_lr++; - - weight = x_hr * y_hr; - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; - fg[0] += weight * m_gamma->dir(*fg_ptr++); - fg[1] += weight * m_gamma->dir(*fg_ptr++); - fg[2] += weight * m_gamma->dir(*fg_ptr++); - src_alpha += weight * 255; - } - else - { - fg[Order::R] += back_r * weight; - fg[Order::G] += back_g * weight; - fg[Order::B] += back_b * weight; - src_alpha += back_a * weight; - } - - fg[0] >>= image_subpixel_shift * 2; - fg[1] >>= image_subpixel_shift * 2; - fg[2] >>= image_subpixel_shift * 2; - src_alpha >>= image_subpixel_shift * 2; - } - } - - span->r = (int8u)m_gamma->inv(fg[Order::R]); - span->g = (int8u)m_gamma->inv(fg[Order::G]); - span->b = (int8u)m_gamma->inv(fg[Order::B]); - span->a = (int8u)src_alpha; - ++span; - ++base_type::interpolator(); - - } while(--len); - - return base_type::allocator().span(); - } - - private: - const gamma_type* m_gamma; - }; - - - - - - //============================================span_image_filter_rgb24_gamma - template, - class Gamma = gamma_lut > - class span_image_filter_rgb24_gamma : - public span_image_filter - { - public: - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter base_type; - typedef rgba8 color_type; - typedef Gamma gamma_type; - - //-------------------------------------------------------------------- - span_image_filter_rgb24_gamma(alloc_type& alloc, const gamma_type& g) : - base_type(alloc), - m_gamma(&g) - {} - - //-------------------------------------------------------------------- - span_image_filter_rgb24_gamma(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter, - const image_filter_base& filter, - const gamma_type& g) : - base_type(alloc, src, back_color, inter, &filter), - m_gamma(&g) - {} - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - base_type::interpolator().begin(x, y, len); - - int fg[3]; - int src_alpha; - int back_r = m_gamma->dir(base_type::background_color().r); - int back_g = m_gamma->dir(base_type::background_color().g); - int back_b = m_gamma->dir(base_type::background_color().b); - int back_a = base_type::background_color().a; - - const unsigned char *fg_ptr; - - unsigned dimension = base_type::filter().dimension(); - int start = base_type::filter().start(); - int start1 = start - 1; - const int* weight_array = base_type::filter().weight_array_int(); - - int stride = base_type::source_image().stride() - dimension * 3; - color_type* span = base_type::allocator().span(); - - int maxx = base_type::source_image().width() + start - 2; - int maxy = base_type::source_image().height() + start - 2; - - int maxx2 = base_type::source_image().width() - start - 1; - int maxy2 = base_type::source_image().height() - start - 1; - - int x_count; - int weight_y; - - do - { - base_type::interpolator().coordinates(&x, &y); - - int x_hr = x; - int y_hr = y; - - int x_lr = x_hr >> image_subpixel_shift; - int y_lr = y_hr >> image_subpixel_shift; - - fg[0] = fg[1] = fg[2] = image_filter_size / 2; - - int x_fract = x_hr & image_subpixel_mask; - unsigned y_count = dimension; - - if(x_lr >= -start && y_lr >= -start && - x_lr <= maxx && y_lr <= maxy) - { - y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); - fg_ptr = base_type::source_image().row(y_lr + start) + (x_lr + start) * 3; - do - { - x_count = dimension; - weight_y = weight_array[y_hr]; - x_hr = image_subpixel_mask - x_fract; - - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - image_filter_shift; - - fg[0] += m_gamma->dir(*fg_ptr++) * weight; - fg[1] += m_gamma->dir(*fg_ptr++) * weight; - fg[2] += m_gamma->dir(*fg_ptr++) * weight; - - x_hr += image_subpixel_size; - - } while(--x_count); - - y_hr += image_subpixel_size; - fg_ptr += stride; - - } while(--y_count); - - fg[0] >>= image_filter_shift; - fg[1] >>= image_filter_shift; - fg[2] >>= image_filter_shift; - - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - - if(fg[0] > 255) fg[0] = 255; - if(fg[1] > 255) fg[1] = 255; - if(fg[2] > 255) fg[2] = 255; - src_alpha = 255; - } - else - { - if(x_lr < start1 || y_lr < start1 || - x_lr > maxx2 || y_lr > maxy2) - { - fg[Order::R] = back_r; - fg[Order::G] = back_g; - fg[Order::B] = back_b; - src_alpha = back_a; - } - else - { - src_alpha = image_filter_size / 2; - y_lr = (y >> image_subpixel_shift) + start; - y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); - - do - { - x_count = dimension; - weight_y = weight_array[y_hr]; - x_lr = (x >> image_subpixel_shift) + start; - x_hr = image_subpixel_mask - x_fract; - - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - image_filter_shift; - - if(x_lr >= 0 && y_lr >= 0 && - x_lr < int(base_type::source_image().width()) && - y_lr < int(base_type::source_image().height())) - { - fg_ptr = base_type::source_image().row(y_lr) + x_lr * 3; - fg[0] += m_gamma->dir(*fg_ptr++) * weight; - fg[1] += m_gamma->dir(*fg_ptr++) * weight; - fg[2] += m_gamma->dir(*fg_ptr++) * weight; - src_alpha += 255 * weight; - } - else - { - fg[Order::R] += back_r * weight; - fg[Order::G] += back_g * weight; - fg[Order::B] += back_b * weight; - src_alpha += back_a * weight; - } - x_hr += image_subpixel_size; - x_lr++; - - } while(--x_count); - - y_hr += image_subpixel_size; - y_lr++; - - } while(--y_count); - - - fg[0] >>= image_filter_shift; - fg[1] >>= image_filter_shift; - fg[2] >>= image_filter_shift; - src_alpha >>= image_filter_shift; - - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - if(src_alpha < 0) src_alpha = 0; - - if(fg[0] > 255) fg[0] = 255; - if(fg[1] > 255) fg[1] = 255; - if(fg[2] > 255) fg[2] = 255; - if(src_alpha > 255) src_alpha = 255; - } - } - - span->r = (int8u)m_gamma->inv(fg[Order::R]); - span->g = (int8u)m_gamma->inv(fg[Order::G]); - span->b = (int8u)m_gamma->inv(fg[Order::B]); - span->a = (int8u)src_alpha; - ++span; - ++base_type::interpolator(); - - } while(--len); - - return base_type::allocator().span(); - } - - private: - const gamma_type* m_gamma; - }; - -} - - -#endif - - - diff --git a/agg2/include/agg_span_image_filter_rgba32.h b/agg2/include/agg_span_image_filter_rgba32.h deleted file mode 100644 index f36098e..0000000 --- a/agg2/include/agg_span_image_filter_rgba32.h +++ /dev/null @@ -1,548 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// classes span_image_filter_rgba32* -// -//---------------------------------------------------------------------------- -#ifndef AGG_SPAN_IMAGE_FILTER_RGBA32_INCLUDED -#define AGG_SPAN_IMAGE_FILTER_RGBA32_INCLUDED - -#include "agg_basics.h" -#include "agg_color_rgba8.h" -#include "agg_span_image_filter.h" - - -namespace agg -{ - - //=============================================span_image_filter_rgba32_nn - template > - class span_image_filter_rgba32_nn : - public span_image_filter - { - public: - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter base_type; - typedef rgba8 color_type; - - //-------------------------------------------------------------------- - span_image_filter_rgba32_nn(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_filter_rgba32_nn(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter) : - base_type(alloc, src, back_color, inter, 0) - {} - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - base_type::interpolator().begin(x, y, len); - - int fg[4]; - - const unsigned char *fg_ptr; - color_type* span = base_type::allocator().span(); - - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - - do - { - base_type::interpolator().coordinates(&x, &y); - - x >>= image_subpixel_shift; - y >>= image_subpixel_shift; - - if(x >= 0 && y >= 0 && - x <= maxx && y <= maxy) - { - fg_ptr = base_type::source_image().row(y) + (x << 2); - fg[0] = *fg_ptr++; - fg[1] = *fg_ptr++; - fg[2] = *fg_ptr++; - fg[3] = *fg_ptr++; - } - else - { - fg[Order::R] = base_type::background_color().r; - fg[Order::G] = base_type::background_color().g; - fg[Order::B] = base_type::background_color().b; - fg[Order::A] = base_type::background_color().a; - } - - span->r = fg[Order::R]; - span->g = fg[Order::G]; - span->b = fg[Order::B]; - span->a = fg[Order::A]; - ++span; - ++base_type::interpolator(); - - } while(--len); - - return base_type::allocator().span(); - } - - }; - - - - - - - - - - - //=======================================span_image_filter_rgba32_bilinear - template > - class span_image_filter_rgba32_bilinear : - public span_image_filter - { - public: - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter base_type; - typedef rgba8 color_type; - - //-------------------------------------------------------------------- - span_image_filter_rgba32_bilinear(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_filter_rgba32_bilinear(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter) : - base_type(alloc, src, back_color, inter, 0) - {} - - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - base_type::interpolator().begin(x, y, len); - - int fg[4]; - int back_r = base_type::background_color().r; - int back_g = base_type::background_color().g; - int back_b = base_type::background_color().b; - int back_a = base_type::background_color().a; - - const unsigned char *fg_ptr; - - int stride = base_type::source_image().stride() - 2 * 4; - color_type* span = base_type::allocator().span(); - - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - - do - { - int x_hr; - int y_hr; - - base_type::interpolator().coordinates(&x_hr, &y_hr); - - int x_lr = x_hr >> image_subpixel_shift; - int y_lr = y_hr >> image_subpixel_shift; - int weight; - - if(x_lr >= 0 && y_lr >= 0 && - x_lr < maxx && y_lr < maxy) - { - fg[0] = - fg[1] = - fg[2] = - fg[3] = image_subpixel_size * image_subpixel_size / 2; - - x_hr &= image_subpixel_mask; - y_hr &= image_subpixel_mask; - fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2); - - weight = (image_subpixel_size - x_hr) * - (image_subpixel_size - y_hr); - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - fg[3] += weight * *fg_ptr++; - - weight = x_hr * (image_subpixel_size - y_hr); - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - fg[3] += weight * *fg_ptr++; - - fg_ptr += stride; - - weight = (image_subpixel_size - x_hr) * y_hr; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - fg[3] += weight * *fg_ptr++; - - weight = x_hr * y_hr; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - fg[3] += weight * *fg_ptr++; - - fg[0] >>= image_subpixel_shift * 2; - fg[1] >>= image_subpixel_shift * 2; - fg[2] >>= image_subpixel_shift * 2; - fg[3] >>= image_subpixel_shift * 2; - } - else - { - if(x_lr < -1 || y_lr < -1 || - x_lr > maxx || y_lr > maxy) - { - fg[Order::R] = back_r; - fg[Order::G] = back_g; - fg[Order::B] = back_b; - fg[Order::A] = back_a; - } - else - { - fg[0] = - fg[1] = - fg[2] = - fg[3] = image_subpixel_size * image_subpixel_size / 2; - - x_hr &= image_subpixel_mask; - y_hr &= image_subpixel_mask; - - weight = (image_subpixel_size - x_hr) * - (image_subpixel_size - y_hr); - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2); - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - fg[3] += weight * *fg_ptr++; - } - else - { - fg[Order::R] += back_r * weight; - fg[Order::G] += back_g * weight; - fg[Order::B] += back_b * weight; - fg[Order::A] += back_a * weight; - } - - x_lr++; - - weight = x_hr * (image_subpixel_size - y_hr); - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2); - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - fg[3] += weight * *fg_ptr++; - } - else - { - fg[Order::R] += back_r * weight; - fg[Order::G] += back_g * weight; - fg[Order::B] += back_b * weight; - fg[Order::A] += back_a * weight; - } - - x_lr--; - y_lr++; - - weight = (image_subpixel_size - x_hr) * y_hr; - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2); - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - fg[3] += weight * *fg_ptr++; - } - else - { - fg[Order::R] += back_r * weight; - fg[Order::G] += back_g * weight; - fg[Order::B] += back_b * weight; - fg[Order::A] += back_a * weight; - } - - x_lr++; - - weight = x_hr * y_hr; - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2); - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - fg[3] += weight * *fg_ptr++; - } - else - { - fg[Order::R] += back_r * weight; - fg[Order::G] += back_g * weight; - fg[Order::B] += back_b * weight; - fg[Order::A] += back_a * weight; - } - - fg[0] >>= image_subpixel_shift * 2; - fg[1] >>= image_subpixel_shift * 2; - fg[2] >>= image_subpixel_shift * 2; - fg[3] >>= image_subpixel_shift * 2; - } - } - - span->r = (int8u)fg[Order::R]; - span->g = (int8u)fg[Order::G]; - span->b = (int8u)fg[Order::B]; - span->a = (int8u)fg[Order::A]; - ++span; - ++base_type::interpolator(); - - } while(--len); - - return base_type::allocator().span(); - } - }; - - - - - - //================================================span_image_filter_rgba32 - template > - class span_image_filter_rgba32 : - public span_image_filter - { - public: - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter base_type; - typedef rgba8 color_type; - - //-------------------------------------------------------------------- - span_image_filter_rgba32(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_filter_rgba32(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter, - const image_filter_base& filter) : - base_type(alloc, src, back_color, inter, &filter) - {} - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - base_type::interpolator().begin(x, y, len); - - int fg[4]; - - int back_r = base_type::background_color().r; - int back_g = base_type::background_color().g; - int back_b = base_type::background_color().b; - int back_a = base_type::background_color().a; - - const unsigned char *fg_ptr; - - unsigned dimension = base_type::filter().dimension(); - int start = base_type::filter().start(); - int start1 = start - 1; - const int* weight_array = base_type::filter().weight_array_int(); - - int stride = base_type::source_image().stride() - (dimension << 2); - color_type* span = base_type::allocator().span(); - - int maxx = base_type::source_image().width() + start - 2; - int maxy = base_type::source_image().height() + start - 2; - - int maxx2 = base_type::source_image().width() - start - 1; - int maxy2 = base_type::source_image().height() - start - 1; - - int x_count; - int weight_y; - - do - { - base_type::interpolator().coordinates(&x, &y); - - int x_hr = x; - int y_hr = y; - - int x_lr = x_hr >> image_subpixel_shift; - int y_lr = y_hr >> image_subpixel_shift; - - fg[0] = fg[1] = fg[2] = fg[3] = image_filter_size / 2; - - int x_fract = x_hr & image_subpixel_mask; - unsigned y_count = dimension; - - if(x_lr >= -start && y_lr >= -start && - x_lr <= maxx && y_lr <= maxy) - { - y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); - fg_ptr = base_type::source_image().row(y_lr + start) + ((x_lr + start) << 2); - do - { - x_count = dimension; - weight_y = weight_array[y_hr]; - x_hr = image_subpixel_mask - x_fract; - - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - image_filter_shift; - - fg[0] += *fg_ptr++ * weight; - fg[1] += *fg_ptr++ * weight; - fg[2] += *fg_ptr++ * weight; - fg[3] += *fg_ptr++ * weight; - - x_hr += image_subpixel_size; - - } while(--x_count); - - y_hr += image_subpixel_size; - fg_ptr += stride; - - } while(--y_count); - - fg[0] >>= image_filter_shift; - fg[1] >>= image_filter_shift; - fg[2] >>= image_filter_shift; - fg[3] >>= image_filter_shift; - - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - if(fg[3] < 0) fg[3] = 0; - - if(fg[0] > 255) fg[0] = 255; - if(fg[1] > 255) fg[1] = 255; - if(fg[2] > 255) fg[2] = 255; - if(fg[3] > 255) fg[3] = 255; - } - else - { - if(x_lr < start1 || y_lr < start1 || - x_lr > maxx2 || y_lr > maxy2) - { - fg[Order::R] = back_r; - fg[Order::G] = back_g; - fg[Order::B] = back_b; - fg[Order::A] = back_a; - } - else - { - y_lr = (y >> image_subpixel_shift) + start; - y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); - - do - { - x_count = dimension; - weight_y = weight_array[y_hr]; - x_lr = (x >> image_subpixel_shift) + start; - x_hr = image_subpixel_mask - x_fract; - - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - image_filter_shift; - - if(x_lr >= 0 && y_lr >= 0 && - x_lr < int(base_type::source_image().width()) && - y_lr < int(base_type::source_image().height())) - { - fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2); - fg[0] += *fg_ptr++ * weight; - fg[1] += *fg_ptr++ * weight; - fg[2] += *fg_ptr++ * weight; - fg[3] += *fg_ptr++ * weight; - } - else - { - fg[Order::R] += back_r * weight; - fg[Order::G] += back_g * weight; - fg[Order::B] += back_b * weight; - fg[Order::A] += back_a * weight; - } - x_hr += image_subpixel_size; - x_lr++; - - } while(--x_count); - - y_hr += image_subpixel_size; - y_lr++; - - } while(--y_count); - - - fg[0] >>= image_filter_shift; - fg[1] >>= image_filter_shift; - fg[2] >>= image_filter_shift; - fg[3] >>= image_filter_shift; - - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - if(fg[3] < 0) fg[3] = 0; - - if(fg[0] > 255) fg[0] = 255; - if(fg[1] > 255) fg[1] = 255; - if(fg[2] > 255) fg[2] = 255; - if(fg[3] > 255) fg[3] = 255; - } - } - - span->r = fg[Order::R]; - span->g = fg[Order::G]; - span->b = fg[Order::B]; - span->a = fg[Order::A]; - ++span; - ++base_type::interpolator(); - - } while(--len); - - return base_type::allocator().span(); - } - - }; - - -} - - -#endif - - - diff --git a/agg2/include/agg_span_interpolator_linear.h b/agg2/include/agg_span_interpolator_linear.h deleted file mode 100644 index 61af77a..0000000 --- a/agg2/include/agg_span_interpolator_linear.h +++ /dev/null @@ -1,101 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED -#define AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED - -#include "agg_basics.h" -#include "agg_dda_line.h" -#include "agg_trans_affine.h" - -namespace agg -{ - - //================================================span_interpolator_linear - template - class span_interpolator_linear - { - public: - typedef Transformer trans_type; - - enum - { - subpixel_shift = SubpixelShift, - subpixel_size = 1 << subpixel_shift - }; - - //-------------------------------------------------------------------- - span_interpolator_linear() {} - span_interpolator_linear(const trans_type& trans) : m_trans(&trans) {} - span_interpolator_linear(const trans_type& trans, - double x, double y, unsigned len) : - m_trans(&trans) - { - begin(x, y, len); - } - - //---------------------------------------------------------------- - const trans_type& transformer() const { return *m_trans; } - void transformer(const trans_type& trans) { m_trans = &trans; } - - //---------------------------------------------------------------- - void begin(double x, double y, unsigned len) - { - double tx; - double ty; - - tx = x; - ty = y; - m_trans->transform(&tx, &ty); - int x1 = int(tx * subpixel_size); - int y1 = int(ty * subpixel_size); - - tx = x + len; - ty = y; - m_trans->transform(&tx, &ty); - int x2 = int(tx * subpixel_size); - int y2 = int(ty * subpixel_size); - - m_li_x = dda2_line_interpolator(x1, x2, len); - m_li_y = dda2_line_interpolator(y1, y2, len); - } - - //---------------------------------------------------------------- - void operator++() - { - ++m_li_x; - ++m_li_y; - } - - //---------------------------------------------------------------- - void coordinates(int* x, int* y) const - { - *x = m_li_x.y(); - *y = m_li_y.y(); - } - - private: - const trans_type* m_trans; - dda2_line_interpolator m_li_x; - dda2_line_interpolator m_li_y; - }; - -} - - - -#endif - - diff --git a/agg2/include/agg_span_pattern.h b/agg2/include/agg_span_pattern.h deleted file mode 100644 index 3a5b648..0000000 --- a/agg2/include/agg_span_pattern.h +++ /dev/null @@ -1,78 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - - -#ifndef AGG_SPAN_PATTERN_INCLUDED -#define AGG_SPAN_PATTERN_INCLUDED - -#include "agg_basics.h" -#include "agg_rendering_buffer.h" -#include "agg_span_generator.h" - - -namespace agg -{ - - //--------------------------------------------------------span_pattern - template - class span_pattern : public span_generator - { - public: - typedef ColorT color_type; - typedef AlphaT alpha_type; - typedef Allocator alloc_type; - - //---------------------------------------------------------------- - span_pattern(alloc_type& alloc) : - span_generator(alloc) - {} - - //---------------------------------------------------------------- - span_pattern(alloc_type& alloc, - const rendering_buffer& src, - unsigned offset_x, unsigned offset_y, - alpha_type alpha) : - span_generator(alloc), - m_src(&src), - m_offset_x(offset_x), - m_offset_y(offset_y), - m_alpha(alpha) - {} - - //---------------------------------------------------------------- - const rendering_buffer& source_image() const { return *m_src; } - unsigned offset_x() const { return m_offset_x; } - unsigned offset_y() const { return m_offset_y; } - alpha_type alpha() const { return m_alpha; } - - //---------------------------------------------------------------- - void source_image(const rendering_buffer& v) { m_src = &v; } - void offset_x(unsigned v) { m_offset_x = v; } - void offset_y(unsigned v) { m_offset_y = v; } - void alpha(alpha_type v) { m_alpha = v; } - - //---------------------------------------------------------------- - private: - const rendering_buffer* m_src; - unsigned m_offset_x; - unsigned m_offset_y; - alpha_type m_alpha; - }; - - -} - -#endif - diff --git a/agg2/include/agg_span_pattern_rgb24.h b/agg2/include/agg_span_pattern_rgb24.h deleted file mode 100644 index 88da150..0000000 --- a/agg2/include/agg_span_pattern_rgb24.h +++ /dev/null @@ -1,79 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - - -#ifndef AGG_SPAN_PATTERN_RGB24_INCLUDED -#define AGG_SPAN_PATTERN_RGB24_INCLUDED - -#include "agg_basics.h" -#include "agg_pixfmt_rgb24.h" -#include "agg_span_pattern.h" - -namespace agg -{ - - //=======================================================span_pattern_rgb24 - template > - class span_pattern_rgb24 : public span_pattern - { - public: - typedef Allocator alloc_type; - typedef rgba8 color_type; - typedef span_pattern base_type; - - //-------------------------------------------------------------------- - span_pattern_rgb24(alloc_type& alloc) : base_type(alloc) {} - - //---------------------------------------------------------------- - span_pattern_rgb24(alloc_type& alloc, - const rendering_buffer& src, - unsigned offset_x, unsigned offset_y, - int8u alpha = 255) : - base_type(alloc, src, offset_x, offset_y, alpha) - {} - - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - color_type* span = base_type::allocator().span(); - unsigned sx = (base_type::offset_x() + x) % base_type::source_image().width(); - unsigned wp = base_type::source_image().width() * 3; - const int8u* p = base_type::source_image().row((base_type::offset_y() + y) % base_type::source_image().height()); - p += sx * 3; - do - { - span->r = p[Order::R]; - span->g = p[Order::G]; - span->b = p[Order::B]; - span->a = base_type::alpha(); - p += 3; - ++sx; - ++span; - if(sx >= base_type::source_image().width()) - { - sx -= base_type::source_image().width(); - p -= wp; - } - } - while(--len); - return base_type::allocator().span(); - } - }; - -} - -#endif - diff --git a/agg2/include/agg_span_pattern_rgba32.h b/agg2/include/agg_span_pattern_rgba32.h deleted file mode 100644 index 5b9cea7..0000000 --- a/agg2/include/agg_span_pattern_rgba32.h +++ /dev/null @@ -1,77 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - - -#ifndef AGG_SPAN_PATTERN_RGBA32_INCLUDED -#define AGG_SPAN_PATTERN_RGBA32_INCLUDED - -#include "agg_basics.h" -#include "agg_pixfmt_rgba32.h" -#include "agg_span_pattern.h" - -namespace agg -{ - - //======================================================span_pattern_rgba32 - template > - class span_pattern_rgba32 : public span_pattern - { - public: - typedef Allocator alloc_type; - typedef rgba8 color_type; - typedef span_pattern base_type; - - //-------------------------------------------------------------------- - span_pattern_rgba32(alloc_type& alloc) : base_type(alloc) {} - - //---------------------------------------------------------------- - span_pattern_rgba32(alloc_type& alloc, - const rendering_buffer& src, - unsigned offset_x, unsigned offset_y) : - base_type(alloc, src, offset_x, offset_y, 0) - {} - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - color_type* span = base_type::allocator().span(); - unsigned sx = (base_type::offset_x() + x) % base_type::source_image().width(); - unsigned wp = base_type::source_image().width() << 2; - const int8u* p = base_type::source_image().row((base_type::offset_y() + y) % base_type::source_image().height()); - p += sx << 2; - do - { - span->r = p[Order::R]; - span->g = p[Order::G]; - span->b = p[Order::B]; - span->a = p[Order::A]; - p += 4; - ++sx; - ++span; - if(sx >= base_type::source_image().width()) - { - sx -= base_type::source_image().width(); - p -= wp; - } - } - while(--len); - return base_type::allocator().span(); - } - }; - -} - -#endif - diff --git a/agg2/include/agg_trans_perspective.h b/agg2/include/agg_trans_perspective.h deleted file mode 100644 index 3a46de5..0000000 --- a/agg2/include/agg_trans_perspective.h +++ /dev/null @@ -1,148 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// Perspective 2D transformations -// -//---------------------------------------------------------------------------- -#ifndef AGG_TRANS_PERSPECTIVE_INCLUDED -#define AGG_TRANS_PERSPECTIVE_INCLUDED - -#include "agg_basics.h" -#include "agg_simul_eq.h" - -namespace agg -{ - //=======================================================trans_perspective - class trans_perspective - { - public: - //-------------------------------------------------------------------- - trans_perspective() : m_valid(false) {} - - - //-------------------------------------------------------------------- - // Arbitrary quadrangle transformations - trans_perspective(const double* src, const double* dst) - { - quad_to_quad(src, dst); - } - - - //-------------------------------------------------------------------- - // Direct transformations - trans_perspective(double x1, double y1, double x2, double y2, - const double* quad) - { - rect_to_quad(x1, y1, x2, y2, quad); - } - - - //-------------------------------------------------------------------- - // Reverse transformations - trans_perspective(const double* quad, - double x1, double y1, double x2, double y2) - { - quad_to_rect(quad, x1, y1, x2, y2); - } - - - //-------------------------------------------------------------------- - // Set the transformations using two arbitrary quadrangles. - void quad_to_quad(const double* src, const double* dst) - { - - double left[8][8]; - double right[8][1]; - - unsigned i; - for (i = 0; i < 4; i++) - { - unsigned ix = i * 2; - unsigned iy = ix + 1; - - left[ix][0] = 1.0; - left[ix][1] = src[ix]; - left[ix][2] = src[iy]; - left[ix][3] = 0.0; - left[ix][4] = 0.0; - left[ix][5] = 0.0; - left[ix][6] = -src[ix] * dst[ix]; - left[ix][7] = -src[iy] * dst[ix]; - right[ix][0] = dst[ix]; - - left[iy][0] = 0.0; - left[iy][1] = 0.0; - left[iy][2] = 0.0; - left[iy][3] = 1.0; - left[iy][4] = src[ix]; - left[iy][5] = src[iy]; - left[iy][6] = -src[ix] * dst[iy]; - left[iy][7] = -src[iy] * dst[iy]; - right[iy][0] = dst[iy]; - } - m_valid = simul_eq<8, 1>::solve(left, right, m_mtx); - } - - - //-------------------------------------------------------------------- - // Set the direct transformations, i.e., rectangle -> quadrangle - void rect_to_quad(double x1, double y1, double x2, double y2, - const double* quad) - { - double src[8]; - src[0] = src[6] = x1; - src[2] = src[4] = x2; - src[1] = src[3] = y1; - src[5] = src[7] = y2; - quad_to_quad(src, quad); - } - - - //-------------------------------------------------------------------- - // Set the reverse transformations, i.e., quadrangle -> rectangle - void quad_to_rect(const double* quad, - double x1, double y1, double x2, double y2) - { - double dst[8]; - dst[0] = dst[6] = x1; - dst[2] = dst[4] = x2; - dst[1] = dst[3] = y1; - dst[5] = dst[7] = y2; - quad_to_quad(quad, dst); - } - - //-------------------------------------------------------------------- - // Check if the equations were solved successfully - bool is_valid() const { return m_valid; } - - //-------------------------------------------------------------------- - // Transform a point (x, y) - void transform(double* x, double* y) const - { - double tx = *x; - double ty = *y; - double d = 1.0 / (m_mtx[6][0] * tx + m_mtx[7][0] * ty + 1.0); - *x = (m_mtx[0][0] + m_mtx[1][0] * tx + m_mtx[2][0] * ty) * d; - *y = (m_mtx[3][0] + m_mtx[4][0] * tx + m_mtx[5][0] * ty) * d; - } - - private: - double m_mtx[8][1]; - bool m_valid; - }; - -} - -#endif diff --git a/agg2/include/agg_vcgen_contour.h b/agg2/include/agg_vcgen_contour.h deleted file mode 100644 index 3531e7d..0000000 --- a/agg2/include/agg_vcgen_contour.h +++ /dev/null @@ -1,88 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_VCGEN_CONTOUR_INCLUDED -#define AGG_VCGEN_CONTOUR_INCLUDED - -#include "agg_basics.h" -#include "agg_vertex_sequence.h" - -namespace agg -{ - - //----------------------------------------------------------vcgen_contour - // - // See Implementation agg_vcgen_contour.cpp - // - class vcgen_contour - { - enum status_e - { - initial, - ready, - outline, - add_point, - end_poly - }; - - public: - typedef vertex_sequence vertex_storage; - - vcgen_contour(); - - void width(double w) { m_width = w * 0.5; } - void miter_limit(double ml) { m_miter_limit = ml; } - void miter_limit_theta(double t); - void auto_detect_orientation(bool v) { m_auto_detect = v; } - - double width() const { return m_width * 2.0; } - double miter_limit() const { return m_miter_limit; } - bool auto_detect_orientation() const { return m_auto_detect; } - - // Generator interface - void remove_all(); - void add_vertex(double x, double y, unsigned cmd); - - // Vertex Source Interface - void rewind(unsigned id); - unsigned vertex(double* x, double* y); - - private: - vcgen_contour(const vcgen_contour&); - const vcgen_contour& operator = (const vcgen_contour&); - - bool calc_miter(const vertex_dist& v0, - const vertex_dist& v1, - const vertex_dist& v2); - - vertex_storage m_src_vertices; - double m_width; - double m_abs_width; - double m_signed_width; - double m_miter_limit; - status_e m_status; - unsigned m_src_vertex; - unsigned m_closed; - unsigned m_orientation; - bool m_auto_detect; - double m_x1; - double m_y1; - double m_x2; - double m_y2; - }; - -} - -#endif diff --git a/agg2/include/agg_vcgen_stroke.h b/agg2/include/agg_vcgen_stroke.h deleted file mode 100644 index 825cc15..0000000 --- a/agg2/include/agg_vcgen_stroke.h +++ /dev/null @@ -1,155 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_VCGEN_STROKE_INCLUDED -#define AGG_VCGEN_STROKE_INCLUDED - -#include "agg_basics.h" -#include "agg_vertex_sequence.h" -#include "agg_vertex_iterator.h" - -namespace agg -{ - - // Minimal angle to calculate round joins - const double vcgen_stroke_theta = 1e-10; //----vcgen_stroke_theta - - //============================================================vcgen_stroke - // - // See Implementation agg_vcgen_stroke.cpp - // Stroke generator - // - //------------------------------------------------------------------------ - class vcgen_stroke - { - enum status_e - { - initial, - ready, - cap1, - cap2, - outline1, - close_first, - outline2, - out_vertices, - end_poly1, - end_poly2, - stop - }; - - public: - enum line_cap_e - { - butt_cap, - square_cap, - round_cap - }; - - enum line_join_e - { - miter_join, - miter_join_revert, - round_join, - bevel_join - }; - - struct coord_type - { - double x, y; - - coord_type() {} - coord_type(double x_, double y_) : x(x_), y(y_) {} - }; - - - typedef vertex_sequence vertex_storage; - typedef pod_deque coord_storage; - - vcgen_stroke(); - - void line_cap(line_cap_e lc) { m_line_cap = lc; } - void line_join(line_join_e lj) { m_line_join = lj; } - - line_cap_e line_cap() const { return m_line_cap; } - line_join_e line_join() const { return m_line_join; } - - void width(double w) { m_width = w * 0.5; } - void miter_limit(double ml) { m_miter_limit = ml; } - void miter_limit_theta(double t); - 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 approximation_scale() const { return m_approx_scale; } - - void shorten(double s) { m_shorten = s; } - double shorten() const { return m_shorten; } - - // Vertex Generator Interface - void remove_all(); - void add_vertex(double x, double y, unsigned cmd); - - // Vertex Source Interface - void rewind(unsigned id); - unsigned vertex(double* x, double* y); - - typedef vcgen_stroke source_type; - typedef vertex_iterator iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - - private: - vcgen_stroke(const vcgen_stroke&); - const vcgen_stroke& operator = (const vcgen_stroke&); - - void calc_join(const vertex_dist& v0, - const vertex_dist& v1, - const vertex_dist& v2, - double len1, double len2); - - void calc_miter(const vertex_dist& v0, - const vertex_dist& v1, - const vertex_dist& v2, - double dx1, double dy1, - double dx2, double dy2, - bool revert_flag); - - void calc_arc(double x, double y, - double dx1, double dy1, - double dx2, double dy2); - - void calc_cap(const vertex_dist& v0, - const vertex_dist& v1, - double len); - - vertex_storage m_src_vertices; - coord_storage m_out_vertices; - double m_width; - double m_miter_limit; - double m_approx_scale; - double m_shorten; - line_cap_e m_line_cap; - line_join_e m_line_join; - unsigned m_closed; - status_e m_status; - status_e m_prev_status; - unsigned m_src_vertex; - unsigned m_out_vertex; - }; - - -} - -#endif diff --git a/agg2/include/agg_vertex_iterator.h b/agg2/include/agg_vertex_iterator.h deleted file mode 100644 index 75746dd..0000000 --- a/agg2/include/agg_vertex_iterator.h +++ /dev/null @@ -1,133 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// classes: vertex_iterator -// vertex_source_adaptor -// vertex_source_adaptor_with_id -// -//---------------------------------------------------------------------------- -#ifndef AGG_VERTEX_ITERATOR_INCLUDED -#define AGG_VERTEX_ITERATOR_INCLUDED - -#include "agg_basics.h" - - -namespace agg -{ - - //---------------------------------------------------------vertex_iterator - template class vertex_iterator - { - public: - vertex_iterator() {} - vertex_iterator(unsigned cmd) { m_vertex.cmd = cmd; } - vertex_iterator(const vertex_iterator& i) : m_vs(i.m_vs), m_vertex(i.m_vertex) {} - vertex_iterator(VertexSource& vs, unsigned id) : m_vs(&vs) - { - m_vs->rewind(id); - m_vertex.cmd = m_vs->vertex(&m_vertex.x, &m_vertex.y); - } - vertex_iterator& operator++() - { - m_vertex.cmd = m_vs->vertex(&m_vertex.x, &m_vertex.y); - return *this; - } - - const vertex_type& operator*() const { return m_vertex; } - const vertex_type* operator->() const { return &m_vertex; } - - bool operator != (const vertex_iterator& i) - { - return m_vertex.cmd != i.m_vertex.cmd; - } - - private: - VertexSource* m_vs; - vertex_type m_vertex; - }; - - - //---------------------------------------------------vertex_source_adaptor - template class vertex_source_adaptor - { - public: - vertex_source_adaptor(const VertexContainer& container) : - m_container(&container) {} - - void rewind(unsigned) - { - m_iterator = m_container->begin(); - m_end = m_container->end(); - } - - unsigned vertex(double* x, double* y) - { - unsigned cmd = path_cmd_stop; - if(m_iterator != m_end) - { - *x = m_iterator->x; - *y = m_iterator->y; - cmd = m_iterator->cmd; - ++m_iterator; - } - return cmd; - } - - private: - const VertexContainer* m_container; - typename VertexContainer::const_iterator m_iterator; - typename VertexContainer::const_iterator m_end; - }; - - - - //-------------------------------------------vertex_source_adaptor_with_id - template class vertex_source_adaptor_with_id - { - public: - vertex_source_adaptor_with_id(const VertexContainer& container) : - m_container(&container) {} - - void rewind(unsigned id) - { - m_iterator = m_container->begin(id); - m_end = m_container->end(); - } - - unsigned vertex(double* x, double* y) - { - unsigned cmd = path_cmd_stop; - if(m_iterator != m_end) - { - *x = m_iterator->x; - *y = m_iterator->y; - cmd = m_iterator->cmd; - ++m_iterator; - } - return cmd; - } - - private: - const VertexContainer* m_container; - typename VertexContainer::const_iterator m_iterator; - typename VertexContainer::const_iterator m_end; - }; - - - -} - - -#endif diff --git a/agg2/include/dbg_new/agg_dbg_new.h b/agg2/include/dbg_new/agg_dbg_new.h deleted file mode 100644 index 687358d..0000000 --- a/agg2/include/dbg_new/agg_dbg_new.h +++ /dev/null @@ -1,79 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// Debuging stuff for catching memory leaks and corruptions -// -//---------------------------------------------------------------------------- -#ifndef AGG_DBG_NEW_INCLUDED -#define AGG_DBG_NEW_INCLUDED - -#ifdef _WIN32 -#include -#include -#endif - -//#define AGG_DBG_NEW_CHECK_ADDR - -void* operator new (unsigned size, const char* file, int line); -void* operator new [] (unsigned size, const char* file, int line); -#define AGG_DBG_NEW_OPERATOR new(__FILE__, __LINE__) - -void operator delete(void *ptr) throw(); -void operator delete [] (void *ptr) throw(); - -namespace agg -{ - #ifdef _WIN32 - inline void printf(char* fmt, ...) - { - FILE* fd = fopen("stdout.txt", "at"); - static char msg[1024]; - va_list arg; - va_start(arg, fmt); - vsprintf(msg, fmt, arg); - va_end(arg); - fputs(msg, fd); - fclose(fd); - } - #endif - - enum { max_dbg_new_level = 32 }; - -#ifdef AGG_DBG_NEW_CHECK_ADDR - enum { max_allocations = 4096 }; -#endif - - // All you need to watch for memory in heap is to declare an object - // of this class in your main() or whatever function you need. - // It will report you about all bad things happend to new/delete. - // Try not to exceed the maximal nested level of declared watchdoggies - // (max_dbg_new_level) - class watchdoggy - { - public: - watchdoggy(const char* file=0, int line=0, bool report_all=false); - ~watchdoggy(); - }; -} - -#define AGG_WATCHDOGGY(name, report_all) \ - agg::watchdoggy name(__FILE__, __LINE__, report_all); -#endif - -#ifdef new -#undef new -#endif -#define new AGG_DBG_NEW_OPERATOR - diff --git a/agg2/include/util/agg_color_conv.h b/agg2/include/util/agg_color_conv.h deleted file mode 100644 index fd7aeea..0000000 --- a/agg2/include/util/agg_color_conv.h +++ /dev/null @@ -1,84 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// Conversion from one colorspace/pixel format to another -// -//---------------------------------------------------------------------------- - -#ifndef AGG_COLOR_CONV_INCLUDED -#define AGG_COLOR_CONV_INCLUDED - -#include -#include "agg_basics.h" -#include "agg_rendering_buffer.h" - - - - -namespace agg -{ - - //--------------------------------------------------------------color_conv - template - void color_conv(rendering_buffer* dst, - const rendering_buffer* src, - CopyRow copy_row_functor) - { - unsigned width = src->width(); - unsigned height = src->height(); - - if(dst->width() < width) width = dst->width(); - if(dst->height() < height) height = dst->height(); - - if(width) - { - unsigned y; - for(y = 0; y < height; y++) - { - copy_row_functor(dst->row(y), src->row(y), width); - } - } - } - - - //---------------------------------------------------------color_conv_row - template - void color_conv_row(unsigned char* dst, - const unsigned char* src, - unsigned width, - CopyRow copy_row_functor) - { - copy_row_functor(dst, src, width); - } - - - //---------------------------------------------------------color_conv_same - template class color_conv_same - { - public: - void operator () (unsigned char* dst, - const unsigned char* src, - unsigned width) const - { - memmove(dst, src, width*BPP); - } - }; - - -} - - - -#endif diff --git a/agg2/src/agg_curves.cpp b/agg2/src/agg_curves.cpp deleted file mode 100644 index 710ea17..0000000 --- a/agg2/src/agg_curves.cpp +++ /dev/null @@ -1,246 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// classes curve3 and curve4 -// -//---------------------------------------------------------------------------- - -#include -#include "agg_curves.h" - -namespace agg -{ - - //------------------------------------------------------------------------ - void curve3::init(double x1, double y1, - double x2, double y2, - double x3, double y3) - { - m_start_x = x1; - m_start_y = y1; - m_end_x = x3; - m_end_y = y3; - - double dx1 = x2 - x1; - double dy1 = y2 - y1; - double dx2 = x3 - x2; - double dy2 = y3 - y2; - - double len = sqrt(dx1 * dx1 + dy1 * dy1) + sqrt(dx2 * dx2 + dy2 * dy2); - - m_num_steps = int(len * 0.25 * m_scale); - - if(m_num_steps < 2) - { - m_num_steps = 2; - } - - double subdivide_step = 1.0 / m_num_steps; - double subdivide_step2 = subdivide_step * subdivide_step; - - double tmpx = (x1 - x2 * 2.0 + x3) * subdivide_step2; - double tmpy = (y1 - y2 * 2.0 + y3) * subdivide_step2; - - m_saved_fx = m_fx = x1; - m_saved_fy = m_fy = y1; - - m_saved_dfx = m_dfx = tmpx + (x2 - x1) * (2.0 * subdivide_step); - m_saved_dfy = m_dfy = tmpy + (y2 - y1) * (2.0 * subdivide_step); - - m_ddfx = tmpx * 2.0; - m_ddfy = tmpy * 2.0; - - m_step = m_num_steps; - } - - - - - //------------------------------------------------------------------------ - void curve3::rewind(unsigned) - { - if(m_num_steps == 0) - { - m_step = -1; - return; - } - m_step = m_num_steps; - m_fx = m_saved_fx; - m_fy = m_saved_fy; - m_dfx = m_saved_dfx; - m_dfy = m_saved_dfy; - } - - - - - //------------------------------------------------------------------------ - unsigned curve3::vertex(double* x, double* y) - { - if(m_step < 0) return path_cmd_stop; - if(m_step == m_num_steps) - { - *x = m_start_x; - *y = m_start_y; - --m_step; - return path_cmd_move_to; - } - if(m_step == 0) - { - *x = m_end_x; - *y = m_end_y; - --m_step; - return path_cmd_line_to; - } - m_fx += m_dfx; - m_fy += m_dfy; - m_dfx += m_ddfx; - m_dfy += m_ddfy; - *x = m_fx; - *y = m_fy; - --m_step; - return path_cmd_line_to; - } - - - - - - - - - - - - - - //------------------------------------------------------------------------ - void curve4::init(double x1, double y1, - double x2, double y2, - double x3, double y3, - double x4, double y4) - { - m_start_x = x1; - m_start_y = y1; - m_end_x = x4; - m_end_y = y4; - - double dx1 = x2 - x1; - double dy1 = y2 - y1; - double dx2 = x3 - x2; - double dy2 = y3 - y2; - double dx3 = x4 - x3; - double dy3 = y4 - y3; - - double len = sqrt(dx1 * dx1 + dy1 * dy1) + - sqrt(dx2 * dx2 + dy2 * dy2) + - sqrt(dx3 * dx3 + dy3 * dy3); - - m_num_steps = int(len * 0.25 * m_scale); - - if(m_num_steps < 2) - { - m_num_steps = 2; - } - - double subdivide_step = 1.0 / m_num_steps; - double subdivide_step2 = subdivide_step * subdivide_step; - double subdivide_step3 = subdivide_step * subdivide_step * subdivide_step; - - double pre1 = 3.0 * subdivide_step; - double pre2 = 3.0 * subdivide_step2; - double pre4 = 6.0 * subdivide_step2; - double pre5 = 6.0 * subdivide_step3; - - double tmp1x = x1 - x2 * 2.0 + x3; - double tmp1y = y1 - y2 * 2.0 + y3; - - double tmp2x = (x2 - x3) * 3.0 - x1 + x4; - double tmp2y = (y2 - y3) * 3.0 - y1 + y4; - - m_saved_fx = m_fx = x1; - m_saved_fy = m_fy = y1; - - m_saved_dfx = m_dfx = (x2 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdivide_step3; - m_saved_dfy = m_dfy = (y2 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdivide_step3; - - m_saved_ddfx = m_ddfx = tmp1x * pre4 + tmp2x * pre5; - m_saved_ddfy = m_ddfy = tmp1y * pre4 + tmp2y * pre5; - - m_dddfx = tmp2x * pre5; - m_dddfy = tmp2y * pre5; - - m_step = m_num_steps; - } - - - - - //------------------------------------------------------------------------ - void curve4::rewind(unsigned) - { - if(m_num_steps == 0) - { - m_step = -1; - return; - } - m_step = m_num_steps; - m_fx = m_saved_fx; - m_fy = m_saved_fy; - m_dfx = m_saved_dfx; - m_dfy = m_saved_dfy; - m_ddfx = m_saved_ddfx; - m_ddfy = m_saved_ddfy; - } - - - - - - //------------------------------------------------------------------------ - unsigned curve4::vertex(double* x, double* y) - { - if(m_step < 0) return path_cmd_stop; - if(m_step == m_num_steps) - { - *x = m_start_x; - *y = m_start_y; - --m_step; - return path_cmd_move_to; - } - if(m_step == 0) - { - *x = m_end_x; - *y = m_end_y; - --m_step; - return path_cmd_line_to; - } - m_fx += m_dfx; - m_fy += m_dfy; - m_dfx += m_ddfx; - m_dfy += m_ddfy; - m_ddfx += m_dddfx; - m_ddfy += m_dddfy; - *x = m_fx; - *y = m_fy; - --m_step; - return path_cmd_line_to; - } - - - - -} - diff --git a/agg2/src/agg_path_storage.cpp b/agg2/src/agg_path_storage.cpp deleted file mode 100644 index c520bc8..0000000 --- a/agg2/src/agg_path_storage.cpp +++ /dev/null @@ -1,525 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// Class path_storage -// -//---------------------------------------------------------------------------- -#include -#include -#include "agg_path_storage.h" -#include "agg_math.h" -#include "agg_bezier_arc.h" - - -namespace agg -{ - - //------------------------------------------------------------------------ - path_storage::~path_storage() - { - if(m_total_blocks) - { - double** coord_blk = m_coord_blocks + m_total_blocks - 1; - while(m_total_blocks--) - { - delete [] *coord_blk; - --coord_blk; - } - delete [] m_coord_blocks; - } - } - - - //------------------------------------------------------------------------ - path_storage::path_storage() : - m_total_vertices(0), - m_total_blocks(0), - m_max_blocks(0), - m_coord_blocks(0), - m_cmd_blocks(0), - m_iterator(0) - { - } - - - //------------------------------------------------------------------------ - path_storage::path_storage(const path_storage& ps) : - m_total_vertices(0), - m_total_blocks(0), - m_max_blocks(0), - m_coord_blocks(0), - m_cmd_blocks(0), - m_iterator(0) - { - copy_from(ps); - } - - - //------------------------------------------------------------------------ - void path_storage::remove_all() - { - m_total_vertices = 0; - m_iterator = 0; - } - - - //------------------------------------------------------------------------ - void path_storage::copy_from(const path_storage& ps) - { - remove_all(); - unsigned i; - for(i = 0; i < ps.total_vertices(); i++) - { - double x, y; - unsigned cmd = ps.vertex(i, &x, &y); - add_vertex(x, y, cmd); - } - } - - - //------------------------------------------------------------------------ - void path_storage::allocate_block(unsigned nb) - { - if(nb >= m_max_blocks) - { - double** new_coords = - new double* [(m_max_blocks + block_pool) * 2]; - - unsigned char** new_cmds = - (unsigned char**)(new_coords + m_max_blocks + block_pool); - - if(m_coord_blocks) - { - memcpy(new_coords, - m_coord_blocks, - m_max_blocks * sizeof(double*)); - - memcpy(new_cmds, - m_cmd_blocks, - m_max_blocks * sizeof(unsigned char*)); - - delete [] m_coord_blocks; - } - m_coord_blocks = new_coords; - m_cmd_blocks = new_cmds; - m_max_blocks += block_pool; - } - m_coord_blocks[nb] = - new double [block_size * 2 + - block_size / - (sizeof(double) / sizeof(unsigned char))]; - - m_cmd_blocks[nb] = - (unsigned char*)(m_coord_blocks[nb] + block_size * 2); - - m_total_blocks++; - } - - - //------------------------------------------------------------------------ - void path_storage::rewind(unsigned path_id) - { - m_iterator = path_id; - } - - - - //------------------------------------------------------------------------ - void path_storage::arc_to(double rx, double ry, - double angle, - bool large_arc_flag, - bool sweep_flag, - double x, double y) - { - if(m_total_vertices && is_vertex(command(m_total_vertices - 1))) - { - const double epsilon = 1e-30; - double x0 = 0.0; - double y0 = 0.0; - last_vertex(&x0, &y0); - - rx = fabs(rx); - ry = fabs(ry); - - // Ensure radii are valid - //------------------------- - if(rx < epsilon || ry < epsilon) - { - line_to(x, y); - return; - } - - if(calc_distance(x0, y0, x, y) < epsilon) - { - // If the endpoints (x, y) and (x0, y0) are identical, then this - // is equivalent to omitting the elliptical arc segment entirely. - return; - } - bezier_arc_svg a(x0, y0, rx, ry, angle, large_arc_flag, sweep_flag, x, y); - if(a.radii_ok()) - { - add_path(a, 0, true); - } - else - { - line_to(x, y); - } - } - else - { - move_to(x, y); - } - } - - - //------------------------------------------------------------------------ - void path_storage::arc_rel(double rx, double ry, - double angle, - bool large_arc_flag, - bool sweep_flag, - double dx, double dy) - { - rel_to_abs(&dx, &dy); - arc_to(rx, ry, angle, large_arc_flag, sweep_flag, dx, dy); - } - - - //------------------------------------------------------------------------ - void path_storage::curve3(double x_ctrl, double y_ctrl, - double x_to, double y_to) - { - add_vertex(x_ctrl, y_ctrl, path_cmd_curve3); - add_vertex(x_to, y_to, path_cmd_curve3); - } - - //------------------------------------------------------------------------ - void path_storage::curve3_rel(double dx_ctrl, double dy_ctrl, - double dx_to, double dy_to) - { - rel_to_abs(&dx_ctrl, &dy_ctrl); - rel_to_abs(&dx_to, &dy_to); - add_vertex(dx_ctrl, dy_ctrl, path_cmd_curve3); - add_vertex(dx_to, dy_to, path_cmd_curve3); - } - - //------------------------------------------------------------------------ - void path_storage::curve3(double x_to, double y_to) - { - double x0; - double y0; - if(is_vertex(last_vertex(&x0, &y0))) - { - double x_ctrl; - double y_ctrl; - unsigned cmd = prev_vertex(&x_ctrl, &y_ctrl); - if(is_curve(cmd)) - { - x_ctrl = x0 + x0 - x_ctrl; - y_ctrl = y0 + y0 - y_ctrl; - } - else - { - x_ctrl = x0; - y_ctrl = y0; - } - curve3(x_ctrl, x_ctrl, x_to, y_to); - } - } - - - //------------------------------------------------------------------------ - void path_storage::curve3_rel(double dx_to, double dy_to) - { - rel_to_abs(&dx_to, &dy_to); - curve3(dx_to, dy_to); - } - - - //------------------------------------------------------------------------ - void path_storage::curve4(double x_ctrl1, double y_ctrl1, - double x_ctrl2, double y_ctrl2, - double x_to, double y_to) - { - add_vertex(x_ctrl1, y_ctrl1, path_cmd_curve4); - add_vertex(x_ctrl2, y_ctrl2, path_cmd_curve4); - add_vertex(x_to, y_to, path_cmd_curve4); - } - - //------------------------------------------------------------------------ - void path_storage::curve4_rel(double dx_ctrl1, double dy_ctrl1, - double dx_ctrl2, double dy_ctrl2, - double dx_to, double dy_to) - { - rel_to_abs(&dx_ctrl1, &dy_ctrl1); - rel_to_abs(&dx_ctrl2, &dy_ctrl2); - rel_to_abs(&dx_to, &dy_to); - add_vertex(dx_ctrl1, dy_ctrl1, path_cmd_curve4); - add_vertex(dx_ctrl2, dy_ctrl2, path_cmd_curve4); - add_vertex(dx_to, dy_to, path_cmd_curve4); - } - - - //------------------------------------------------------------------------ - void path_storage::curve4(double x_ctrl2, double y_ctrl2, - double x_to, double y_to) - { - double x0; - double y0; - if(is_vertex(last_vertex(&x0, &y0))) - { - double x_ctrl1; - double y_ctrl1; - unsigned cmd = prev_vertex(&x_ctrl1, &y_ctrl1); - if(is_curve(cmd)) - { - x_ctrl1 = x0 + x0 - x_ctrl1; - y_ctrl1 = y0 + y0 - y_ctrl1; - } - else - { - x_ctrl1 = x0; - y_ctrl1 = y0; - } - curve4(x_ctrl1, y_ctrl1, x_ctrl2, y_ctrl2, x_to, y_to); - } - } - - - //------------------------------------------------------------------------ - void path_storage::curve4_rel(double dx_ctrl2, double dy_ctrl2, - double dx_to, double dy_to) - { - rel_to_abs(&dx_ctrl2, &dy_ctrl2); - rel_to_abs(&dx_to, &dy_to); - curve4(dx_ctrl2, dy_ctrl2, dx_to, dy_to); - } - - - //------------------------------------------------------------------------ - void path_storage::end_poly(unsigned flags) - { - if(m_total_vertices) - { - if(is_vertex(command(m_total_vertices - 1))) - { - add_vertex(0.0, 0.0, path_cmd_end_poly | flags); - } - } - } - - - //------------------------------------------------------------------------ - unsigned path_storage::start_new_path() - { - if(m_total_vertices) - { - if(!is_stop(command(m_total_vertices - 1))) - { - add_vertex(0.0, 0.0, path_cmd_stop); - } - } - return m_total_vertices; - } - - - //------------------------------------------------------------------------ - void path_storage::add_poly(const double* vertices, unsigned num, - bool solid_path, unsigned end_flags) - { - if(num) - { - if(!solid_path) - { - move_to(vertices[0], vertices[1]); - vertices += 2; - --num; - } - while(num--) - { - line_to(vertices[0], vertices[1]); - vertices += 2; - } - if(end_flags) end_poly(end_flags); - } - } - - - //------------------------------------------------------------------------ - unsigned path_storage::perceive_polygon_orientation(unsigned idx, - double xs, double ys, - unsigned* orientation) - { - unsigned i; - double sum = 0.0; - double x, y, xn, yn; - - x = xs; - y = ys; - for(i = idx; i < m_total_vertices; ++i) - { - if(is_next_poly(vertex(i, &xn, &yn))) break; - sum += x * yn - y * xn; - x = xn; - y = yn; - } - if(i > idx) sum += x * ys - y * xs; - *orientation = path_flags_none; - if(sum != 0.0) - { - *orientation = (sum < 0.0) ? path_flags_cw : path_flags_ccw; - } - return i; - } - - - //------------------------------------------------------------------------ - void path_storage::reverse_polygon(unsigned start, unsigned end) - { - unsigned i; - unsigned tmp_cmd = command(start); - - // Shift all commands to one position - for(i = start; i < end; i++) - { - modify_command(i, command(i + 1)); - } - - // Assign starting command to the ending command - modify_command(end, tmp_cmd); - - // Reverse the polygon - while(end > start) - { - unsigned start_nb = start >> block_shift; - unsigned end_nb = end >> block_shift; - double* start_ptr = m_coord_blocks[start_nb] + ((start & block_mask) << 1); - double* end_ptr = m_coord_blocks[end_nb] + ((end & block_mask) << 1); - double tmp_xy; - - tmp_xy = *start_ptr; - *start_ptr++ = *end_ptr; - *end_ptr++ = tmp_xy; - - tmp_xy = *start_ptr; - *start_ptr = *end_ptr; - *end_ptr = tmp_xy; - - tmp_cmd = m_cmd_blocks[start_nb][start & block_mask]; - m_cmd_blocks[start_nb][start & block_mask] = m_cmd_blocks[end_nb][end & block_mask]; - m_cmd_blocks[end_nb][end & block_mask] = (unsigned char)tmp_cmd; - - ++start; - --end; - } - } - - - //------------------------------------------------------------------------ - unsigned path_storage::arrange_orientations(unsigned path_id, - path_flags_e new_orientation) - { - unsigned end = m_total_vertices; - if(m_total_vertices && new_orientation != path_flags_none) - { - unsigned start = path_id; - - double xs, ys; - unsigned cmd = vertex(start, &xs, &ys); - unsigned inc = 0; - for(;;) - { - unsigned orientation; - end = perceive_polygon_orientation(start + 1, xs, ys, - &orientation); - if(end > start + 2 && - orientation && - orientation != unsigned(new_orientation)) - { - reverse_polygon(start + inc, end - 1); - } - if(end >= m_total_vertices) break; - cmd = command(end); - if(is_stop(cmd)) - { - ++end; - break; - } - if(is_end_poly(cmd)) - { - inc = 1; - modify_command(end, set_orientation(cmd, new_orientation)); - } - else - { - cmd = vertex(++end, &xs, &ys); - inc = 0; - } - start = end; - } - } - return end; - } - - - - //------------------------------------------------------------------------ - void path_storage::arrange_orientations_all_paths(path_flags_e new_orientation) - { - if(new_orientation != path_flags_none) - { - unsigned start = 0; - while(start < m_total_vertices) - { - start = arrange_orientations(start, new_orientation); - } - } - } - - - - //------------------------------------------------------------------------ - void path_storage::flip_x(double x1, double x2) - { - unsigned i; - double x, y; - for(i = 0; i < m_total_vertices; i++) - { - unsigned cmd = vertex(i, &x, &y); - if(is_vertex(cmd)) - { - modify_vertex(i, x2 - x + x1, y); - } - } - } - - - //------------------------------------------------------------------------ - void path_storage::flip_y(double y1, double y2) - { - unsigned i; - double x, y; - for(i = 0; i < m_total_vertices; i++) - { - unsigned cmd = vertex(i, &x, &y); - if(is_vertex(cmd)) - { - modify_vertex(i, x, y2 - y + y1); - } - } - } - - -} - diff --git a/agg2/src/agg_rasterizer_scanline_aa.cpp b/agg2/src/agg_rasterizer_scanline_aa.cpp deleted file mode 100644 index 9d3c0e3..0000000 --- a/agg2/src/agg_rasterizer_scanline_aa.cpp +++ /dev/null @@ -1,621 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of David Turner, -// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType -// libray - in producing this work. See http://www.freetype.org for details. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// Class outline_aa - implementation. -// -// Initially the rendering algorithm was designed by David Turner and the -// other authors of the FreeType library - see the above notice. I nearly -// created a similar renderer, but still I was far from David's work. -// I completely redesigned the original code and adapted it for Anti-Grain -// ideas. Two functions - render_line and render_hline are the core of -// the algorithm - they calculate the exact coverage of each pixel cell -// of the polygon. I left these functions almost as is, because there's -// no way to improve the perfection - hats off to David and his group! -// -// All other code is very different from the original. -// -//---------------------------------------------------------------------------- - -#include -#include "agg_rasterizer_scanline_aa.h" - - -namespace agg -{ - - //------------------------------------------------------------------------ - inline void cell_aa::set_cover(int c, int a) - { - cover = c; - area = a; - } - - //------------------------------------------------------------------------ - inline void cell_aa::add_cover(int c, int a) - { - cover += c; - area += a; - } - - //------------------------------------------------------------------------ - inline void cell_aa::set_coord(int cx, int cy) - { - x = int16(cx); - y = int16(cy); - packed_coord = (cy << 16) + cx; - } - - //------------------------------------------------------------------------ - inline void cell_aa::set(int cx, int cy, int c, int a) - { - x = int16(cx); - y = int16(cy); - packed_coord = (cy << 16) + cx; - cover = c; - area = a; - } - - //------------------------------------------------------------------------ - outline_aa::~outline_aa() - { - delete [] m_sorted_cells; - if(m_num_blocks) - { - cell_aa** ptr = m_cells + m_num_blocks - 1; - while(m_num_blocks--) - { - delete [] *ptr; - ptr--; - } - delete [] m_cells; - } - } - - - //------------------------------------------------------------------------ - outline_aa::outline_aa() : - m_num_blocks(0), - m_max_blocks(0), - m_cur_block(0), - m_num_cells(0), - m_cells(0), - m_cur_cell_ptr(0), - m_sorted_cells(0), - m_sorted_size(0), - m_cur_x(0), - m_cur_y(0), - m_min_x(0x7FFFFFFF), - m_min_y(0x7FFFFFFF), - m_max_x(-0x7FFFFFFF), - m_max_y(-0x7FFFFFFF), - m_sorted(false) - { - m_cur_cell.set(0x7FFF, 0x7FFF, 0, 0); - } - - - //------------------------------------------------------------------------ - void outline_aa::reset() - { - m_num_cells = 0; - m_cur_block = 0; - m_cur_cell.set(0x7FFF, 0x7FFF, 0, 0); - m_sorted = false; - m_min_x = 0x7FFFFFFF; - m_min_y = 0x7FFFFFFF; - m_max_x = -0x7FFFFFFF; - m_max_y = -0x7FFFFFFF; - } - - - - //------------------------------------------------------------------------ - void outline_aa::allocate_block() - { - if(m_cur_block >= m_num_blocks) - { - if(m_num_blocks >= m_max_blocks) - { - cell_aa** new_cells = new cell_aa* [m_max_blocks + cell_block_pool]; - if(m_cells) - { - memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_aa*)); - delete [] m_cells; - } - m_cells = new_cells; - m_max_blocks += cell_block_pool; - } - m_cells[m_num_blocks++] = new cell_aa [unsigned(cell_block_size)]; - } - m_cur_cell_ptr = m_cells[m_cur_block++]; - } - - - //------------------------------------------------------------------------ - inline void outline_aa::add_cur_cell() - { - if(m_cur_cell.area | m_cur_cell.cover) - { - if((m_num_cells & cell_block_mask) == 0) - { - if(m_num_blocks >= cell_block_limit) return; - allocate_block(); - } - *m_cur_cell_ptr++ = m_cur_cell; - ++m_num_cells; - if(m_cur_cell.x < m_min_x) m_min_x = m_cur_cell.x; - if(m_cur_cell.x > m_max_x) m_max_x = m_cur_cell.x; - } - } - - - - //------------------------------------------------------------------------ - inline void outline_aa::set_cur_cell(int x, int y) - { - if(m_cur_cell.packed_coord != (y << 16) + x) - { - add_cur_cell(); - m_cur_cell.set(x, y, 0, 0); - } - } - - - - //------------------------------------------------------------------------ - inline void outline_aa::render_hline(int ey, int x1, int y1, int x2, int y2) - { - int ex1 = x1 >> poly_base_shift; - int ex2 = x2 >> poly_base_shift; - int fx1 = x1 & poly_base_mask; - int fx2 = x2 & poly_base_mask; - - int delta, p, first, dx; - int incr, lift, mod, rem; - - //trivial case. Happens often - if(y1 == y2) - { - set_cur_cell(ex2, ey); - return; - } - - //everything is located in a single cell. That is easy! - if(ex1 == ex2) - { - delta = y2 - y1; - m_cur_cell.add_cover(delta, (fx1 + fx2) * delta); - return; - } - - //ok, we'll have to render a run of adjacent cells on the same - //hline... - p = (poly_base_size - fx1) * (y2 - y1); - first = poly_base_size; - incr = 1; - - dx = x2 - x1; - - if(dx < 0) - { - p = fx1 * (y2 - y1); - first = 0; - incr = -1; - dx = -dx; - } - - delta = p / dx; - mod = p % dx; - - if(mod < 0) - { - delta--; - mod += dx; - } - - m_cur_cell.add_cover(delta, (fx1 + first) * delta); - - ex1 += incr; - set_cur_cell(ex1, ey); - y1 += delta; - - if(ex1 != ex2) - { - p = poly_base_size * (y2 - y1 + delta); - lift = p / dx; - rem = p % dx; - - if (rem < 0) - { - lift--; - rem += dx; - } - - mod -= dx; - - while (ex1 != ex2) - { - delta = lift; - mod += rem; - if(mod >= 0) - { - mod -= dx; - delta++; - } - - m_cur_cell.add_cover(delta, (poly_base_size) * delta); - y1 += delta; - ex1 += incr; - set_cur_cell(ex1, ey); - } - } - delta = y2 - y1; - m_cur_cell.add_cover(delta, (fx2 + poly_base_size - first) * delta); - } - - - - - - - //------------------------------------------------------------------------ - void outline_aa::render_line(int x1, int y1, int x2, int y2) - { - int ey1 = y1 >> poly_base_shift; - int ey2 = y2 >> poly_base_shift; - int fy1 = y1 & poly_base_mask; - int fy2 = y2 & poly_base_mask; - - int dx, dy, x_from, x_to; - int p, rem, mod, lift, delta, first, incr; - - dx = x2 - x1; - dy = y2 - y1; - - //everything is on a single hline - if(ey1 == ey2) - { - render_hline(ey1, x1, fy1, x2, fy2); - return; - } - - //Vertical line - we have to calculate start and end cells, - //and then - the common values of the area and coverage for - //all cells of the line. We know exactly there's only one - //cell, so, we don't have to call render_hline(). - incr = 1; - if(dx == 0) - { - int ex = x1 >> poly_base_shift; - int two_fx = (x1 - (ex << poly_base_shift)) << 1; - int area; - - first = poly_base_size; - if(dy < 0) - { - first = 0; - incr = -1; - } - - x_from = x1; - - //render_hline(ey1, x_from, fy1, x_from, first); - delta = first - fy1; - m_cur_cell.add_cover(delta, two_fx * delta); - - ey1 += incr; - set_cur_cell(ex, ey1); - - delta = first + first - poly_base_size; - area = two_fx * delta; - while(ey1 != ey2) - { - //render_hline(ey1, x_from, poly_base_size - first, x_from, first); - m_cur_cell.set_cover(delta, area); - ey1 += incr; - set_cur_cell(ex, ey1); - } - //render_hline(ey1, x_from, poly_base_size - first, x_from, fy2); - delta = fy2 - poly_base_size + first; - m_cur_cell.add_cover(delta, two_fx * delta); - return; - } - - //ok, we have to render several hlines - p = (poly_base_size - fy1) * dx; - first = poly_base_size; - - if(dy < 0) - { - p = fy1 * dx; - first = 0; - incr = -1; - dy = -dy; - } - - delta = p / dy; - mod = p % dy; - - if(mod < 0) - { - delta--; - mod += dy; - } - - x_from = x1 + delta; - render_hline(ey1, x1, fy1, x_from, first); - - ey1 += incr; - set_cur_cell(x_from >> poly_base_shift, ey1); - - if(ey1 != ey2) - { - p = poly_base_size * dx; - lift = p / dy; - rem = p % dy; - - if(rem < 0) - { - lift--; - rem += dy; - } - mod -= dy; - - while(ey1 != ey2) - { - delta = lift; - mod += rem; - if (mod >= 0) - { - mod -= dy; - delta++; - } - - x_to = x_from + delta; - render_hline(ey1, x_from, poly_base_size - first, x_to, first); - x_from = x_to; - - ey1 += incr; - set_cur_cell(x_from >> poly_base_shift, ey1); - } - } - render_hline(ey1, x_from, poly_base_size - first, x2, fy2); - } - - - //------------------------------------------------------------------------ - void outline_aa::move_to(int x, int y) - { - if(m_sorted) reset(); - set_cur_cell(x >> poly_base_shift, y >> poly_base_shift); - m_cur_x = x; - m_cur_y = y; - } - - - - //------------------------------------------------------------------------ - void outline_aa::line_to(int x, int y) - { - render_line(m_cur_x, m_cur_y, x, y); - m_cur_x = x; - m_cur_y = y; - m_sorted = false; - } - - - //------------------------------------------------------------------------ - enum - { - qsort_threshold = 9 - }; - - - //------------------------------------------------------------------------ - template static inline void swap_cells(T* a, T* b) - { - T temp = *a; - *a = *b; - *b = temp; - } - - //------------------------------------------------------------------------ - template static inline bool less_than(T* a, T* b) - { - return (*a)->packed_coord < (*b)->packed_coord; - } - - - - //------------------------------------------------------------------------ - void outline_aa::qsort_cells(cell_aa** start, unsigned num) - { - cell_aa** stack[80]; - cell_aa*** top; - cell_aa** limit; - cell_aa** base; - - limit = start + num; - base = start; - top = stack; - - for (;;) - { - int len = int(limit - base); - - cell_aa** i; - cell_aa** j; - cell_aa** pivot; - - if(len > qsort_threshold) - { - // we use base + len/2 as the pivot - pivot = base + len / 2; - swap_cells(base, pivot); - - i = base + 1; - j = limit - 1; - - // now ensure that *i <= *base <= *j - if(less_than(j, i)) - { - swap_cells(i, j); - } - - if(less_than(base, i)) - { - swap_cells(base, i); - } - - if(less_than(j, base)) - { - swap_cells(base, j); - } - - for(;;) - { - do i++; while( less_than(i, base) ); - do j--; while( less_than(base, j) ); - - if ( i > j ) - { - break; - } - - swap_cells(i, j); - } - - swap_cells(base, j); - - // now, push the largest sub-array - if(j - base > limit - i) - { - top[0] = base; - top[1] = j; - base = i; - } - else - { - top[0] = i; - top[1] = limit; - limit = j; - } - top += 2; - } - else - { - // the sub-array is small, perform insertion sort - j = base; - i = j + 1; - - for(; i < limit; j = i, i++) - { - for(; less_than(j + 1, j); j--) - { - swap_cells(j + 1, j); - if (j == base) - { - break; - } - } - } - if(top > stack) - { - top -= 2; - base = top[0]; - limit = top[1]; - } - else - { - break; - } - } - } - } - - - - - - //------------------------------------------------------------------------ - void outline_aa::sort_cells() - { - if(m_num_cells == 0) return; - if(m_num_cells > m_sorted_size) - { - delete [] m_sorted_cells; - m_sorted_size = m_num_cells; - m_sorted_cells = new cell_aa* [m_num_cells + 1]; - } - - cell_aa** sorted_ptr = m_sorted_cells; - cell_aa** block_ptr = m_cells; - cell_aa* cell_ptr; - - unsigned nb = m_num_cells >> cell_block_shift; - unsigned i; - - while(nb--) - { - cell_ptr = *block_ptr++; - i = cell_block_size; - while(i--) - { - *sorted_ptr++ = cell_ptr++; - } - } - - cell_ptr = *block_ptr++; - i = m_num_cells & cell_block_mask; - while(i--) - { - *sorted_ptr++ = cell_ptr++; - } - m_sorted_cells[m_num_cells] = 0; - qsort_cells(m_sorted_cells, m_num_cells); - m_min_y = m_sorted_cells[0]->y; - m_max_y = m_sorted_cells[m_num_cells - 1]->y; - } - - - - - //------------------------------------------------------------------------ - const cell_aa* const* outline_aa::cells() - { - //Perform sort only the first time. - if(!m_sorted) - { - add_cur_cell(); - sort_cells(); - m_sorted = true; - } - return m_sorted_cells; - } - - - - - -} - - - - - diff --git a/agg2/src/agg_vcgen_stroke.cpp b/agg2/src/agg_vcgen_stroke.cpp deleted file mode 100644 index 0c7430e..0000000 --- a/agg2/src/agg_vcgen_stroke.cpp +++ /dev/null @@ -1,420 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// Stroke generator -// -//---------------------------------------------------------------------------- -#include -#include "agg_vcgen_stroke.h" -#include "agg_shorten_path.h" - -namespace agg -{ - - //------------------------------------------------------------------------ - vcgen_stroke::vcgen_stroke() : - m_src_vertices(), - m_out_vertices(), - m_width(0.5), - m_miter_limit(4.0), - m_approx_scale(1.0), - m_shorten(0.0), - m_line_cap(butt_cap), - m_line_join(miter_join), - m_closed(0), - m_status(initial), - m_src_vertex(0), - m_out_vertex(0) - { - } - - - //------------------------------------------------------------------------ - void vcgen_stroke::miter_limit_theta(double t) - { - m_miter_limit = 1.0 / sin(t * 0.5) ; - } - - - //------------------------------------------------------------------------ - void vcgen_stroke::remove_all() - { - m_src_vertices.remove_all(); - m_closed = 0; - m_status = initial; - } - - - //------------------------------------------------------------------------ - void vcgen_stroke::add_vertex(double x, double y, unsigned cmd) - { - m_status = initial; - if(is_move_to(cmd)) - { - m_src_vertices.modify_last(vertex_dist(x, y)); - } - else - { - if(is_vertex(cmd)) - { - m_src_vertices.add(vertex_dist(x, y)); - } - else - { - m_closed = get_close_flag(cmd); - } - } - } - - - //------------------------------------------------------------------------ - void vcgen_stroke::rewind(unsigned) - { - if(m_status == initial) - { - m_src_vertices.close(m_closed != 0); - shorten_path(m_src_vertices, m_shorten, m_closed); - } - m_status = ready; - m_src_vertex = 0; - m_out_vertex = 0; - } - - - //------------------------------------------------------------------------ - unsigned vcgen_stroke::vertex(double* x, double* y) - { - unsigned cmd = path_cmd_line_to; - while(!is_stop(cmd)) - { - switch(m_status) - { - case initial: - rewind(0); - - case ready: - if(m_src_vertices.size() < 2 + unsigned(m_closed != 0)) - { - cmd = path_cmd_stop; - break; - } - m_status = m_closed ? outline1 : cap1; - cmd = path_cmd_move_to; - m_src_vertex = 0; - m_out_vertex = 0; - break; - - case cap1: - calc_cap(m_src_vertices[0], - m_src_vertices[1], - m_src_vertices[0].dist); - m_src_vertex = 1; - m_prev_status = outline1; - m_status = out_vertices; - m_out_vertex = 0; - break; - - case cap2: - calc_cap(m_src_vertices[m_src_vertices.size() - 1], - m_src_vertices[m_src_vertices.size() - 2], - m_src_vertices[m_src_vertices.size() - 2].dist); - m_prev_status = outline2; - m_status = out_vertices; - m_out_vertex = 0; - break; - - case outline1: - if(m_closed) - { - if(m_src_vertex >= m_src_vertices.size()) - { - m_prev_status = close_first; - m_status = end_poly1; - break; - } - } - else - { - if(m_src_vertex >= m_src_vertices.size() - 1) - { - m_status = cap2; - break; - } - } - - calc_join(m_src_vertices.prev(m_src_vertex), - m_src_vertices.curr(m_src_vertex), - m_src_vertices.next(m_src_vertex), - m_src_vertices.prev(m_src_vertex).dist, - m_src_vertices.curr(m_src_vertex).dist); - ++m_src_vertex; - m_prev_status = m_status; - m_status = out_vertices; - m_out_vertex = 0; - break; - - case close_first: - m_status = outline2; - cmd = path_cmd_move_to; - - case outline2: - if(m_src_vertex <= unsigned(m_closed == 0)) - { - m_status = end_poly2; - m_prev_status = stop; - break; - } - - --m_src_vertex; - calc_join(m_src_vertices.next(m_src_vertex), - m_src_vertices.curr(m_src_vertex), - m_src_vertices.prev(m_src_vertex), - m_src_vertices.curr(m_src_vertex).dist, - m_src_vertices.prev(m_src_vertex).dist); - - m_prev_status = m_status; - m_status = out_vertices; - m_out_vertex = 0; - break; - - case out_vertices: - if(m_out_vertex >= m_out_vertices.size()) - { - m_status = m_prev_status; - } - else - { - const coord_type& c = m_out_vertices[m_out_vertex++]; - *x = c.x; - *y = c.y; - return cmd; - } - break; - - case end_poly1: - m_status = m_prev_status; - return path_cmd_end_poly | path_flags_close | path_flags_ccw; - - case end_poly2: - m_status = m_prev_status; - return path_cmd_end_poly | path_flags_close | path_flags_cw; - - case stop: - cmd = path_cmd_stop; - break; - } - } - return cmd; - } - - - - //------------------------------------------------------------------------ - void vcgen_stroke::calc_arc(double x, double y, - double dx1, double dy1, - double dx2, double dy2) - { - double a1 = atan2(dy1, dx1); - double a2 = atan2(dy2, dx2); - double da = a1 - a2; - - if(fabs(da) < vcgen_stroke_theta) - { - m_out_vertices.add(coord_type(x + dx1, y + dy1)); - m_out_vertices.add(coord_type(x + dx2, y + dy2)); - return; - } - - bool ccw = da > 0.0 && da < pi; - - da = fabs(1.0 / (m_width * m_approx_scale)); - if(!ccw) - { - if(a1 > a2) a2 += 2 * pi; - while(a1 < a2) - { - m_out_vertices.add(coord_type(x + cos(a1) * m_width, y + sin(a1) * m_width)); - a1 += da; - } - } - else - { - if(a1 < a2) a2 -= 2 * pi; - while(a1 > a2) - { - m_out_vertices.add(coord_type(x + cos(a1) * m_width, y + sin(a1) * m_width)); - a1 -= da; - } - } - m_out_vertices.add(coord_type(x + dx2, y + dy2)); - } - - - //------------------------------------------------------------------------ - void vcgen_stroke::calc_cap(const vertex_dist& v0, - const vertex_dist& v1, - double len) - { - m_out_vertices.remove_all(); - - double dx1 = m_width * (v1.y - v0.y) / len; - double dy1 = m_width * (v1.x - v0.x) / len; - double dx2 = 0; - double dy2 = 0; - - - if(m_line_cap == square_cap) - { - dx2 = dy1; - dy2 = dx1; - } - - if(m_line_cap == round_cap) - { - double a1 = atan2(dy1, -dx1); - double a2 = a1 + pi; - double da = fabs(1.0 / (m_width * m_approx_scale)); - while(a1 < a2) - { - m_out_vertices.add(coord_type(v0.x + cos(a1) * m_width, - v0.y + sin(a1) * m_width)); - a1 += da; - } - m_out_vertices.add(coord_type(v0.x + dx1, v0.y - dy1)); - } - else - { - m_out_vertices.add(coord_type(v0.x - dx1 - dx2, v0.y + dy1 - dy2)); - m_out_vertices.add(coord_type(v0.x + dx1 - dx2, v0.y - dy1 - dy2)); - } - } - - - - //------------------------------------------------------------------------ - void vcgen_stroke::calc_miter(const vertex_dist& v0, - const vertex_dist& v1, - const vertex_dist& v2, - double dx1, double dy1, - double dx2, double dy2, - bool revert_flag) - { - double xi = v1.x; - double yi = v1.y; - 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)) - { - // The calculation didn't succeed, most probaly - // the the three points lie one straight line - //---------------- - m_out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1)); - } - else - { - double d1 = calc_distance(v1.x, v1.y, xi, yi); - double lim = m_width * m_miter_limit; - if(d1 > lim) - { - // Miter limit exceeded - //------------------------ - if(revert_flag) - { - // For the compatibility with SVG, PDF, etc, - // we use a simple bevel join instead of - // "smart" bevel - //------------------- - m_out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1)); - m_out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2)); - } - else - { - // Smart bevel that cuts the miter at the limit point - //------------------- - d1 = lim / d1; - double x1 = v1.x + dx1; - double y1 = v1.y - dy1; - double x2 = v1.x + dx2; - double y2 = v1.y - dy2; - - x1 += (xi - x1) * d1; - y1 += (yi - y1) * d1; - x2 += (xi - x2) * d1; - y2 += (yi - y2) * d1; - m_out_vertices.add(coord_type(x1, y1)); - m_out_vertices.add(coord_type(x2, y2)); - } - } - else - { - // Inside the miter limit - //--------------------- - m_out_vertices.add(coord_type(xi, yi)); - } - } - } - - - //------------------------------------------------------------------------ - void vcgen_stroke::calc_join(const vertex_dist& v0, - const vertex_dist& v1, - const vertex_dist& v2, - double len1, double len2) - { - double dx1, dy1, dx2, dy2; - - dx1 = m_width * (v1.y - v0.y) / len1; - dy1 = m_width * (v1.x - v0.x) / len1; - - dx2 = m_width * (v2.y - v1.y) / len2; - dy2 = m_width * (v2.x - v1.x) / len2; - - m_out_vertices.remove_all(); - if(m_line_join == miter_join) - { - calc_miter(v0, v1, v2, dx1, dy1, dx2, dy2, m_line_join == miter_join_revert); - } - else - { - if(calc_point_location(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y) > 0.0) - { - calc_miter(v0, v1, v2, dx1, dy1, dx2, dy2, false); - } - else - { - if(m_line_join == round_join) - { - calc_arc(v1.x, v1.y, dx1, -dy1, dx2, -dy2); - } - else - { - if(m_line_join == miter_join_revert) - { - calc_miter(v0, v1, v2, dx1, dy1, dx2, dy2, true); - } - else - { - m_out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1)); - m_out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2)); - } - } - } - } - } - - -} diff --git a/agg2/src/ctrl/agg_scale_ctrl.cpp b/agg2/src/ctrl/agg_scale_ctrl.cpp deleted file mode 100644 index bcc488f..0000000 --- a/agg2/src/ctrl/agg_scale_ctrl.cpp +++ /dev/null @@ -1,302 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// classes scale_ctrl_impl, scale_ctrl -// -//---------------------------------------------------------------------------- - -#include "ctrl/agg_scale_ctrl.h" - -namespace agg -{ - - //------------------------------------------------------------------------ - scale_ctrl_impl::scale_ctrl_impl(double x1, double y1, - double x2, double y2, bool flip_y) : - ctrl(x1, y1, x2, y2, flip_y), - m_border_thickness(1.0), - m_border_extra((y2 - y1) / 2), - m_pdx(0.0), - m_move_what(move_nothing), - m_value1(0.3), - m_value2(0.7), - m_min_d(0.01) - { - calc_box(); - } - - - //------------------------------------------------------------------------ - void scale_ctrl_impl::calc_box() - { - m_xs1 = m_x1 + m_border_thickness; - m_ys1 = m_y1 + m_border_thickness; - m_xs2 = m_x2 - m_border_thickness; - m_ys2 = m_y2 - m_border_thickness; - } - - - //------------------------------------------------------------------------ - void scale_ctrl_impl::border_thickness(double t, double extra) - { - m_border_thickness = t; - m_border_extra = extra; - calc_box(); - } - - - - //------------------------------------------------------------------------ - void scale_ctrl_impl::rewind(unsigned idx) - { - m_idx = idx; - - switch(idx) - { - default: - - case 0: // Background - m_vertex = 0; - m_vx[0] = m_x1 - m_border_extra; - m_vy[0] = m_y1 - m_border_extra; - m_vx[1] = m_x2 + m_border_extra; - m_vy[1] = m_y1 - m_border_extra; - m_vx[2] = m_x2 + m_border_extra; - m_vy[2] = m_y2 + m_border_extra; - m_vx[3] = m_x1 - m_border_extra; - m_vy[3] = m_y2 + m_border_extra; - break; - - case 1: // Border - m_vertex = 0; - m_vx[0] = m_x1; - m_vy[0] = m_y1; - m_vx[1] = m_x2; - m_vy[1] = m_y1; - m_vx[2] = m_x2; - m_vy[2] = m_y2; - m_vx[3] = m_x1; - m_vy[3] = m_y2; - m_vx[4] = m_x1 + m_border_thickness; - m_vy[4] = m_y1 + m_border_thickness; - m_vx[5] = m_x1 + m_border_thickness; - m_vy[5] = m_y2 - m_border_thickness; - m_vx[6] = m_x2 - m_border_thickness; - m_vy[6] = m_y2 - m_border_thickness; - m_vx[7] = m_x2 - m_border_thickness; - m_vy[7] = m_y1 + m_border_thickness; - break; - - case 2: // pointer1 - m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_value1, - (m_ys1 + m_ys2) / 2.0, - m_y2 - m_y1, - m_y2 - m_y1, - 32); - m_ellipse.rewind(0); - break; - - case 3: // pointer2 - m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_value2, - (m_ys1 + m_ys2) / 2.0, - m_y2 - m_y1, - m_y2 - m_y1, - 32); - m_ellipse.rewind(0); - break; - - case 4: // slider - m_vertex = 0; - m_vx[0] = m_xs1 + (m_xs2 - m_xs1) * m_value1; - m_vy[0] = m_y1 - m_border_extra / 2.0; - m_vx[1] = m_xs1 + (m_xs2 - m_xs1) * m_value2; - m_vy[1] = m_vy[0]; - m_vx[2] = m_vx[1]; - m_vy[2] = m_y2 + m_border_extra / 2.0; - m_vx[3] = m_vx[0]; - m_vy[3] = m_vy[2]; - break; - } - } - - - //------------------------------------------------------------------------ - unsigned scale_ctrl_impl::vertex(double* x, double* y) - { - unsigned cmd = path_cmd_line_to; - switch(m_idx) - { - case 0: - case 4: - if(m_vertex == 0) cmd = path_cmd_move_to; - if(m_vertex >= 4) cmd = path_cmd_stop; - *x = m_vx[m_vertex]; - *y = m_vy[m_vertex]; - m_vertex++; - break; - - case 1: - if(m_vertex == 0 || m_vertex == 4) cmd = path_cmd_move_to; - if(m_vertex >= 8) cmd = path_cmd_stop; - *x = m_vx[m_vertex]; - *y = m_vy[m_vertex]; - m_vertex++; - break; - - case 2: - case 3: - cmd = m_ellipse.vertex(x, y); - break; - - default: - cmd = path_cmd_stop; - break; - } - - if(!is_stop(cmd)) - { - transform_xy(x, y); - } - - return cmd; - } - - - - //------------------------------------------------------------------------ - bool scale_ctrl_impl::in_rect(double x, double y) const - { - inverse_transform_xy(&x, &y); - return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2; - } - - - //------------------------------------------------------------------------ - bool scale_ctrl_impl::on_mouse_button_down(double x, double y) - { - inverse_transform_xy(&x, &y); - - double xp1 = m_xs1 + (m_xs2 - m_xs1) * m_value1; - double xp2 = m_xs1 + (m_xs2 - m_xs1) * m_value2; - double ys1 = m_y1 - m_border_extra / 2.0; - double ys2 = m_y2 + m_border_extra / 2.0; - double yp = (m_ys1 + m_ys2) / 2.0; - - if(x > xp1 && y > ys1 && x < xp2 && y < ys2) - { - m_pdx = xp1 - x; - m_move_what = move_slider; - return true; - } - - if(x < xp1 && calc_distance(x, y, xp1, yp) <= m_y2 - m_y1) - { - m_pdx = xp1 - x; - m_move_what = move_value1; - return true; - } - - if(x > xp2 && calc_distance(x, y, xp2, yp) <= m_y2 - m_y1) - { - m_pdx = xp2 - x; - m_move_what = move_value2; - return true; - } - - - return false; - } - - - //------------------------------------------------------------------------ - bool scale_ctrl_impl::on_mouse_move(double x, double y, bool button_flag) - { - inverse_transform_xy(&x, &y); - if(!button_flag) - { - return on_mouse_button_up(x, y); - } - - double xp = x + m_pdx; - double dv; - - switch(m_move_what) - { - case move_value1: - m_value1 = (xp - m_xs1) / (m_xs2 - m_xs1); - if(m_value1 < 0.0) m_value1 = 0.0; - if(m_value1 > m_value2 - m_min_d) m_value1 = m_value2 - m_min_d; - return true; - - case move_value2: - m_value2 = (xp - m_xs1) / (m_xs2 - m_xs1); - if(m_value2 > 1.0) m_value2 = 1.0; - if(m_value2 < m_value1 + m_min_d) m_value2 = m_value1 + m_min_d; - return true; - - case move_slider: - dv = m_value2 - m_value1; - m_value1 = (xp - m_xs1) / (m_xs2 - m_xs1); - m_value2 = m_value1 + dv; - if(m_value1 < 0.0) - { - dv = m_value2 - m_value1; - m_value1 = 0.0; - m_value2 = m_value1 + dv; - } - if(m_value2 > 1.0) - { - dv = m_value2 - m_value1; - m_value2 = 1.0; - m_value1 = m_value2 - dv; - } - return true; - } - - return false; - } - - - //------------------------------------------------------------------------ - bool scale_ctrl_impl::on_mouse_button_up(double, double) - { - m_move_what = move_nothing; - return false; - } - - - //------------------------------------------------------------------------ - bool scale_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up) - { -/* - if(right || up) - { - m_value += 0.005; - if(m_value > 1.0) m_value = 1.0; - return true; - } - - if(left || down) - { - m_value -= 0.005; - if(m_value < 0.0) m_value = 0.0; - return true; - } -*/ - return false; - } - -} - diff --git a/agg2/src/dbg_new/agg_dbg_new.cpp b/agg2/src/dbg_new/agg_dbg_new.cpp deleted file mode 100644 index 3b5d5fa..0000000 --- a/agg2/src/dbg_new/agg_dbg_new.cpp +++ /dev/null @@ -1,538 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// Debuging stuff for catching memory leaks and corruptions -// -//---------------------------------------------------------------------------- -#include -#include -#include -#include -#include "dbg_new/agg_dbg_new.h" - -namespace agg -{ - - int dbg_new_level = -1; - - struct dbg_new - { - unsigned new_count; - unsigned del_count; - unsigned new_bytes; - unsigned del_bytes; - unsigned max_count; - unsigned max_bytes; - unsigned corrupted_count; - char file_name[512]; - int line; - bool report_all; - }; - - dbg_new dbg_new_info[max_dbg_new_level] = - { - { 0, 0, 0, 0, 0, 0, 0, "", 0, false }, - }; - -#ifdef AGG_DBG_NEW_CHECK_ADDR - void* dbg_new_allocations[max_allocations] = - { - 0, - }; - unsigned dbg_new_prev_word[max_allocations] = - { - 0, - }; - - - unsigned dbg_new_max_count = 0; -#endif - - - //------------------------------------------------------------------------ - void add_allocated_addr(void* ptr) - { -#ifdef AGG_DBG_NEW_CHECK_ADDR - if(dbg_new_max_count >= max_allocations) - { - printf("ADDR_CHECK: limit exceeded\n"); - } - dbg_new_allocations[dbg_new_max_count] = ptr; - memcpy(dbg_new_prev_word + dbg_new_max_count, - ((char*)ptr) - sizeof(unsigned), - sizeof(unsigned)); - dbg_new_max_count++; -#endif - } - - - //------------------------------------------------------------------------ - bool check_and_remove_allocated_addr(void* ptr) - { -#ifdef AGG_DBG_NEW_CHECK_ADDR - unsigned i; - for(i = 0; i < dbg_new_max_count; i++) - { - if(dbg_new_allocations[i] == ptr) - { - unsigned prev; - memcpy(&prev, - ((char*)ptr) - sizeof(unsigned), - sizeof(unsigned)); - - if(prev != dbg_new_prev_word[i]) - { - printf("MEMORY CORRUPTION AT %08x prev=%08x cur=%08x\n", ptr, prev, dbg_new_prev_word[i]); - //return false; - } - - if(i < dbg_new_max_count - 1) - { - memmove(dbg_new_allocations + i, - dbg_new_allocations + i + 1, - sizeof(void*) * dbg_new_max_count - i - 1); - } - dbg_new_max_count--; - //printf("free ok\n"); - return true; - } - } - printf("ATTEMPT TO FREE BAD ADDRESS %08x\n", ptr); - return false; -#else - return true; -#endif - } - - - //------------------------------------------------------------------------ - watchdoggy::watchdoggy(const char* file, int line, bool report_all) - { - #ifdef _WIN32 - if(dbg_new_level == -1) - { - FILE* fd = fopen("stdout.txt", "wt"); - fclose(fd); - } - #endif - - dbg_new_level++; - ::memset(dbg_new_info + dbg_new_level, 0, sizeof(dbg_new)); - if(file == 0) file = ""; - int len = strlen(file); - if(len > 511) len = 511; - ::memcpy(dbg_new_info[dbg_new_level].file_name, file, len); - dbg_new_info[dbg_new_level].file_name[len] = 0; - dbg_new_info[dbg_new_level].line = line; - dbg_new_info[dbg_new_level].report_all = report_all; - printf("wd%d started. File:%s line:%d\n", - dbg_new_level, - file, - line); - } - - - //------------------------------------------------------------------------ - watchdoggy::~watchdoggy() - { - if(dbg_new_level >= 0) - { - printf("wd%d stopped. File:%s line:%d\n", - dbg_new_level, - dbg_new_info[dbg_new_level].file_name, - dbg_new_info[dbg_new_level].line); - printf("new_count=%u del_count=%u max_count=%u balance=%d\n" - "new_bytes=%u del_bytes=%u max_bytes=%u balance=%d " - "corrupted_count=%u\n", - dbg_new_info[dbg_new_level].new_count, - dbg_new_info[dbg_new_level].del_count, - dbg_new_info[dbg_new_level].max_count, - int(dbg_new_info[dbg_new_level].new_count - - dbg_new_info[dbg_new_level].del_count), - dbg_new_info[dbg_new_level].new_bytes, - dbg_new_info[dbg_new_level].del_bytes, - dbg_new_info[dbg_new_level].max_bytes, - int(dbg_new_info[dbg_new_level].new_bytes - - dbg_new_info[dbg_new_level].del_bytes), - dbg_new_info[dbg_new_level].corrupted_count - ); - dbg_new_level--; - } - } - - - //------------------------------------------------------------------------ - // - // This code implements the AUTODIN II polynomial - // The variable corresponding to the macro argument "crc" should - // be an unsigned long. - // Oroginal code by Spencer Garrett - // - // generated using the AUTODIN II polynomial - // x^32 + x^26 + x^23 + x^22 + x^16 + - // x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1 - // - //------------------------------------------------------------------------ - static const unsigned crc32tab[256] = - { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, - 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, - 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, - 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, - 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, - 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, - 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, - 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, - 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, - 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, - - 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, - 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, - 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, - 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, - 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, - 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, - 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, - 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, - 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, - 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, - - 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, - 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, - 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, - 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, - 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, - 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, - 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, - 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, - 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, - 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, - 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, - 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, - 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, - 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, - 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, - 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, - 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, - 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d - }; - - - //------------------------------------------------------------------------ - static unsigned long calcCRC32(const char* buf, unsigned size) - { - unsigned long crc = (unsigned long)~0; - const char* p; - unsigned len = 0; - unsigned nr = size; - - for (len += nr, p = buf; nr--; ++p) - { - crc = (crc >> 8) ^ crc32tab[(crc ^ *p) & 0xff]; - } - return ~crc; - } - - - - - - //------------------------------------------------------------------------ - void* dbg_malloc(unsigned size, const char* file, int line) - { - if(dbg_new_level < 0) - { - void* ptr = ::malloc(size); - printf("%u allocated at %08x %s %d\n", size, ptr, file, line); - add_allocated_addr(ptr); - return ptr; - } - - // The structure of the allocated memory: - // - // [USER_SIZE:16 bytes] //allows for keeping proper data alignment - // [USER_MEM] - // [CRC32_sum:long, actual size depends on architecture] - // [test_bytes:256 bytes] //should be enough for checking non-fatal - // //corruptions with keeping the line number - // //and filename correct - // [line:unsigned] - // [strlen:unsigned] - // [file_name:zero_end_string] - - unsigned fname_len = ::strlen(file) + 1; - unsigned total_size = 16 + // size - size + // user_mem - sizeof(unsigned long) + // crc32 - 256 + // zero_bytes - sizeof(unsigned) + // line - sizeof(unsigned) + // strlen - fname_len; // .cpp file_name - - char* inf_ptr = (char*)::malloc(total_size); - char* ret_ptr = inf_ptr + 16; - - int i; - for(i = 0; i < 16; i++) - { - inf_ptr[i] = (char)(15-i); - } - ::memcpy(inf_ptr, &size, sizeof(unsigned)); - - unsigned long crc32_before = calcCRC32(inf_ptr, 16); - - inf_ptr += 16 + size; - char* crc32_ptr = inf_ptr; - inf_ptr += sizeof(unsigned long); - - for(i = 0; i < 256; i++) - { - *inf_ptr++ = (char)(255-i); - } - - ::memcpy(inf_ptr, &line, sizeof(unsigned)); - inf_ptr += sizeof(unsigned); - - ::memcpy(inf_ptr, &fname_len, sizeof(unsigned)); - inf_ptr += sizeof(unsigned); - - ::strcpy(inf_ptr, file); - - unsigned long // long just in case - crc32_sum = calcCRC32(crc32_ptr + sizeof(unsigned long), - 256 + - sizeof(unsigned) + - sizeof(unsigned) + - fname_len); - - crc32_sum ^= crc32_before; - - ::memcpy(crc32_ptr, &crc32_sum, sizeof(unsigned long)); - - dbg_new_info[dbg_new_level].new_count++; - dbg_new_info[dbg_new_level].new_bytes += size; - int balance = int(dbg_new_info[dbg_new_level].new_count - - dbg_new_info[dbg_new_level].del_count); - - if(balance > 0) - { - if(balance > int(dbg_new_info[dbg_new_level].max_count)) - { - dbg_new_info[dbg_new_level].max_count = unsigned(balance); - } - } - - - balance = int(dbg_new_info[dbg_new_level].new_bytes - - dbg_new_info[dbg_new_level].del_bytes); - - if(balance > 0) - { - if(balance > int(dbg_new_info[dbg_new_level].max_bytes)) - { - dbg_new_info[dbg_new_level].max_bytes = unsigned(balance); - } - } - - - if(dbg_new_info[dbg_new_level].report_all) - { - printf("wdl%d. %u allocated %08x. %s, %d\n", - dbg_new_level, - size, - ret_ptr, - file, - line - ); - } - - add_allocated_addr(ret_ptr); - return ret_ptr; - } - - - - //------------------------------------------------------------------------ - void dbg_free(void* ptr) - { - if(ptr == 0) - { - //printf("Null pointer free\n"); - return; - } - - if(!check_and_remove_allocated_addr(ptr)) return; - - if(dbg_new_level < 0) - { - printf("free at %08x\n", ptr); - ::free(ptr); - return; - } - - char* free_ptr = (char*)ptr; - char* inf_ptr = free_ptr; - free_ptr -= 16; - - unsigned size; - ::memcpy(&size, free_ptr, sizeof(unsigned)); - - unsigned long crc32_before = calcCRC32(free_ptr, 16); - - inf_ptr += size; - unsigned long crc32_sum; - ::memcpy(&crc32_sum, inf_ptr, sizeof(unsigned long)); - inf_ptr += sizeof(unsigned long); - char* crc32_ptr = inf_ptr; - - inf_ptr += 256; - - unsigned line; - ::memcpy(&line, inf_ptr, sizeof(unsigned)); - inf_ptr += sizeof(unsigned); - - unsigned fname_len; - ::memcpy(&fname_len, inf_ptr, sizeof(unsigned)); - inf_ptr += sizeof(unsigned); - - char file[512]; - if(fname_len > 511) fname_len = 511; - ::memcpy(file, inf_ptr, fname_len); - file[fname_len] = 0; - - if(crc32_sum != (calcCRC32(crc32_ptr, - 256 + - sizeof(unsigned) + - sizeof(unsigned) + - fname_len) ^ crc32_before)) - { - printf("WD%d:MEMORY CORRUPTION AT %08x. Allocated %u bytes in %s, line %d\n", - dbg_new_level, - ptr, - size, - file, - line); - dbg_new_info[dbg_new_level].corrupted_count++; - } - else - { - ::free(free_ptr); - - dbg_new_info[dbg_new_level].del_count++; - dbg_new_info[dbg_new_level].del_bytes += size; - - if(dbg_new_info[dbg_new_level].report_all) - { - printf("wdl%d. %u freed %08x. %s, %d\n", - dbg_new_level, - size, - free_ptr, - file, - line - ); - } - } - } -} - -#ifdef new -#undef new -#endif - -//---------------------------------------------------------------------------- -void* operator new (unsigned size, const char* file, int line) -{ - return agg::dbg_malloc(size, file, line); -} - -//---------------------------------------------------------------------------- -void* operator new [] (unsigned size, const char* file, int line) -{ - return agg::dbg_malloc(size, file, line); -} - -//---------------------------------------------------------------------------- -void operator delete(void *ptr) throw() -{ - agg::dbg_free(ptr); -} - -//---------------------------------------------------------------------------- -void operator delete [] (void *ptr) throw() -{ - agg::dbg_free(ptr); -} - - - - - - - - - - - - - - -/* -#include "dbg_new/agg_dbg_new.h" - -int main() -{ - AGG_WATCHDOGGY(wd1, true); - int* a = new int[100]; - a[100] = 0; - - delete [] a; - return 0; -} -*/ - - - - - - - - diff --git a/agg2/src/platform/BeOS/agg_platform_support.cpp b/agg2/src/platform/BeOS/agg_platform_support.cpp deleted file mode 100644 index 2761f09..0000000 --- a/agg2/src/platform/BeOS/agg_platform_support.cpp +++ /dev/null @@ -1,841 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.2 -// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: superstippi@gmx.de -//---------------------------------------------------------------------------- -// -// class platform_support -// -//---------------------------------------------------------------------------- - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "platform/agg_platform_support.h" -#include "util/agg_color_conv_rgb8.h" - -class AGGView : public BView { - public: - AGGView(BRect frame, agg::platform_support* agg, agg::pix_format_e format, bool flipY) - : BView(frame, "AGG View", B_FOLLOW_ALL, - B_FRAME_EVENTS | B_WILL_DRAW), - fAGG(agg), - fFormat(format), - fFlipY(flipY), - fRedraw(true), - fPulse(NULL), - fLastPulse(0), - fEnableTicks(true) - { - SetViewColor(B_TRANSPARENT_32_BIT); - - frame.OffsetTo(0.0, 0.0); - fBitmap = new BBitmap(frame, 0, B_RGBA32); - if (fBitmap->IsValid()) { - memset(fBitmap->Bits(), 0, fBitmap->BitsLength()); - fAGG->rbuf_window().attach((uint8*)fBitmap->Bits(), - fBitmap->Bounds().IntegerWidth() + 1, - fBitmap->Bounds().IntegerHeight() + 1, - fFlipY ? -fBitmap->BytesPerRow() : fBitmap->BytesPerRow()); - } else { - delete fBitmap; - fBitmap = NULL; - } - } - - virtual ~AGGView() - { - delete fBitmap; - delete fPulse; - } - - virtual void AttachedToWindow() - { - BMessage message('tick'); - BMessenger target(this, Looper()); - delete fPulse; -// BScreen screen; -// TODO: calc screen retrace - fPulse = new BMessageRunner(target, &message, 40000); - - // make sure we call this once - fAGG->on_resize(Bounds().IntegerWidth() + 1, - Bounds().IntegerHeight() + 1); - } - virtual void DetachedFromWindow() - { - delete fPulse; - fPulse = NULL; - } - - virtual void MessageReceived(BMessage* message) - { - bigtime_t now = system_time(); - switch (message->what) { - case 'tick': - // drop messages that have piled up - if (/*now - fLastPulse > 30000*/fEnableTicks) { - fLastPulse = now; - if (!fAGG->wait_mode()) - fAGG->on_idle(); - Window()->PostMessage('entk', this); - fEnableTicks = false; - } else { -// fprintf(stderr, "dropping tick message (%lld)\n", now - fLastPulse); - } - break; - case 'entk': - fEnableTicks = true; - if (now - fLastPulse > 30000) { - fLastPulse = now; - if (!fAGG->wait_mode()) - fAGG->on_idle(); - } - break; - default: - BView::MessageReceived(message); - break; - } - } - - virtual void Draw(BRect updateRect) - { - if (fBitmap) { - if (fRedraw) { - fAGG->on_draw(); - fRedraw = false; - } - if (fFormat == agg::pix_format_bgra32) { - DrawBitmap(fBitmap, updateRect, updateRect); - } else { - BBitmap* bitmap = new BBitmap(fBitmap->Bounds(), 0, B_RGBA32); - - agg::rendering_buffer rbuf_src; - rbuf_src.attach((uint8*)fBitmap->Bits(), - fBitmap->Bounds().IntegerWidth() + 1, - fBitmap->Bounds().IntegerHeight() + 1, - fFlipY ? -fBitmap->BytesPerRow() : fBitmap->BytesPerRow()); - - agg::rendering_buffer rbuf_dst; - rbuf_dst.attach((uint8*)bitmap->Bits(), - bitmap->Bounds().IntegerWidth() + 1, - bitmap->Bounds().IntegerHeight() + 1, - fFlipY ? -bitmap->BytesPerRow() : bitmap->BytesPerRow()); - switch(fFormat) { - case agg::pix_format_rgb555: agg::color_conv(&rbuf_dst, &rbuf_src, agg::color_conv_rgb555_to_bgra32()); break; - case agg::pix_format_rgb565: agg::color_conv(&rbuf_dst, &rbuf_src, agg::color_conv_rgb565_to_bgra32()); break; - case agg::pix_format_rgb24: agg::color_conv(&rbuf_dst, &rbuf_src, agg::color_conv_rgb24_to_bgra32()); break; - case agg::pix_format_bgr24: agg::color_conv(&rbuf_dst, &rbuf_src, agg::color_conv_bgr24_to_bgra32()); break; - case agg::pix_format_rgba32: agg::color_conv(&rbuf_dst, &rbuf_src, agg::color_conv_rgba32_to_bgra32()); break; - case agg::pix_format_argb32: agg::color_conv(&rbuf_dst, &rbuf_src, agg::color_conv_argb32_to_bgra32()); break; - case agg::pix_format_abgr32: agg::color_conv(&rbuf_dst, &rbuf_src, agg::color_conv_abgr32_to_bgra32()); break; - case agg::pix_format_bgra32: agg::color_conv(&rbuf_dst, &rbuf_src, agg::color_conv_bgra32_to_bgra32()); break; - } - DrawBitmap(bitmap, updateRect, updateRect); - delete bitmap; - } - } else { - FillRect(updateRect); - } - } - - virtual void FrameResized(float width, float height) - { - delete fBitmap; - BRect r(0.0, 0.0, width, height); - fBitmap = new BBitmap(r, 0, B_RGBA32); - if (!fBitmap->IsValid()) { - delete fBitmap; - fBitmap = NULL; - } else { - fAGG->rbuf_window().attach((uint8*)fBitmap->Bits(), - fBitmap->Bounds().IntegerWidth() + 1, - fBitmap->Bounds().IntegerHeight() + 1, - fFlipY ? -fBitmap->BytesPerRow() : fBitmap->BytesPerRow()); - - fAGG->trans_affine_resizing((int)width + 1, - (int)height + 1); - - // pass the event on to AGG - fAGG->on_resize((int)width + 1, - (int)height + 1); - - fRedraw = true; - Invalidate(); - } - } - - virtual void KeyDown(const char* bytes, int32 numBytes) - { - if (bytes && numBytes > 0) { - fLastKeyDown = bytes[0]; - - bool left = false; - bool up = false; - bool right = false; - bool down = false; - - switch (fLastKeyDown) { - - case B_LEFT_ARROW: - left = true; - break; - - case B_UP_ARROW: - up = true; - break; - - case B_RIGHT_ARROW: - right = true; - break; - - case B_DOWN_ARROW: - down = true; - break; - } - -/* case key_f2: - fAGG->copy_window_to_img(agg::platform_support::max_images - 1); - fAGG->save_img(agg::platform_support::max_images - 1, "screenshot"); - break; - }*/ - - - if (fAGG->m_ctrls.on_arrow_keys(left, right, down, up)) { - fAGG->on_ctrl_change(); - fAGG->force_redraw(); - } else { - fAGG->on_key(fMouseX, fMouseY, fLastKeyDown, GetKeyFlags()); - } -// fAGG->on_key(fMouseX, fMouseY, fLastKeyDown, GetKeyFlags()); - - } - } - virtual void MouseDown(BPoint where) - { - BMessage* currentMessage = Window()->CurrentMessage(); - if (currentMessage) { - if (currentMessage->FindInt32("buttons", (int32*)&fMouseButtons) < B_OK) - fMouseButtons = B_PRIMARY_MOUSE_BUTTON; - } else - fMouseButtons = B_PRIMARY_MOUSE_BUTTON; - - fMouseX = (int)where.x; - fMouseY = fFlipY ? (int)(Bounds().Height() - where.y) : (int)where.y; - - // pass the event on to AGG - if (fMouseButtons == B_PRIMARY_MOUSE_BUTTON) { - // left mouse button -> see if to handle in controls - fAGG->m_ctrls.set_cur(fMouseX, fMouseY); - if (fAGG->m_ctrls.on_mouse_button_down(fMouseX, fMouseY)) { - fAGG->on_ctrl_change(); - fAGG->force_redraw(); - } else { - if (fAGG->m_ctrls.in_rect(fMouseX, fMouseY)) { - if (fAGG->m_ctrls.set_cur(fMouseX, fMouseY)) { - fAGG->on_ctrl_change(); - fAGG->force_redraw(); - } - } else { - fAGG->on_mouse_button_down(fMouseX, fMouseY, GetKeyFlags()); - } - } - } else if (fMouseButtons & B_SECONDARY_MOUSE_BUTTON) { - // right mouse button -> simple - fAGG->on_mouse_button_down(fMouseX, fMouseY, GetKeyFlags()); - } - SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); - } - virtual void MouseMoved(BPoint where, uint32 transit, const BMessage* dragMesage) - { - // workarround missed mouse up events - // (if we react too slowly, app_server might have dropped events) - BMessage* currentMessage = Window()->CurrentMessage(); - int32 buttons = 0; - if (currentMessage->FindInt32("buttons", &buttons) < B_OK) { - buttons = 0; - } - if (!buttons) - MouseUp(where); - - fMouseX = (int)where.x; - fMouseY = fFlipY ? (int)(Bounds().Height() - where.y) : (int)where.y; - - // pass the event on to AGG - if (fAGG->m_ctrls.on_mouse_move(fMouseX, fMouseY, - (GetKeyFlags() & agg::mouse_left) != 0)) { - fAGG->on_ctrl_change(); - fAGG->force_redraw(); - } else { - if (!fAGG->m_ctrls.in_rect(fMouseX, fMouseY)) { - fAGG->on_mouse_move(fMouseX, fMouseY, GetKeyFlags()); - } - } - } - - virtual void MouseUp(BPoint where) - { - fMouseX = (int)where.x; - fMouseY = fFlipY ? (int)(Bounds().Height() - where.y) : (int)where.y; - - // pass the event on to AGG - if (fMouseButtons == B_PRIMARY_MOUSE_BUTTON) { - fMouseButtons = 0; - - if (fAGG->m_ctrls.on_mouse_button_up(fMouseX, fMouseY)) { - fAGG->on_ctrl_change(); - fAGG->force_redraw(); - } - fAGG->on_mouse_button_up(fMouseX, fMouseY, GetKeyFlags()); - } else if (fMouseButtons == B_SECONDARY_MOUSE_BUTTON) { - fMouseButtons = 0; - - fAGG->on_mouse_button_up(fMouseX, fMouseY, GetKeyFlags()); - } - } - - BBitmap* Bitmap() const - { - return fBitmap; - } - - uint8 LastKeyDown() const - { - return fLastKeyDown; - } - uint32 MouseButtons() - { - uint32 buttons = 0; - if (LockLooper()) { - buttons = fMouseButtons; - UnlockLooper(); - } - return buttons; - } - - void Update() - { - // trigger display update - if (LockLooper()) { - Invalidate(); - UnlockLooper(); - } - } - - void ForceRedraw() - { - // force a redraw (fRedraw = true;) - // and trigger display update - if (LockLooper()) { - fRedraw = true; - Invalidate(); - UnlockLooper(); - } - } - - unsigned GetKeyFlags() - { - uint32 buttons = fMouseButtons; - uint32 mods = modifiers(); - unsigned flags = 0; - if (buttons & B_PRIMARY_MOUSE_BUTTON) flags |= agg::mouse_left; - if (buttons & B_SECONDARY_MOUSE_BUTTON) flags |= agg::mouse_right; - if (mods & B_SHIFT_KEY) flags |= agg::kbd_shift; - if (mods & B_COMMAND_KEY) flags |= agg::kbd_ctrl; - return flags; - } - - private: - BBitmap* fBitmap; - uint8 fLastKeyDown; - agg::platform_support* fAGG; - agg::pix_format_e fFormat; - - uint32 fMouseButtons; - int32 fMouseX; - int32 fMouseY; - bool fFlipY; - bool fRedraw; - BMessageRunner* fPulse; - bigtime_t fLastPulse; - bool fEnableTicks; -}; - -class AGGWindow : public BWindow { - public: - AGGWindow() - : BWindow(BRect(-50.0, -50.0, -10.0, -10.0), - "AGG Application", B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS) - { - } - - virtual bool QuitRequested() - { - be_app->PostMessage(B_QUIT_REQUESTED); - return true; - } - - bool Init(BRect frame, agg::platform_support* agg, agg::pix_format_e format, - bool flipY, uint32 flags) - { - MoveTo(frame.LeftTop()); - ResizeTo(frame.Width(), frame.Height()); - - SetFlags(flags); - - frame.OffsetTo(0.0, 0.0); - fView = new AGGView(frame, agg, format, flipY); - AddChild(fView); - - return fView->Bitmap() != NULL; - } - - - AGGView* View() const - { - return fView; - } - private: - AGGView* fView; -}; - -class AGGApplication : public BApplication { - public: - AGGApplication() - : BApplication("application/x-vnd.AGG-AGG") - { - fWindow = new AGGWindow(); - } - - virtual void ReadyToRun() - { - if (fWindow) { - fWindow->Show(); - } - } - - virtual bool Init(agg::platform_support* agg, int width, int height, - agg::pix_format_e format, bool flipY, uint32 flags) - { - // ignore flip_y for now - BRect r(50.0, 50.0, - 50.0 + width - 1.0, - 50.0 + height - 1.0); - uint32 windowFlags = B_ASYNCHRONOUS_CONTROLS; - if (!(flags & agg::window_resize)) - windowFlags |= B_NOT_RESIZABLE; - - return fWindow->Init(r, agg, format, flipY, windowFlags);; - } - - - AGGWindow* Window() const - { - return fWindow; - } - - private: - AGGWindow* fWindow; -}; - -namespace agg -{ - -class platform_specific { - public: - platform_specific(agg::platform_support* agg, - agg::pix_format_e format, bool flip_y) - : fAGG(agg), - fApp(NULL), - fFormat(format), - fFlipY(flip_y), - fTimerStart(system_time()) - { - memset(fImages, 0, sizeof(fImages)); - fApp = new AGGApplication(); - } - ~platform_specific() - { - for (int32 i = 0; i < agg::platform_support::max_images; i++) - delete fImages[i]; - delete fApp; - } - - bool Init(int width, int height, unsigned flags) - { - return fApp->Init(fAGG, width, height, fFormat, fFlipY, flags); - } - - int Run() - { - status_t ret = B_NO_INIT; - if (fApp) { - fApp->Run(); - ret = B_OK; - } - return ret; - } - - void SetTitle(const char* title) - { - if (fApp && fApp->Window() && fApp->Window()->Lock()) { - fApp->Window()->SetTitle(title); - fApp->Window()->Unlock(); - } - } - void StartTimer() - { - fTimerStart = system_time(); - } - double ElapsedTime() const - { - return (system_time() - fTimerStart) / 1000.0; - } - - void ForceRedraw() - { - fApp->Window()->View()->ForceRedraw(); - } - void UpdateWindow() - { - fApp->Window()->View()->Update(); - } - - - agg::platform_support* fAGG; - AGGApplication* fApp; - agg::pix_format_e fFormat; - bool fFlipY; - bigtime_t fTimerStart; - BBitmap* fImages[agg::platform_support::max_images]; -}; - - - //------------------------------------------------------------------------ - platform_support::platform_support(pix_format_e format, bool flip_y) : - m_specific(new platform_specific(this, format, flip_y)), - m_format(format), - m_bpp(32/*m_specific->m_bpp*/), - m_window_flags(0), - m_wait_mode(true), - m_flip_y(flip_y), - m_initial_width(10), - m_initial_height(10) - { - strcpy(m_caption, "Anti-Grain Geometry Application"); - } - - - //------------------------------------------------------------------------ - platform_support::~platform_support() - { - delete m_specific; - } - - //------------------------------------------------------------------------ - void platform_support::caption(const char* cap) - { - strcpy(m_caption, cap); - m_specific->SetTitle(cap); - } - - //------------------------------------------------------------------------ - void platform_support::start_timer() - { - m_specific->StartTimer(); - } - - //------------------------------------------------------------------------ - double platform_support::elapsed_time() const - { - return m_specific->ElapsedTime(); - } - - //------------------------------------------------------------------------ - void* platform_support::raw_display_handler() - { - return NULL;//m_specific->m_current_dc; - } - - //------------------------------------------------------------------------ - void platform_support::message(const char* msg) - { - BAlert* alert = new BAlert("AGG Message", msg, "Ok"); - alert->Go(/*NULL*/); - } - - //------------------------------------------------------------------------ - bool platform_support::init(unsigned width, unsigned height, unsigned flags) - { - bool success = m_specific->Init(width, height, flags); - - m_window_flags = flags; - -// m_specific->create_pmap(width, height, &m_rbuf_window); - m_initial_width = width; - m_initial_height = height; - on_init(); -// m_specific->m_redraw_flag = true; - return true; - } - - - - //------------------------------------------------------------------------ - int platform_support::run() - { - return m_specific->Run(); - } - - - //------------------------------------------------------------------------ - const char* platform_support::img_ext() const { return ""; } - - //------------------------------------------------------------------------ - // TO DO: Stephan, please fix it. Place the buffer in - // struct platform_specific. I think it's enough to allocate it - // as an array, somewhat like char m_full_path[MAX_PATH]; - const char* platform_support::full_file_name(const char* file_name) - { - return file_name; - } - - - //------------------------------------------------------------------------ - bool platform_support::load_img(unsigned idx, const char* file) - { - if (idx < max_images) - { - // figure out where we're running from - app_info info; - status_t ret = be_roster->GetRunningAppInfo(be_app->Team(), &info); - if (ret < B_OK) { - fprintf(stderr, "GetRunningAppInfo() failed: %s\n", strerror(ret)); - return false; - } - BPath path(&info.ref); - ret = path.InitCheck(); - if (ret < B_OK) { - fprintf(stderr, "making path failed: %s\n", strerror(ret)); - return false; - } - ret = path.GetParent(&path); - if (ret < B_OK) { - fprintf(stderr, "getting parent folder failed: %s\n", strerror(ret)); - return false; - } - ret = path.Append(file); - if (ret < B_OK) { - fprintf(stderr, "appending image file name failed: %s\n", strerror(ret)); - return false; - } - BBitmap* transBitmap = BTranslationUtils::GetBitmap(path.Path()); - if (transBitmap && transBitmap->IsValid()) { - if(transBitmap->ColorSpace() != B_RGB32 && transBitmap->ColorSpace() != B_RGBA32) { - // ups we got a smart ass Translator making our live harder - delete transBitmap; - return false; - } - - color_space format = B_RGB24; - - switch (m_format) { - case pix_format_gray8: - format = B_GRAY8; - break; - case pix_format_rgb555: - format = B_RGB15; - break; - case pix_format_rgb565: - format = B_RGB16; - break; - case pix_format_rgb24: - format = B_RGB24_BIG; - break; - case pix_format_bgr24: - format = B_RGB24; - break; - case pix_format_abgr32: - case pix_format_argb32: - case pix_format_bgra32: - format = B_RGB32; - break; - case pix_format_rgba32: - format = B_RGB32_BIG; - break; - } - BBitmap* bitmap = new BBitmap(transBitmap->Bounds(), 0, format); - if (!bitmap || !bitmap->IsValid()) { - fprintf(stderr, "failed to allocate temporary bitmap!\n"); - delete transBitmap; - delete bitmap; - return false; - } - - delete m_specific->fImages[idx]; - - rendering_buffer rbuf_tmp; - rbuf_tmp.attach((uint8*)transBitmap->Bits(), - transBitmap->Bounds().IntegerWidth() + 1, - transBitmap->Bounds().IntegerHeight() + 1, - m_flip_y ? -transBitmap->BytesPerRow() : transBitmap->BytesPerRow()); - - m_specific->fImages[idx] = bitmap; - - m_rbuf_img[idx].attach((uint8*)bitmap->Bits(), - bitmap->Bounds().IntegerWidth() + 1, - bitmap->Bounds().IntegerHeight() + 1, - m_flip_y ? -bitmap->BytesPerRow() : bitmap->BytesPerRow()); - - rendering_buffer* dst = &m_rbuf_img[idx]; - - switch(m_format) - { - case pix_format_gray8: - return false; -// color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_gray8()); break; - break; - - case pix_format_rgb555: - color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb555()); break; - break; - - case pix_format_rgb565: - color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb565()); break; - break; - - case pix_format_rgb24: - color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb24()); break; - break; - - case pix_format_bgr24: - color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgr24()); break; - break; - - case pix_format_abgr32: - color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_abgr32()); break; - break; - - case pix_format_argb32: - color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_argb32()); break; - break; - - case pix_format_bgra32: - color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgra32()); break; - break; - - case pix_format_rgba32: - color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgba32()); break; - break; - } - delete transBitmap; - - return true; - - } else { - fprintf(stderr, "failed to load bitmap: '%s'\n", path.Path()); - } - } - return false; - } - - - - //------------------------------------------------------------------------ - bool platform_support::save_img(unsigned idx, const char* file) - { - // TODO: implement using BTranslatorRoster and friends - return false; - } - - - - //------------------------------------------------------------------------ - bool platform_support::create_img(unsigned idx, unsigned width, unsigned height) - { - if(idx < max_images) - { - if(width == 0) width = m_specific->fApp->Window()->View()->Bitmap()->Bounds().IntegerWidth() + 1; - if(height == 0) height = m_specific->fApp->Window()->View()->Bitmap()->Bounds().IntegerHeight() + 1; - BBitmap* bitmap = new BBitmap(BRect(0.0, 0.0, width - 1, height - 1), 0, B_RGBA32);; - if (bitmap && bitmap->IsValid()) { - delete m_specific->fImages[idx]; - m_specific->fImages[idx] = bitmap; - m_rbuf_img[idx].attach((uint8*)bitmap->Bits(), - width, height, - m_flip_y ? -bitmap->BytesPerRow() : bitmap->BytesPerRow()); - return true; - } else { - delete bitmap; - } - } - return false; - } - - - //------------------------------------------------------------------------ - void platform_support::force_redraw() - { - m_specific->ForceRedraw(); - } - - - - //------------------------------------------------------------------------ - void platform_support::update_window() - { - m_specific->UpdateWindow(); - } - - - //------------------------------------------------------------------------ - void platform_support::on_init() {} - void platform_support::on_resize(int sx, int sy) {} - void platform_support::on_idle() {} - void platform_support::on_mouse_move(int x, int y, unsigned flags) {} - void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {} - void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {} - void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {} - void platform_support::on_ctrl_change() {} - void platform_support::on_draw() {} - void platform_support::on_post_draw(void* raw_handler) {} -} - - - - - - -//---------------------------------------------------------------------------- -int agg_main(int argc, char* argv[]); - - - -int -main(int argc, char* argv[]) -{ - return agg_main(argc, argv); -} - - - - diff --git a/aggdraw.cxx b/aggdraw.cxx index 0ad56c7..0338322 100644 --- a/aggdraw.cxx +++ b/aggdraw.cxx @@ -32,9 +32,7 @@ * 2005-10-20 fl added clear method * 2005-10-23 fl support either hdc or hwnd in expose * 2006-02-12 fl fixed crashes in type(obj) and path constructor - * - * Copyright (c) 2003-2006 by Secret Labs AB - * + * 2014-07-28 dg Updated to agg-2.4 * 2015-07-15 ej fixed broken paths * 2017-01-03 ej added support for python 3 * 2017-01-03 ej tostring() -> tobytes(), fromstring() -> frombytes() @@ -42,6 +40,8 @@ * 2017-08-18 dh fixed a couple compiler warnings (specifically clang) * 2018-04-21 dh fixed python 2 compatibility in getcolor * + * Copyright (c) 2003-2006 by Secret Labs AB + * Copyright (c) 2014-2016 by Dov Grobgeld * Copyright (c) 2011-2017 by AggDraw Developers * */ @@ -58,10 +58,15 @@ #define M_PI 3.1415926535897931 #endif +#define PY_SSIZE_T_CLEAN 1 + #include "Python.h" #if PY_MAJOR_VERSION >= 3 #define IS_PY3K #define HAVE_UNICODE +#define NON_CONST_MAYBE(s) (s) +#else +#define NON_CONST_MAYBE(s) (char*)(s) #endif #include "bytesobject.h" @@ -84,13 +89,14 @@ #include "agg_font_freetype.h" #endif #include "agg_path_storage.h" -#include "agg_pixfmt_gray8.h" -#include "agg_pixfmt_rgb24.h" -#include "agg_pixfmt_rgba32.h" +#include "agg_pixfmt_gray.h" +#include "agg_pixfmt_rgb.h" +#include "agg_pixfmt_rgba.h" #include "agg_rasterizer_scanline_aa.h" #include "agg_renderer_scanline.h" #include "agg_rendering_buffer.h" #include "agg_scanline_p.h" +#include "agg_vcgen_stroke.h" #include "platform/agg_platform_support.h" // agg::pix_format_* /* -------------------------------------------------------------------- */ @@ -164,7 +170,11 @@ static PyTypeObject DrawType = { "Draw", sizeof(DrawObject), 0, /* methods */ (destructor) draw_dealloc, /* tp_dealloc */ +#if PY_VERSION_HEX < 0x030800b4 (printfunc)0, /* tp_print */ +#else + (Py_ssize_t)0, /* tp_vectorcall_offset */ +#endif (getattrfunc)draw_getattr, /* tp_getattr */ 0, /* tp_setattr */ }; @@ -174,6 +184,9 @@ typedef struct { PyObject_HEAD agg::rgba8 color; float width; + agg::line_join_e line_join; + agg::line_cap_e line_cap; + float miter_limit; } PenObject; static void pen_dealloc(PenObject* self); @@ -254,7 +267,11 @@ static PyTypeObject FontType = { "Font", sizeof(FontObject), 0, /* methods */ (destructor) font_dealloc, /* tp_dealloc */ +#if PY_VERSION_HEX < 0x030800b4 (printfunc)0, /* tp_print */ +#else + (Py_ssize_t)0, /* tp_vectorcall_offset */ +#endif 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ @@ -295,7 +312,11 @@ static PyTypeObject PathType = { "Path", sizeof(PathObject), 0, /* methods */ (destructor) path_dealloc, /* tp_dealloc */ +#if PY_VERSION_HEX < 0x030800b4 (printfunc)0, /* tp_print */ +#else + (Py_ssize_t)0, /* tp_vectorcall_offset */ +#endif 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ @@ -359,8 +380,12 @@ text_getchar(PyObject* string, int index, unsigned long* char_out) class draw_adaptor_base { public: - const char* mode; - virtual ~draw_adaptor_base() {}; + char* mode; + draw_adaptor_base() : mode(NULL) {}; + virtual ~draw_adaptor_base() { + if(mode) + free(mode); + }; virtual void setantialias(bool flag) = 0; virtual void draw(agg::path_storage &path, PyObject* obj1, PyObject* obj2=NULL) = 0; @@ -381,7 +406,9 @@ template class draw_adaptor : public draw_adaptor_base { draw_adaptor(DrawObject* self_, const char* mode_) { self = self_; - mode = mode_; + if (mode) + free(mode); + mode = strdup(mode_); setantialias(true); @@ -424,7 +451,7 @@ template class draw_adaptor : public draw_adaptor_base { p = new agg::path_storage(); agg::conv_transform tp(path, *self->transform); - p->add_path(tp, 0, false); + p->concat_path(tp, 0); } else p = &path; @@ -432,10 +459,6 @@ template class draw_adaptor : public draw_adaptor_base { /* interior */ agg::conv_contour contour(*p); contour.auto_detect_orientation(true); - if (pen) - contour.width(pen->width / 2.0); - else - contour.width(0.5); rasterizer.reset(); rasterizer.add_path(contour); renderer.color(brush->color); @@ -446,6 +469,9 @@ template class draw_adaptor : public draw_adaptor_base { /* outline */ /* FIXME: add path for dashed lines */ agg::conv_stroke stroke(*p); + stroke.line_join(pen->line_join); + stroke.line_cap(pen->line_cap); + stroke.miter_limit(pen->miter_limit); stroke.width(pen->width); rasterizer.reset(); rasterizer.add_path(stroke); @@ -709,7 +735,7 @@ draw_new(PyObject* self_, PyObject* args) self->image = image; if (image) { - PyObject* buffer = PyObject_CallMethod(image, "tobytes", NULL); + PyObject* buffer = PyObject_CallMethod(image, NON_CONST_MAYBE("tobytes"), NULL); if (!buffer) return NULL; /* FIXME: release resources */ if (!PyBytes_Check(buffer)) { @@ -968,7 +994,7 @@ getcolor(PyObject* color, int opacity) /* unknown color: pass it to the Python layer */ if (aggdraw_getcolor_obj) { PyObject* result; - result = PyObject_CallFunction(aggdraw_getcolor_obj, "O", color); + result = PyObject_CallFunction(aggdraw_getcolor_obj, NON_CONST_MAYBE("O"), color); if (result) { int ok = PyArg_ParseTuple(result, "iii", &red, &green, &blue); Py_DECREF(result); @@ -1053,7 +1079,7 @@ draw_arc(DrawObject* self, PyObject* args) false ); arc.approximation_scale(1); - path.add_path(arc); + path.concat_path(arc); self->draw->draw(path, pen); @@ -1099,7 +1125,7 @@ draw_chord(DrawObject* self, PyObject* args) false ); arc.approximation_scale(1); - path.add_path(arc); + path.concat_path(arc); path.close_polygon(); self->draw->draw(path, pen, brush); @@ -1138,7 +1164,7 @@ draw_ellipse(DrawObject* self, PyObject* args) agg::path_storage path; agg::ellipse ellipse((x1+x0)/2, (y1+y0)/2, (x1-x0)/2, (y1-y0)/2, 8); ellipse.approximation_scale(1); - path.add_path(ellipse); + path.concat_path(ellipse); self->draw->draw(path, pen, brush); @@ -1187,7 +1213,7 @@ draw_line(DrawObject* self, PyObject* args) path.move_to(xy[0].X, xy[0].Y); for (int i = 1; i < count; i++) path.line_to(xy[i].X, xy[i].Y); - delete xy; + delete [] xy; self->draw->draw(path, pen); } @@ -1237,7 +1263,7 @@ draw_pieslice(DrawObject* self, PyObject* args) false ); arc.approximation_scale(1); - path.add_path(arc); + path.concat_path(arc); path.line_to(x, y); path.close_polygon(); @@ -1283,7 +1309,7 @@ draw_polygon(DrawObject* self, PyObject* args) for (int i = 1; i < count; i++) path.line_to(xy[i].X, xy[i].Y); path.close_polygon(); - delete xy; + delete [] xy; self->draw->draw(path, pen, brush); } @@ -1403,11 +1429,11 @@ draw_symbol(DrawObject* self, PyObject* args) agg::conv_transform tp(*symbol->path, transform); agg::path_storage p; - p.add_path(tp, 0, false); + p.concat_path(tp, 0); self->draw->draw(p, pen, brush); } - delete xy; + delete [] xy; Py_INCREF(Py_None); return Py_None; @@ -1552,7 +1578,8 @@ const char *draw_frombytes_doc = "Copies data from a string buffer to the drawin static PyObject* draw_frombytes(DrawObject* self, PyObject* args) { - char* data = NULL; int data_size; + char* data = NULL; + Py_ssize_t data_size; if (!PyArg_ParseTuple(args, "s#:frombytes", &data, &data_size)) return NULL; @@ -1684,7 +1711,7 @@ draw_flush(DrawObject* self, PyObject* args) if (!buffer) return NULL; - result = PyObject_CallMethod(self->image, "frombytes", "N", buffer); + result = PyObject_CallMethod(self->image, NON_CONST_MAYBE("frombytes"), NON_CONST_MAYBE("N"), buffer); if (!result) return NULL; @@ -1800,7 +1827,16 @@ const char *pen_doc = "Creates a Pen object.\n" "width : int, optional\n" " Pen width. Default 1.\n" "opacity : int, optional\n" - " Pen opacity. Default 255.\n"; + " Pen opacity. Default 255.\n" + "linejoin : int, optional\n" + " Type of line_join. Types are 0=miter_join\n" + " 1=miter_join_revert; 2=round_join; 3=bevel_join;\n" + " 4=miter_join_round. Default 0 (miter join).\n" + "linecap : int, optional\n" + " Type of linecap. Types are 0=butt_cap;\n" + " 1=square_cap; 2=round_cap. Default 1 (butt cap).\n" + "miterlimit : float, optional\n" + " Type of miterlimit. Default 4.0.\n"; static PyObject* pen_new(PyObject* self_, PyObject* args, PyObject* kw) @@ -1809,10 +1845,14 @@ pen_new(PyObject* self_, PyObject* args, PyObject* kw) PyObject* color; float width = 1.0; + agg::line_join_e line_join = agg::miter_join; + agg::line_cap_e line_cap = agg::butt_cap; + float miter_limit = 4.0; // Like default in agg_math_stroke.h int opacity = 255; - static const char* const kwlist[] = { "color", "width", "opacity", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "O|fi:Pen", const_cast(kwlist), - &color, &width, &opacity)) + static const char* const kwlist[] = { "color", "width", "opacity", "linejoin", "linecap", "miterlimit", NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kw, "O|fiiif:Pen", const_cast(kwlist), + &color, &width, &opacity, + &line_join,&line_cap,&miter_limit)) return NULL; self = PyObject_NEW(PenObject, &PenType); @@ -1822,6 +1862,9 @@ pen_new(PyObject* self_, PyObject* args, PyObject* kw) self->color = getcolor(color, opacity); self->width = width; + self->line_join = line_join; + self->line_cap = line_cap; + self->miter_limit = miter_limit; return (PyObject*) self; } @@ -1914,13 +1957,13 @@ font_new(PyObject* self_, PyObject* args, PyObject* kw) self->height = size; if (!font_load(self)) { - PyErr_SetString(PyExc_IOError, "cannot load font"); + PyErr_SetString(PyExc_IOError, NON_CONST_MAYBE("cannot load font")); return NULL; } return (PyObject*) self; #else - PyErr_SetString(PyExc_IOError, "cannot load font (no text renderer)"); + PyErr_SetString(PyExc_IOError, NON_CONST_MAYBE("cannot load font (no text renderer)")); return NULL; #endif } @@ -1941,7 +1984,7 @@ font_load(FontObject* font, bool outline) font_engine.flip_y(1); font_engine.height(font->height); - // requires patch to "agg2\font_freetype\agg_font_freetype.h" + // requires patch to "agg\font_freetype\agg_font_freetype.h" // the patch should simply expose the m_cur_face variable return font_engine.m_cur_face; } @@ -2003,7 +2046,7 @@ font_getattr(FontObject* self, char* name) { #if defined(HAVE_FREETYPE2) FT_Face face; - if (!strcmp(name, "family")) { + if (!strcmp(name, NON_CONST_MAYBE("family"))) { face = font_load(self); if (!face) { Py_INCREF(Py_None); @@ -2011,7 +2054,7 @@ font_getattr(FontObject* self, char* name) } return PyBytes_FromString(face->family_name); } - if (!strcmp(name, "style")) { + if (!strcmp(name, NON_CONST_MAYBE("style"))) { face = font_load(self); if (!face) { Py_INCREF(Py_None); @@ -2019,7 +2062,7 @@ font_getattr(FontObject* self, char* name) } return PyBytes_FromString(face->style_name); } - if (!strcmp(name, "ascent")) { + if (!strcmp(name, NON_CONST_MAYBE("ascent"))) { face = font_load(self); if (!face) { Py_INCREF(Py_None); @@ -2027,7 +2070,7 @@ font_getattr(FontObject* self, char* name) } return PyFloat_FromDouble(face->size->metrics.ascender/64.0); } - if (!strcmp(name, "descent")) { + if (!strcmp(name, NON_CONST_MAYBE("descent"))) { face = font_load(self); if (!face) { Py_INCREF(Py_None); @@ -2055,7 +2098,7 @@ static PyObject* path_new(PyObject* self_, PyObject* args) { PyObject* xyIn = NULL; - if (!PyArg_ParseTuple(args, "|O:Path", &xyIn)) + if (!PyArg_ParseTuple(args, NON_CONST_MAYBE("|O:Path"), &xyIn)) return NULL; PathObject* self = PyObject_NEW(PathObject, &PathType); @@ -2075,7 +2118,7 @@ path_new(PyObject* self_, PyObject* args) self->path->move_to(xy[0].X, xy[0].Y); for (int i = 1; i < count; i++) self->path->line_to(xy[i].X, xy[i].Y); - delete xy; + delete [] xy; } return (PyObject*) self; @@ -2097,7 +2140,7 @@ symbol_new(PyObject* self_, PyObject* args) { char* path; float scale = 1.0; - if (!PyArg_ParseTuple(args, "s|f:Symbol", &path, &scale)) + if (!PyArg_ParseTuple(args, NON_CONST_MAYBE("s|f:Symbol"), &path, &scale)) return NULL; PathObject* self = PyObject_NEW(PathObject, &PathType); @@ -2129,7 +2172,7 @@ symbol_new(PyObject* self_, PyObject* args) } else { if (!op) { PyErr_Format( - PyExc_ValueError, "no command at start of path" + PyExc_ValueError, NON_CONST_MAYBE("no command at start of path") ); return NULL; } @@ -2250,7 +2293,7 @@ symbol_new(PyObject* self_, PyObject* args) default: PyErr_Format( PyExc_ValueError, - "unknown path command '%c'", op + NON_CONST_MAYBE("unknown path command '%c'"), op ); /* FIXME: cleanup */ return NULL; @@ -2258,7 +2301,7 @@ symbol_new(PyObject* self_, PyObject* args) if (p == q) { PyErr_Format( PyExc_ValueError, - "invalid arguments for command '%c'", op + NON_CONST_MAYBE("invalid arguments for command '%c'"), op ); /* FIXME: cleanup */ return NULL; @@ -2270,21 +2313,13 @@ symbol_new(PyObject* self_, PyObject* args) agg::path_storage* path = self->path; agg::conv_curve curve(*path); self->path = new agg::path_storage(); - self->path->add_path(curve, 0, false); + self->path->concat_path(curve, 0); delete path; } return (PyObject*) self; } -void expandPaths(PathObject *self) -{ - agg::path_storage* path = self->path; - agg::conv_curve curve(*path); - self->path = new agg::path_storage(); - self->path->add_path(curve, 0, false); - delete path; -} const char *path_moveto_doc = "Move the path pointer to the given location.\n" "\n" @@ -2297,7 +2332,7 @@ static PyObject* path_moveto(PathObject* self, PyObject* args) { double x, y; - if (!PyArg_ParseTuple(args, "dd:moveto", &x, &y)) + if (!PyArg_ParseTuple(args, NON_CONST_MAYBE("dd:moveto"), &x, &y)) return NULL; self->path->move_to(x, y); @@ -2317,7 +2352,7 @@ static PyObject* path_rmoveto(PathObject* self, PyObject* args) { double x, y; - if (!PyArg_ParseTuple(args, "dd:rmoveto", &x, &y)) + if (!PyArg_ParseTuple(args, NON_CONST_MAYBE("dd:rmoveto"), &x, &y)) return NULL; self->path->rel_to_abs(&x, &y); @@ -2338,7 +2373,7 @@ static PyObject* path_lineto(PathObject* self, PyObject* args) { double x, y; - if (!PyArg_ParseTuple(args, "dd:lineto", &x, &y)) + if (!PyArg_ParseTuple(args, NON_CONST_MAYBE("dd:lineto"), &x, &y)) return NULL; self->path->line_to(x, y); @@ -2360,7 +2395,7 @@ static PyObject* path_rlineto(PathObject* self, PyObject* args) { double x, y; - if (!PyArg_ParseTuple(args, "dd:rlineto", &x, &y)) + if (!PyArg_ParseTuple(args, NON_CONST_MAYBE("dd:rlineto"), &x, &y)) return NULL; self->path->rel_to_abs(&x, &y); @@ -2385,13 +2420,11 @@ static PyObject* path_curveto(PathObject* self, PyObject* args) { double x1, y1, x2, y2, x, y; - if (!PyArg_ParseTuple(args, "dddddd:curveto", &x1, &y1, &x2, &y2, &x, &y)) + if (!PyArg_ParseTuple(args, NON_CONST_MAYBE("dddddd:curveto"), &x1, &y1, &x2, &y2, &x, &y)) return NULL; self->path->curve4(x1, y1, x2, y2, x, y); - expandPaths(self); - Py_INCREF(Py_None); return Py_None; } @@ -2413,7 +2446,7 @@ static PyObject* path_rcurveto(PathObject* self, PyObject* args) { double x1, y1, x2, y2, x, y; - if (!PyArg_ParseTuple(args, "dddddd:rcurveto", &x1, &y1, &x2, &y2, &x, &y)) + if (!PyArg_ParseTuple(args, NON_CONST_MAYBE("dddddd:rcurveto"), &x1, &y1, &x2, &y2, &x, &y)) return NULL; self->path->rel_to_abs(&x1, &y1); @@ -2431,16 +2464,10 @@ const char *path_close_doc = "Close the current path."; static PyObject* path_close(PathObject* self, PyObject* args) { - if (!PyArg_ParseTuple(args, ":close")) + if (!PyArg_ParseTuple(args, NON_CONST_MAYBE(":close"))) return NULL; - self->path->close_polygon(0); - /* expand curves */ - agg::path_storage* path = self->path; - agg::conv_curve curve(*path); - self->path = new agg::path_storage(); - self->path->add_path(curve, 0, false); - delete path; + self->path->close_polygon(); Py_INCREF(Py_None); return Py_None; @@ -2450,7 +2477,7 @@ static PyObject* path_polygon(PathObject* self, PyObject* args) { PyObject* xyIn; - if (!PyArg_ParseTuple(args, "O:polygon", &xyIn)) + if (!PyArg_ParseTuple(args, NON_CONST_MAYBE("O:polygon"), &xyIn)) return NULL; int count; @@ -2464,9 +2491,9 @@ path_polygon(PathObject* self, PyObject* args) for (int i = 1; i < count; i++) path.line_to(xy[i].X, xy[i].Y); path.close_polygon(); - delete xy; + delete [] xy; - self->path->add_path(path, 0, false); + self->path->concat_path(path, 0); Py_INCREF(Py_None); return Py_None; @@ -2479,7 +2506,7 @@ const char *path_coords_doc = "Returns the coordinates for this path.\n" static PyObject* path_coords(PathObject* self, PyObject* args) { - if (!PyArg_ParseTuple(args, ":coords")) + if (!PyArg_ParseTuple(args, NON_CONST_MAYBE(":coords"))) return NULL; agg::conv_curve curve(*self->path); diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 7eae7b3..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,68 +0,0 @@ -environment: - global: - PYTHON: "C:\\conda" - MINICONDA_VERSION: "latest" - CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\ci-helpers\\appveyor\\windows_sdk.cmd" - CONDA_DEPENDENCIES: "sphinx pillow coveralls coverage pytest" - CONDA_CHANNELS: "conda-forge" - CONDA_CHANNEL_PRIORITY: "True" - TWINE_USERNAME: "dhoese" - TWINE_PASSWORD: - secure: zws6RrJGZ5XULrqXQDF/Cw== - - matrix: - - - CIBW_TEST_REQUIRES: "numpy pillow pytest" - CIBW_TEST_COMMAND: "python {project}\\selftest.py" - CIBUILDWHEEL: 1 - - - PYTHON: "C:\\Python27_32" - PYTHON_VERSION: "2.7" - PYTHON_ARCH: "32" - NUMPY_VERSION: "stable" - CIBUILDWHEEL: 0 - - - PYTHON: "C:\\Python27_64" - PYTHON_VERSION: "2.7" - PYTHON_ARCH: "64" - NUMPY_VERSION: "stable" - CIBUILDWHEEL: 0 - - - PYTHON: "C:\\Python36_32" - PYTHON_VERSION: "3.6" - PYTHON_ARCH: "32" - NUMPY_VERSION: "stable" - CIBUILDWHEEL: 0 - - - PYTHON: "C:\\Python36_64" - PYTHON_VERSION: "3.6" - PYTHON_ARCH: "64" - NUMPY_VERSION: "stable" - CIBUILDWHEEL: 0 - -install: - - if [%CIBUILDWHEEL%]==[0] git clone --depth 1 git://github.com/astropy/ci-helpers.git - - if [%CIBUILDWHEEL%]==[0] powershell ci-helpers/appveyor/install-miniconda.ps1 - - if [%CIBUILDWHEEL%]==[0] SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH% - - if [%CIBUILDWHEEL%]==[0] call activate test - -build: false # Not a C# project, build stuff at the test step instead. - -build_script: - - if [%CIBUILDWHEEL%]==[1] pip install cibuildwheel - - if [%CIBUILDWHEEL%]==[1] cibuildwheel --output-dir dist - - if [%CIBUILDWHEEL%]==[1] powershell ci/appveyor-twine.ps1 - - -test_script: - - if [%CIBUILDWHEEL%]==[0] conda info --envs - - if [%CIBUILDWHEEL%]==[0] %CMD_IN_ENV% pip install -e . - - if [%CIBUILDWHEEL%]==[0] %CMD_IN_ENV% python selftest.py - -after_test: - - if [%CIBUILDWHEEL%]==[0] %CMD_IN_ENV% python setup.py bdist_wheel bdist_wininst - - ps: "ls dist" - -artifacts: - # Archive the generated wheel package in the ci.appveyor.com build report. - - path: dist\* diff --git a/ci/appveyor-twine.ps1 b/ci/appveyor-twine.ps1 deleted file mode 100755 index e0a1449..0000000 --- a/ci/appveyor-twine.ps1 +++ /dev/null @@ -1,6 +0,0 @@ -# Small script for uploading wheels to pypi with twine - -if($env:appveyor_repo_tag -eq "true") { - python -m pip install twine - python -m twine upload --skip-existing dist/*.whl -} \ No newline at end of file diff --git a/ci/environment.yaml b/ci/environment.yaml new file mode 100644 index 0000000..7966090 --- /dev/null +++ b/ci/environment.yaml @@ -0,0 +1,7 @@ +name: test-environment +channels: + - conda-forge +dependencies: + - numpy + - pillow + - pytest diff --git a/ci/travis-build.sh b/ci/travis-build.sh deleted file mode 100755 index 2f297df..0000000 --- a/ci/travis-build.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash - -set -ex - -if [ "${BUILDMODE}" = "ASTROPY" ]; then - - pip install -e . - python selftest.py - -elif [ "${BUILDMODE}" = "CIBUILDWHEEL" ]; then - - export PIP=pip - if [ $(uname) = "Darwin" ]; then - export PIP=pip2 - fi - - cibuildwheel --output-dir wheelhouse - if [ $(uname) = "Darwin" ]; then - # Re-do delocate with patched version that actually works for aggdraw - $PIP install -U git+https://github.com/natefoo/delocate.git@top-level-fix-squash - export PATH="$PATH:/Library/Frameworks/Python.framework/Versions/2.7/bin" - WHEELS=wheelhouse/*.whl - for w in $WHEELS - do - delocate-wheel -v $w - done - fi - - if [[ $TRAVIS_TAG ]]; then - python -m pip install twine - python -m twine upload --skip-existing wheelhouse/*.whl - if [ $(uname) = "Darwin" ]; then # so we only do this once - python setup.py sdist - python -m twine upload --skip-existing dist/*.tar.gz - fi - fi - -fi diff --git a/ci/travis-install.sh b/ci/travis-install.sh deleted file mode 100755 index 0162d19..0000000 --- a/ci/travis-install.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -if [[ "${BUILDMODE}" == "ASTROPY" ]]; then - git clone --depth 1 git://github.com/astropy/ci-helpers.git - source ci-helpers/travis/setup_conda.sh -elif [[ "${BUILDMODE}" == "CIBUILDWHEEL" ]]; then - export PIP=pip - if [[ $(uname) == "Darwin" ]]; then - export PIP=pip2 - fi - $PIP install cibuildwheel -fi \ No newline at end of file diff --git a/selftest.py b/selftest.py index a2904a2..c589c73 100644 --- a/selftest.py +++ b/selftest.py @@ -102,7 +102,8 @@ def test_graphics2(): canvas = Draw(image) canvas.symbol((0, 0), symbol, pen) canvas.flush() - assert np.asarray(image).sum() == 50800 + # This is different from agg 2.4 but fully acceptable! + assert np.asarray(image).sum() == 51200 def test_graphics3(): @@ -125,10 +126,12 @@ def test_path(): p.lineto(1, 1) assert p.coords() == [0.0, 0.0, 1.0, 1.0] - p.curveto(0, 0, 0, 0, 0, 0) + p.curveto(2, 1, 2, 1, 2, 0) p.close() p.coords() - assert p.coords() == [0.0, 0.0, 1.0, 1.0, 0.125, 0.125, 0.0, 0.0] + # Changed test w.r.t. aggdraw for agg 2.4 + # Correctness of this may be seen in the file test-path-proof.ps + assert p.coords() == [0.0, 0.0, 1.0, 1.0, 1.625, 1.0, 2.0, 0.625, 2.0, 0.0] draw = Draw("RGB", (800, 600)) draw.line(p) diff --git a/setup.py b/setup.py index 5d2c320..2f27575 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ except ImportError: from distutils.core import setup, Extension -VERSION = "1.3.11" +VERSION = "1.3.13" SUMMARY = "High quality drawing interface for PIL." @@ -112,21 +112,19 @@ def _get_freetype_with_pkgconfig(): sources = [ # source code currently used by aggdraw # FIXME: link against AGG library instead? - "agg2/src/agg_arc.cpp", - "agg2/src/agg_bezier_arc.cpp", - "agg2/src/agg_curves.cpp", - "agg2/src/agg_path_storage.cpp", - "agg2/src/agg_rasterizer_scanline_aa.cpp", - "agg2/src/agg_trans_affine.cpp", - "agg2/src/agg_vcgen_contour.cpp", + "agg/src/agg_arc.cpp", + "agg/src/agg_bezier_arc.cpp", + "agg/src/agg_curves.cpp", + "agg/src/agg_trans_affine.cpp", + "agg/src/agg_vcgen_contour.cpp", # "agg2/src/agg_vcgen_dash.cpp", - "agg2/src/agg_vcgen_stroke.cpp", + "agg/src/agg_vcgen_stroke.cpp", ] # define VERSION macro in C++ code, need to quote it defines = [('VERSION', VERSION)] -include_dirs = ["agg2/include"] +include_dirs = ["agg/include"] library_dirs = [] libraries = [] @@ -134,9 +132,9 @@ def _get_freetype_with_pkgconfig(): if FREETYPE_ROOT: defines.append(("HAVE_FREETYPE2", None)) sources.extend([ - "agg2/font_freetype/agg_font_freetype.cpp", + "agg/font_freetype/agg_font_freetype.cpp", ]) - include_dirs.append("agg2/font_freetype") + include_dirs.append("agg/font_freetype") include_dirs.append(os.path.join(FREETYPE_ROOT, "include")) include_dirs.append(os.path.join(FREETYPE_ROOT, "include/freetype")) include_dirs.append(os.path.join(FREETYPE_ROOT, "include/freetype2")) @@ -145,6 +143,7 @@ def _get_freetype_with_pkgconfig(): if sys.platform == "win32": libraries.extend(["kernel32", "user32", "gdi32"]) + defines.append(("NOMINMAX", None)) setup( name="aggdraw",