diff options
author | Eugene Sandulenko | 2010-09-25 19:50:04 +0000 |
---|---|---|
committer | Eugene Sandulenko | 2010-10-13 00:06:12 +0000 |
commit | 7bcfe1f195671057ecb028e3bf353f475cebb379 (patch) | |
tree | 762596a6526809f3dafcf2716947111f6935360b | |
parent | 343981923291581b3c4890ea99961a1bf2e7c56e (diff) | |
download | scummvm-rg350-7bcfe1f195671057ecb028e3bf353f475cebb379.tar.gz scummvm-rg350-7bcfe1f195671057ecb028e3bf353f475cebb379.tar.bz2 scummvm-rg350-7bcfe1f195671057ecb028e3bf353f475cebb379.zip |
SWORD25: Remove standalone SWF rendering tool
svn-id: r53387
22 files changed, 0 insertions, 7354 deletions
diff --git a/engines/sword25/tools/swfdisplay/Makefile b/engines/sword25/tools/swfdisplay/Makefile deleted file mode 100644 index 7e2005134e..0000000000 --- a/engines/sword25/tools/swfdisplay/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -CC = g++ -DEBFLAGS = -g -Wall -O0 -LDFLAGS = -lgdk_pixbuf-2.0 -lpng -CXXFLAGS = -I/usr/include/gtk-2.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include/ -I/usr/include/gdk-pixbuf-2.0/ -BCFLAGS = -I/usr/include/libart-2.0 -I/usr/include/gtk-2.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include/ -I/usr/include/gdk-pixbuf-2.0/ -BIN_TARGET = swfrender -OBJ_TARGETS = \ - swfrender.o \ - art.o \ - art_svp_intersect.o \ - art_svp_render_aa.o \ - art_svp_vpath.o \ - art_svp_vpath_stroke.o \ - art_vpath_bpath.o \ - vectorimage.o \ - vectorimagerenderer.o - -all: ${BIN_TARGET} - -${BIN_TARGET}: ${OBJ_TARGETS} - ${CC} ${DEBFLAGS} $^ -o $@ ${LDFLAGS} - -%.o: %.cpp Makefile - ${CC} ${CXXFLAGS} ${DEBFLAGS} -c $< -o $@ - -bezierrender: bezierrender.o - ${CC} ${DEBFLAGS} $^ -o $@ ${LDFLAGS} -lart_lgpl_2 - -bezierrender.o: bezierrender.cpp - ${CC} ${BCFLAGS} ${DEBFLAGS} -c $< -o $@ - -clean: ${BIN_TARGET} Makefile - rm -f *~ *.o ${BIN_TARGET} 2>/dev/null diff --git a/engines/sword25/tools/swfdisplay/algorithm.h b/engines/sword25/tools/swfdisplay/algorithm.h deleted file mode 100644 index 8d6743a911..0000000000 --- a/engines/sword25/tools/swfdisplay/algorithm.h +++ /dev/null @@ -1,255 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/common/algorithm.h $ - * $Id: algorithm.h 51524 2010-07-30 23:42:50Z lordhoto $ - */ - -#ifndef COMMON_ALGORITHM_H -#define COMMON_ALGORITHM_H - -#include "func.h" - -namespace Common { - -/** - * Copies data from the range [first, last) to [dst, dst + (last - first)). - * It requires the range [dst, dst + (last - first)) to be valid. - * It also requires dst not to be in the range [first, last). - */ -template<class In, class Out> -Out copy(In first, In last, Out dst) { - while (first != last) - *dst++ = *first++; - return dst; -} - -/** - * Copies data from the range [first, last) to [dst - (last - first), dst). - * It requires the range [dst - (last - first), dst) to be valid. - * It also requires dst not to be in the range [first, last). - * - * Unlike copy copy_backward copies the data from the end to the beginning. - */ -template<class In, class Out> -Out copy_backward(In first, In last, Out dst) { - while (first != last) - *--dst = *--last; - return dst; -} - -/** - * Copies data from the range [first, last) to [dst, dst + (last - first)). - * It requires the range [dst, dst + (last - first)) to be valid. - * It also requires dst not to be in the range [first, last). - * - * Unlike copy or copy_backward it does not copy all data. It only copies - * a data element when operator() of the op parameter returns true for the - * passed data element. - */ -template<class In, class Out, class Op> -Out copy_if(In first, In last, Out dst, Op op) { - while (first != last) { - if (op(*first)) - *dst++ = *first; - ++first; - } - return dst; -} - -// Our 'specialized' 'set_to' template for char, signed char and unsigned char arrays. -// Since C++ doesn't support partial specialized template functions (currently) we -// are going this way... -// With this we assure the usage of memset for those, which should be -// faster than a simple loop like for the generic 'set_to'. -template<class Value> -signed char *set_to(signed char *first, signed char *last, Value val) { - memset(first, (val & 0xFF), last - first); - return last; -} - -template<class Value> -unsigned char *set_to(unsigned char *first, unsigned char *last, Value val) { - memset(first, (val & 0xFF), last - first); - return last; -} - -template<class Value> -char *set_to(char *first, char *last, Value val) { - memset(first, (val & 0xFF), last - first); - return last; -} - -/** - * Sets all elements in the range [first, last) to val. - */ -template<class In, class Value> -In set_to(In first, In last, Value val) { - while (first != last) - *first++ = val; - return first; -} - -/** - * Finds the first data value in the range [first, last) matching v. - * For data comperance it uses operator == of the data elements. - */ -template<class In, class T> -In find(In first, In last, const T &v) { - while (first != last) { - if (*first == v) - return first; - ++first; - } - return last; -} - -/** - * Finds the first data value in the range [first, last) for which - * the specified predicate p returns true. - */ -template<class In, class Pred> -In find_if(In first, In last, Pred p) { - while (first != last) { - if (p(*first)) - return first; - ++first; - } - return last; -} - -/** - * Applies the function f on all elements of the range [first, last). - * The processing order is from beginning to end. - */ -template<class In, class Op> -Op for_each(In first, In last, Op f) { - while (first != last) f(*first++); - return f; -} - -template<typename T> -unsigned int distance(T *first, T *last) { - return last - first; -} - -template<typename T> -unsigned int distance(T first, T last) { - unsigned int n = 0; - while (first != last) { - ++n; - ++first; - } - return n; -} - -template<typename T> -T *sortChoosePivot(T *first, T *last) { - return first + distance(first, last) / 2; -} - -template<typename T> -T sortChoosePivot(T first, T last) { - unsigned int n = distance(first, last); - n /= 2; - while (n--) - ++first; - return first; -} - -template<typename T, class StrictWeakOrdering> -T sortPartition(T first, T last, T pivot, StrictWeakOrdering &comp) { - --last; - SWAP(*pivot, *last); - - T sorted; - for (sorted = first; first != last; ++first) { - if (!comp(*last, *first)) { - if (first != sorted) - SWAP(*first, *sorted); - ++sorted; - } - } - - SWAP(*last, *sorted); - return sorted; -} - -/** - * Simple sort function, modeled after std::sort. - * It compares data with the given comparator object comp. - * - * Like std::sort this is not guaranteed to be stable. - * - * Two small quotes from wikipedia about stability: - * - * Stable sorting algorithms maintain the relative order of records with - * equal keys. - * - * Unstable sorting algorithms may change the relative order of records with - * equal keys, but stable sorting algorithms never do so. - * - * For more information on that topic check out: - * http://en.wikipedia.org/wiki/Sorting_algorithm#Stability - * - * NOTE: Actually as the time of writing our implementation is unstable. - */ -template<typename T, class StrictWeakOrdering> -void sort(T first, T last, StrictWeakOrdering comp) { - if (first == last) - return; - - T pivot = sortChoosePivot(first, last); - pivot = sortPartition(first, last, pivot, comp); - sort<T, StrictWeakOrdering>(first, pivot, comp); - sort<T, StrictWeakOrdering>(++pivot, last, comp); -} - -/** - * Simple sort function, modeled after std::sort. - */ -template<typename T> -void sort(T *first, T *last) { - sort(first, last, Common::Less<T>()); -} - -template<class T> -void sort(T first, T last) { - sort(first, last, Common::Less<typename T::ValueType>()); -} - -/** - * Euclid's algorithm to compute the greatest common divisor. - */ -template<class T> -T gcd(T a, T b) { - if (a <= 0) a = -a; - if (b <= 0) b = -b; - while (a > 0) { - T tmp = a; - a = b % a; - b = tmp; - } - return b; -} - -} // End of namespace Common -#endif - diff --git a/engines/sword25/tools/swfdisplay/array.h b/engines/sword25/tools/swfdisplay/array.h deleted file mode 100644 index f09db9c63c..0000000000 --- a/engines/sword25/tools/swfdisplay/array.h +++ /dev/null @@ -1,318 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/common/array.h $ - * $Id: array.h 45247 2009-10-19 17:46:50Z fingolfin $ - */ - -#ifndef COMMON_ARRAY_H -#define COMMON_ARRAY_H - -#include "algorithm.h" - -namespace Common { - -/** - * This class implements a dynamically sized container, which - * can be accessed similar to a regular C++ array. Accessing - * elements is performed in constant time (like with plain arrays). - * In addition, one can append, insert and remove entries (this - * is the 'dynamic' part). Doing that in general takes time - * proportional to the number of elements in the array. - * - * The container class closest to this in the C++ standard library is - * std::vector. However, there are some differences. The most important one is - * that std::vector has a far more sophisticated (and complicated) memory - * management scheme. There, only elements that 'live' are actually constructed - * (i.e., have their constructor called), and objects that are removed are - * immediately destructed (have their destructor called). - * With Common::Array, this is not the case; instead, it simply uses new[] and - * delete[] to allocate whole blocks of objects, possibly more than are - * currently 'alive'. This simplifies memory management, but may have - * undesirable side effects when one wants to use an Array of complex - * data types. - * - * @todo Improve the storage management of this class. - * In particular, don't use new[] and delete[], but rather - * construct/destruct objects manually. This way, we can - * ensure that storage which is not currently used does not - * correspond to a live active object. - * (This is only of interest for array of non-POD objects). - */ -template<class T> -class Array { -protected: - uint _capacity; - uint _size; - T *_storage; - -public: - typedef T *iterator; - typedef const T *const_iterator; - - typedef T value_type; - -public: - Array() : _capacity(0), _size(0), _storage(0) {} - - Array(const Array<T> &array) : _capacity(array._size), _size(array._size), _storage(0) { - if (array._storage) { - _storage = new T[_capacity]; - assert(_storage); - copy(array._storage, array._storage + _size, _storage); - } - } - - /** - * Construct an array by copying data from a regular array. - */ - template<class T2> - Array(const T2 *data, int n) { - _capacity = _size = n; - _storage = new T[_capacity]; - assert(_storage); - copy(data, data + _size, _storage); - } - - ~Array() { - delete[] _storage; - _storage = 0; - _capacity = _size = 0; - } - - /** Appends element to the end of the array. */ - void push_back(const T &element) { - if (_size + 1 <= _capacity) - _storage[_size++] = element; - else - insert_aux(end(), &element, &element + 1); - } - - void push_back(const Array<T> &array) { - if (_size + array.size() <= _capacity) { - copy(array.begin(), array.end(), end()); - _size += array.size(); - } else - insert_aux(end(), array.begin(), array.end()); - } - - /** Removes the last element of the array. */ - void pop_back() { - assert(_size > 0); - _size--; - } - - /** Returns a reference to the first element of the array. */ - T &front() { - assert(_size > 0); - return _storage[0]; - } - - /** Returns a reference to the first element of the array. */ - const T &front() const { - assert(_size > 0); - return _storage[0]; - } - - /** Returns a reference to the last element of the array. */ - T &back() { - assert(_size > 0); - return _storage[_size-1]; - } - - /** Returns a reference to the last element of the array. */ - const T &back() const { - assert(_size > 0); - return _storage[_size-1]; - } - - - void insert_at(int idx, const T &element) { - assert(idx >= 0 && (uint)idx <= _size); - insert_aux(_storage + idx, &element, &element + 1); - } - - T remove_at(int idx) { - assert(idx >= 0 && (uint)idx < _size); - T tmp = _storage[idx]; - copy(_storage + idx + 1, _storage + _size, _storage + idx); - _size--; - return tmp; - } - - // TODO: insert, remove, ... - - T& operator[](int idx) { - assert(idx >= 0 && (uint)idx < _size); - return _storage[idx]; - } - - const T& operator[](int idx) const { - assert(idx >= 0 && (uint)idx < _size); - return _storage[idx]; - } - - Array<T>& operator=(const Array<T> &array) { - if (this == &array) - return *this; - - delete[] _storage; - _size = array._size; - _capacity = _size + 32; - _storage = new T[_capacity]; - assert(_storage); - copy(array._storage, array._storage + _size, _storage); - - return *this; - } - - uint size() const { - return _size; - } - - void clear() { - delete[] _storage; - _storage = 0; - _size = 0; - _capacity = 0; - } - - bool empty() const { - return (_size == 0); - } - - bool operator==(const Array<T> &other) const { - if (this == &other) - return true; - if (_size != other._size) - return false; - for (uint i = 0; i < _size; ++i) { - if (_storage[i] != other._storage[i]) - return false; - } - return true; - } - bool operator!=(const Array<T> &other) const { - return !(*this == other); - } - - - iterator begin() { - return _storage; - } - - iterator end() { - return _storage + _size; - } - - const_iterator begin() const { - return _storage; - } - - const_iterator end() const { - return _storage + _size; - } - - void reserve(uint newCapacity) { - if (newCapacity <= _capacity) - return; - - T *old_storage = _storage; - _capacity = newCapacity; - _storage = new T[newCapacity]; - assert(_storage); - - if (old_storage) { - // Copy old data - copy(old_storage, old_storage + _size, _storage); - delete[] old_storage; - } - } - - void resize(uint newSize) { - reserve(newSize); - for (uint i = _size; i < newSize; ++i) - _storage[i] = T(); - _size = newSize; - } - -protected: - static uint roundUpCapacity(uint capacity) { - // Round up capacity to the next power of 2; - // we use a minimal capacity of 8. - uint capa = 8; - while (capa < capacity) - capa <<= 1; - return capa; - } - - /** - * Insert a range of elements coming from this or another array. - * Unlike std::vector::insert, this method does not accept - * arbitrary iterators, mainly because our iterator system is - * seriously limited and does not distinguish between input iterators, - * output iterators, forward iterators or random access iterators. - * - * So, we simply restrict to Array iterators. Extending this to arbitrary - * random access iterators would be trivial. - * - * Moreover, this method does not handle all cases of inserting a subrange - * of an array into itself; this is why it is private for now. - */ - iterator insert_aux(iterator pos, const_iterator first, const_iterator last) { - assert(_storage <= pos && pos <= _storage + _size); - assert(first <= last); - const uint n = last - first; - if (n) { - const uint idx = pos - _storage; - T *newStorage = _storage; - if (_size + n > _capacity) { - // If there is not enough space, allocate more and - // copy old elements over. - uint newCapacity = roundUpCapacity(_size + n); - newStorage = new T[newCapacity]; - assert(newStorage); - copy(_storage, _storage + idx, newStorage); - pos = newStorage + idx; - } - - // Make room for the new elements by shifting back - // existing ones. - copy_backward(_storage + idx, _storage + _size, newStorage + _size + n); - - // Insert the new elements. - copy(first, last, pos); - - // Finally, update the internal state - if (newStorage != _storage) { - delete[] _storage; - _capacity = roundUpCapacity(_size + n); - _storage = newStorage; - } - _size += n; - } - return pos; - } - -}; - -} // End of namespace Common - -#endif diff --git a/engines/sword25/tools/swfdisplay/art-non-display1.cpp b/engines/sword25/tools/swfdisplay/art-non-display1.cpp deleted file mode 100644 index b3d4457e71..0000000000 --- a/engines/sword25/tools/swfdisplay/art-non-display1.cpp +++ /dev/null @@ -1,488 +0,0 @@ -#include <libart_lgpl/art_vpath_bpath.h> -#include <libart_lgpl/art_svp_vpath.h> -#include <libart_lgpl/art_svp_vpath_stroke.h> -#include <libart_lgpl/art_svp_render_aa.h> -#include <libart_lgpl/art_rgb_svp.h> -#include <libart_lgpl/art_rgb.h> - -#define SAVING 1 - -#define WIDTH 3000 -#define HEIGHT 3000 -#define BYTES_PER_PIXEL 3 /* 24 packed rgb bits */ -#define ROWSTRIDE (WIDTH*BYTES_PER_PIXEL) - - -static unsigned char *render_path(void); - -#if SAVING -static void save_buffer(unsigned char *buffer, const char *filename); - -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <png.h> -#include <stdio.h> - -static gboolean -pixbuf_save_to_file(const GdkPixbuf *pixbuf, const char *file_name) { - FILE *handle; - unsigned char *buffer; - gboolean has_alpha; - int width, height, depth, rowstride; - guchar *pixels; - png_structp png_ptr; - png_infop info_ptr; - png_text text[2]; - int i; - - g_return_val_if_fail(pixbuf != NULL, FALSE); - g_return_val_if_fail(file_name != NULL, FALSE); - g_return_val_if_fail(file_name[0] != '\0', FALSE); - - handle = fopen(file_name, "wb"); - if (handle == NULL) { - return FALSE; - } - - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (png_ptr == NULL) { - fclose(handle); - return FALSE; - } - - info_ptr = png_create_info_struct(png_ptr); - if (info_ptr == NULL) { - png_destroy_write_struct(&png_ptr, (png_infopp)NULL); - fclose(handle); - return FALSE; - } - - if (setjmp(png_ptr->jmpbuf)) { - png_destroy_write_struct(&png_ptr, &info_ptr); - fclose(handle); - return FALSE; - } - - png_init_io(png_ptr, handle); - - has_alpha = gdk_pixbuf_get_has_alpha(pixbuf); - width = gdk_pixbuf_get_width(pixbuf); - height = gdk_pixbuf_get_height(pixbuf); - depth = gdk_pixbuf_get_bits_per_sample(pixbuf); - pixels = gdk_pixbuf_get_pixels(pixbuf); - rowstride = gdk_pixbuf_get_rowstride(pixbuf); - - png_set_IHDR(png_ptr, info_ptr, width, height, - depth, PNG_COLOR_TYPE_RGB_ALPHA, - PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - - /* Some text to go with the png image */ - text[0].key = "Title"; - text[0].text = (char *) file_name; - text[0].compression = PNG_TEXT_COMPRESSION_NONE; - text[1].key = "Software"; - text[1].text = "Nautilus Thumbnail"; - text[1].compression = PNG_TEXT_COMPRESSION_NONE; - png_set_text(png_ptr, info_ptr, text, 2); - - /* Write header data */ - png_write_info(png_ptr, info_ptr); - - /* if there is no alpha in the data, allocate buffer to expand into */ - if (has_alpha) { - buffer = NULL; - } else { - buffer = g_malloc(4 * width); - } - - /* pump the raster data into libpng, one scan line at a time */ - for (i = 0; i < height; i++) { - if (has_alpha) { - png_bytep row_pointer = pixels; - png_write_row(png_ptr, row_pointer); - } else { - /* expand RGB to RGBA using an opaque alpha value */ - int x; - unsigned char *buffer_ptr = buffer; - unsigned char *source_ptr = pixels; - for (x = 0; x < width; x++) { - *buffer_ptr++ = *source_ptr++; - *buffer_ptr++ = *source_ptr++; - *buffer_ptr++ = *source_ptr++; - *buffer_ptr++ = 255; - } - png_write_row(png_ptr, (png_bytep) buffer); - } - pixels += rowstride; - } - - png_write_end(png_ptr, info_ptr); - png_destroy_write_struct(&png_ptr, &info_ptr); - - g_free(buffer); - - fclose(handle); - return TRUE; -} - -static void -save_buffer(unsigned char *buffer, const char *filename) { - GdkPixbuf *pixbuf; - - g_type_init(); - - pixbuf = gdk_pixbuf_new_from_data(buffer, - GDK_COLORSPACE_RGB, -#if BYTES_PER_PIXEL == 4 - TRUE, -#else - FALSE, -#endif - 8, - WIDTH, HEIGHT, - ROWSTRIDE, - NULL, NULL); - - pixbuf_save_to_file(pixbuf, filename); - - gdk_pixbuf_unref(pixbuf); -} - -#endif - -void -art_rgb_fill_run1(art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, gint n) { - int i; - - if (r == g && g == b && r == 255) { - memset(buf, g, n + n + n + n); - } else { - art_u32 *alt = (art_u32 *)buf; - //art_u32 color = (r << 24) | (g << 16) | (b << 8) | 0xff; - art_u32 color = (r << 0) | (g << 8) | (b << 16) | (0xff << 24); - for (i = 0; i < n; i++) - *alt++ = color; - } -} - -void -art_rgb_run_alpha1(art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n) { - int i; - int v; - - for (i = 0; i < n; i++) { - v = *buf; - *buf++ = v + (((r - v) * alpha + 0x80) >> 8); - v = *buf; - *buf++ = v + (((g - v) * alpha + 0x80) >> 8); - v = *buf; - *buf++ = v + (((b - v) * alpha + 0x80) >> 8); - v = *buf; - *buf++ = v + (((alpha - v) * alpha + 0x80) >> 8); - } -} - -typedef struct _ArtRgbSVPAlphaData ArtRgbSVPAlphaData; - -struct _ArtRgbSVPAlphaData { - int alphatab[256]; - art_u8 r, g, b, alpha; - art_u8 *buf; - int rowstride; - int x0, x1; -}; - -static void -art_rgb_svp_alpha_callback1(void *callback_data, int y, - int start, ArtSVPRenderAAStep *steps, int n_steps) { - ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data; - art_u8 *linebuf; - int run_x0, run_x1; - art_u32 running_sum = start; - int x0, x1; - int k; - art_u8 r, g, b; - int *alphatab; - int alpha; - - linebuf = data->buf; - x0 = data->x0; - x1 = data->x1; - - r = data->r; - g = data->g; - b = data->b; - alphatab = data->alphatab; - - if (n_steps > 0) { - run_x1 = steps[0].x; - if (run_x1 > x0) { - alpha = (running_sum >> 16) & 0xff; - if (alpha) - art_rgb_run_alpha1(linebuf, r, g, b, alphatab[alpha], run_x1 - x0); - } - - for (k = 0; k < n_steps - 1; k++) { - running_sum += steps[k].delta; - run_x0 = run_x1; - run_x1 = steps[k + 1].x; - if (run_x1 > run_x0) { - alpha = (running_sum >> 16) & 0xff; - if (alpha) - art_rgb_run_alpha1(linebuf + (run_x0 - x0) * 4, r, g, b, alphatab[alpha], run_x1 - run_x0); - } - } - running_sum += steps[k].delta; - if (x1 > run_x1) { - alpha = (running_sum >> 16) & 0xff; - if (alpha) - art_rgb_run_alpha1(linebuf + (run_x1 - x0) * 4, r, g, b, alphatab[alpha], x1 - run_x1); - } - } else { - alpha = (running_sum >> 16) & 0xff; - if (alpha) - art_rgb_run_alpha1(linebuf, r, g, b, alphatab[alpha], x1 - x0); - } - - data->buf += data->rowstride; -} - -static void -art_rgb_svp_alpha_opaque_callback1(void *callback_data, int y, - int start, - ArtSVPRenderAAStep *steps, int n_steps) { - ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data; - art_u8 *linebuf; - int run_x0, run_x1; - art_u32 running_sum = start; - int x0, x1; - int k; - art_u8 r, g, b; - int *alphatab; - int alpha; - - linebuf = data->buf; - x0 = data->x0; - x1 = data->x1; - - r = data->r; - g = data->g; - b = data->b; - alphatab = data->alphatab; - - if (n_steps > 0) { - run_x1 = steps[0].x; - if (run_x1 > x0) { - alpha = running_sum >> 16; - if (alpha) { - if (alpha >= 255) - art_rgb_fill_run1(linebuf, r, g, b, run_x1 - x0); - else - art_rgb_run_alpha1(linebuf, r, g, b, alphatab[alpha], run_x1 - x0); - } - } - - for (k = 0; k < n_steps - 1; k++) { - running_sum += steps[k].delta; - run_x0 = run_x1; - run_x1 = steps[k + 1].x; - if (run_x1 > run_x0) { - alpha = running_sum >> 16; - if (alpha) { - if (alpha >= 255) - art_rgb_fill_run1(linebuf + (run_x0 - x0) * 4, r, g, b, run_x1 - run_x0); - else - art_rgb_run_alpha1(linebuf + (run_x0 - x0) * 4, r, g, b, alphatab[alpha], run_x1 - run_x0); - } - } - } - running_sum += steps[k].delta; - if (x1 > run_x1) { - alpha = running_sum >> 16; - if (alpha) { - if (alpha >= 255) - art_rgb_fill_run1(linebuf + (run_x1 - x0) * 4, r, g, b, x1 - run_x1); - else - art_rgb_run_alpha1(linebuf + (run_x1 - x0) * 4, r, g, b, alphatab[alpha], x1 - run_x1); - } - } - } else { - alpha = running_sum >> 16; - if (alpha) { - if (alpha >= 255) - art_rgb_fill_run1(linebuf, r, g, b, x1 - x0); - else - art_rgb_run_alpha1(linebuf, r, g, b, alphatab[alpha], x1 - x0); - } - } - - data->buf += data->rowstride; -} - -void -art_rgb_svp_alpha1(const ArtSVP *svp, - int x0, int y0, int x1, int y1, - art_u32 rgba, - art_u8 *buf, int rowstride, - ArtAlphaGamma *alphagamma) { - ArtRgbSVPAlphaData data; - int r, g, b, alpha; - int i; - int a, da; - - alpha = rgba >> 24; - r = (rgba >> 16) & 0xff; - g = (rgba >> 8) & 0xff; - b = rgba & 0xff; - - data.r = r; - data.g = g; - data.b = b; - data.alpha = alpha; - - a = 0x8000; - da = (alpha * 66051 + 0x80) >> 8; /* 66051 equals 2 ^ 32 / (255 * 255) */ - - for (i = 0; i < 256; i++) { - data.alphatab[i] = a >> 16; - a += da; - } - - data.buf = buf; - data.rowstride = rowstride; - data.x0 = x0; - data.x1 = x1; - if (alpha == 255) - art_svp_render_aa(svp, x0, y0, x1, y1, art_rgb_svp_alpha_opaque_callback1, &data); - else - art_svp_render_aa(svp, x0, y0, x1, y1, art_rgb_svp_alpha_callback1, &data); -} - -static int art_vpath_len (ArtVpath * a) { - int i; - - for (i = 0; a[i].code != ART_END; i++); - return i; -} - -ArtVpath *art_vpath_reverse(ArtVpath * a) { - ArtVpath *dest; - ArtVpath it; - int len; - int state = 0; - int i; - - len = art_vpath_len(a); - dest = g_malloc((len + 1) * sizeof(ArtVpath)); - - for (i = 0; i < len; i++) { - it = a[len - i - 1]; - if (state) { - it.code = ART_LINETO; - } else { - it.code = ART_MOVETO_OPEN; - state = 1; - } - if (a[len - i - 1].code == ART_MOVETO || - a[len - i - 1].code == ART_MOVETO_OPEN) { - state = 0; - } - dest[i] = it; - } - dest[len] = a[len]; - - return dest; -} - -ArtVpath *art_vpath_reverse_free(ArtVpath *a) { - ArtVpath *dest; - - dest = art_vpath_reverse(a); - art_free(a); - - return dest; -} - -void art_svp_make_convex (ArtSVP *svp) { - int i; - - if (svp->n_segs > 0 && svp->segs[0].dir == 0) { - for (i = 0; i < svp->n_segs; i++) { - svp->segs[i].dir = !svp->segs[i].dir; - } - } -} - - -void drawBez(ArtBpath *bez, art_u8 *buffer, double scaleX, double scaleY, double penWidth, unsigned int color) { - ArtVpath *vec = NULL; - ArtSVP *svp = NULL; - - vec = art_bez_path_to_vec(bez, 0.5); - - if (scaleX != 1.0 || scaleY != 1.0) { - ArtVpath *vec1; - double matrix[6]; - - matrix[0] = scaleX; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = scaleY; - matrix[4] = matrix[5] = 0; - - vec1 = art_vpath_affine_transform(vec, matrix); - art_free(vec); - - vec = vec1; - } - - if (penWidth != -1) { - svp = art_svp_vpath_stroke(vec, ART_PATH_STROKE_JOIN_ROUND, ART_PATH_STROKE_CAP_ROUND, penWidth, 1.0, 0.5); - } else { - svp = art_svp_from_vpath(vec); - } - -#if BYTES_PER_PIXEL == 4 - art_rgb_svp_alpha1(svp, 0, 0, WIDTH, HEIGHT, color, buffer, ROWSTRIDE, NULL); -#else - color <<= 8; - color |= 0xff; - art_rgb_svp_alpha(svp, 0, 0, WIDTH, HEIGHT, color, buffer, ROWSTRIDE, NULL); -#endif - art_free(svp); - - art_free(vec); -} - -static unsigned char *render_path() { - art_u8 *buffer = NULL; - - ArtBpath *bez = NULL; - - buffer = art_new(art_u8, WIDTH * HEIGHT * BYTES_PER_PIXEL); -#if BYTES_PER_PIXEL == 4 - memset(buffer, 0, WIDTH*HEIGHT*BYTES_PER_PIXEL); -#else - memset(buffer, 0xff, WIDTH*HEIGHT*BYTES_PER_PIXEL); -#endif - bez = art_new(ArtBpath, 100); - -#include "image.c" - - art_free(bez); - - return (unsigned char *) buffer; -} - -int main(int argc, char *argv[]) { - unsigned char *buffer; - - buffer = render_path(); - -#if SAVING - save_buffer(buffer, "foo.png"); -#endif - - return 0; -} diff --git a/engines/sword25/tools/swfdisplay/art.cpp b/engines/sword25/tools/swfdisplay/art.cpp deleted file mode 100644 index e88d6e55c4..0000000000 --- a/engines/sword25/tools/swfdisplay/art.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* Libart_LGPL - library of basic graphic primitives - * Copyright (C) 1998 Raph Levien - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* Various utility functions RLL finds useful. */ - -#include "art.h" - -#ifdef HAVE_UINSTD_H -#include <unistd.h> -#endif -#include <stdio.h> -#include <stdarg.h> - -/** - * art_die: Print the error message to stderr and exit with a return code of 1. - * @fmt: The printf-style format for the error message. - * - * Used for dealing with severe errors. - **/ -void -art_die(const char *fmt, ...) { - va_list ap; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - exit(1); -} - -/** - * art_warn: Print the warning message to stderr. - * @fmt: The printf-style format for the warning message. - * - * Used for generating warnings. - **/ -void -art_warn(const char *fmt, ...) { - va_list ap; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); -} - -/** - * art_svp_free: Free an #ArtSVP structure. - * @svp: #ArtSVP to free. - * - * Frees an #ArtSVP structure and all the segments in it. - **/ -void -art_svp_free(ArtSVP *svp) { - int n_segs = svp->n_segs; - int i; - - for (i = 0; i < n_segs; i++) - free(svp->segs[i].points); - free(svp); -} - -#ifdef ART_USE_NEW_INTERSECTOR -#define EPSILON 0 -#else -#define EPSILON 1e-6 -#endif - -/** - * art_svp_seg_compare: Compare two segments of an svp. - * @seg1: First segment to compare. - * @seg2: Second segment to compare. - * - * Compares two segments of an svp. Return 1 if @seg2 is below or to the - * right of @seg1, -1 otherwise. - **/ -int -art_svp_seg_compare(const void *s1, const void *s2) { - const ArtSVPSeg *seg1 = (const ArtSVPSeg *)s1; - const ArtSVPSeg *seg2 = (const ArtSVPSeg *)s2; - - if (seg1->points[0].y - EPSILON > seg2->points[0].y) return 1; - else if (seg1->points[0].y + EPSILON < seg2->points[0].y) return -1; - else if (seg1->points[0].x - EPSILON > seg2->points[0].x) return 1; - else if (seg1->points[0].x + EPSILON < seg2->points[0].x) return -1; - else if ((seg1->points[1].x - seg1->points[0].x) * - (seg2->points[1].y - seg2->points[0].y) - - (seg1->points[1].y - seg1->points[0].y) * - (seg2->points[1].x - seg2->points[0].x) > 0) return 1; - else return -1; -} - -/** - * art_vpath_add_point: Add point to vpath. - * @p_vpath: Where the pointer to the #ArtVpath structure is stored. - * @pn_points: Pointer to the number of points in *@p_vpath. - * @pn_points_max: Pointer to the number of points allocated. - * @code: The pathcode for the new point. - * @x: The X coordinate of the new point. - * @y: The Y coordinate of the new point. - * - * Adds a new point to *@p_vpath, reallocating and updating *@p_vpath - * and *@pn_points_max as necessary. *@pn_points is incremented. - * - * This routine always adds the point after all points already in the - * vpath. Thus, it should be called in the order the points are - * desired. - **/ -void -art_vpath_add_point(ArtVpath **p_vpath, int *pn_points, int *pn_points_max, - ArtPathcode code, double x, double y) { - int i; - - i = (*pn_points)++; - if (i == *pn_points_max) - art_expand(*p_vpath, ArtVpath, *pn_points_max); - (*p_vpath)[i].code = code; - (*p_vpath)[i].x = x; - (*p_vpath)[i].y = y; -} diff --git a/engines/sword25/tools/swfdisplay/art.h b/engines/sword25/tools/swfdisplay/art.h deleted file mode 100644 index aa66036287..0000000000 --- a/engines/sword25/tools/swfdisplay/art.h +++ /dev/null @@ -1,182 +0,0 @@ -/* Libart_LGPL - library of basic graphic primitives - * Copyright (C) 1998 Raph Levien - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* Simple macros to set up storage allocation and basic types for libart - functions. */ - -#ifndef __ART_MISC_H__ -#define __ART_MISC_H__ - -#define DEBUG 1 - -#include <stdio.h> -#include <stdlib.h> -#include <assert.h> -#include <string.h> -#include <math.h> - -typedef unsigned char byte; -typedef unsigned short uint16; -typedef unsigned int uint32; -typedef unsigned int uint; -typedef short int16; -typedef int int32; - -typedef byte art_u8; -typedef uint16 art_u16; -typedef uint32 art_u32; - -#define FLIP_NONE 0 - -#define BS_ASSERT(x) assert(x) -#define error(x) assert(0) -#define BS_LOG_ERRORLN(x) assert(0) - -#define BS_ARGB(A,R,G,B) (((A) << 24) | ((R) << 16) | ((G) << 8) | (B)) - -/* These aren't, strictly speaking, configuration macros, but they're - damn handy to have around, and may be worth playing with for - debugging. */ -#define art_new(type, n) ((type *)malloc ((n) * sizeof(type))) - -#define art_renew(p, type, n) ((type *)realloc (p, (n) * sizeof(type))) - -/* This one must be used carefully - in particular, p and max should - be variables. They can also be pstruct->el lvalues. */ -#define art_expand(p, type, max) do { if(max) { p = art_renew (p, type, max <<= 1); } else { max = 1; p = art_new(type, 1); } } while (0) - -typedef int art_boolean; -#define ART_FALSE 0 -#define ART_TRUE 1 - -/* define pi */ -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif /* M_PI */ - -#ifndef M_SQRT2 -#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ -#endif /* M_SQRT2 */ - -/* Provide macros to feature the GCC function attribute. - */ -#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)) -#define ART_GNUC_PRINTF( format_idx, arg_idx ) \ - __attribute__((__format__ (__printf__, format_idx, arg_idx))) -#define ART_GNUC_NORETURN \ - __attribute__((__noreturn__)) -#else /* !__GNUC__ */ -#define ART_GNUC_PRINTF( format_idx, arg_idx ) -#define ART_GNUC_NORETURN -#endif /* !__GNUC__ */ - -void ART_GNUC_NORETURN -art_die(const char *fmt, ...) ART_GNUC_PRINTF(1, 2); - -void -art_warn(const char *fmt, ...) ART_GNUC_PRINTF(1, 2); - -#define ART_USE_NEW_INTERSECTOR - -typedef struct _ArtDRect ArtDRect; -typedef struct _ArtIRect ArtIRect; - -struct _ArtDRect { - /*< public >*/ - double x0, y0, x1, y1; -}; - -struct _ArtIRect { - /*< public >*/ - int x0, y0, x1, y1; -}; - -typedef struct _ArtPoint ArtPoint; - -struct _ArtPoint { - /*< public >*/ - double x, y; -}; - -/* Basic data structures and constructors for sorted vector paths */ - -typedef struct _ArtSVP ArtSVP; -typedef struct _ArtSVPSeg ArtSVPSeg; - -struct _ArtSVPSeg { - int n_points; - int dir; /* == 0 for "up", 1 for "down" */ - ArtDRect bbox; - ArtPoint *points; -}; - -struct _ArtSVP { - int n_segs; - ArtSVPSeg segs[1]; -}; - -void -art_svp_free(ArtSVP *svp); - -int -art_svp_seg_compare(const void *s1, const void *s2); - -/* Basic data structures and constructors for bezier paths */ - -typedef enum { - ART_MOVETO, - ART_MOVETO_OPEN, - ART_CURVETO, - ART_LINETO, - ART_END -} ArtPathcode; - -typedef struct _ArtBpath ArtBpath; - -struct _ArtBpath { - /*< public >*/ - ArtPathcode code; - double x1; - double y1; - double x2; - double y2; - double x3; - double y3; -}; - -/* Basic data structures and constructors for simple vector paths */ - -typedef struct _ArtVpath ArtVpath; - -/* CURVETO is not allowed! */ -struct _ArtVpath { - ArtPathcode code; - double x; - double y; -}; - -/* Some of the functions need to go into their own modules */ - -void -art_vpath_add_point(ArtVpath **p_vpath, int *pn_points, int *pn_points_max, - ArtPathcode code, double x, double y); - -ArtVpath *art_bez_path_to_vec(const ArtBpath *bez, double flatness); - -#endif /* __ART_MISC_H__ */ diff --git a/engines/sword25/tools/swfdisplay/art_svp_intersect.cpp b/engines/sword25/tools/swfdisplay/art_svp_intersect.cpp deleted file mode 100644 index 56164996b6..0000000000 --- a/engines/sword25/tools/swfdisplay/art_svp_intersect.cpp +++ /dev/null @@ -1,1329 +0,0 @@ -/* Libart_LGPL - library of basic graphic primitives - * Copyright (C) 2001 Raph Levien - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* This file contains a testbed implementation of the new intersection - code. -*/ - -#include "art.h" -#include "art_svp_intersect.h" - -#include <math.h> /* for sqrt */ - -/* This can be used in production, to prevent hangs. Eventually, it - should not be necessary. */ -#define CHEAP_SANITYCHECK - -/* A priority queue - perhaps move to a separate file if it becomes - needed somewhere else */ - -#define ART_PRIQ_USE_HEAP - -typedef struct _ArtPriQ ArtPriQ; -typedef struct _ArtPriPoint ArtPriPoint; - -struct _ArtPriQ { - int n_items; - int n_items_max; - ArtPriPoint **items; -}; - -struct _ArtPriPoint { - double x; - double y; - void *user_data; -}; - -static ArtPriQ * -art_pri_new(void) { - ArtPriQ *result = art_new(ArtPriQ, 1); - - result->n_items = 0; - result->n_items_max = 16; - result->items = art_new(ArtPriPoint *, result->n_items_max); - return result; -} - -static void -art_pri_free(ArtPriQ *pq) { - free(pq->items); - free(pq); -} - -static art_boolean -art_pri_empty(ArtPriQ *pq) { - return pq->n_items == 0; -} - -#ifdef ART_PRIQ_USE_HEAP - -/* This heap implementation is based on Vasek Chvatal's course notes: - http://www.cs.rutgers.edu/~chvatal/notes/pq.html#heap */ - -static void -art_pri_bubble_up(ArtPriQ *pq, int vacant, ArtPriPoint *missing) { - ArtPriPoint **items = pq->items; - int parent; - - parent = (vacant - 1) >> 1; - while (vacant > 0 && (missing->y < items[parent]->y || - (missing->y == items[parent]->y && - missing->x < items[parent]->x))) { - items[vacant] = items[parent]; - vacant = parent; - parent = (vacant - 1) >> 1; - } - - items[vacant] = missing; -} - -static void -art_pri_insert(ArtPriQ *pq, ArtPriPoint *point) { - if (pq->n_items == pq->n_items_max) - art_expand(pq->items, ArtPriPoint *, pq->n_items_max); - - art_pri_bubble_up(pq, pq->n_items++, point); -} - -static void -art_pri_sift_down_from_root(ArtPriQ *pq, ArtPriPoint *missing) { - ArtPriPoint **items = pq->items; - int vacant = 0, child = 2; - int n = pq->n_items; - - while (child < n) { - if (items[child - 1]->y < items[child]->y || - (items[child - 1]->y == items[child]->y && - items[child - 1]->x < items[child]->x)) - child--; - items[vacant] = items[child]; - vacant = child; - child = (vacant + 1) << 1; - } - if (child == n) { - items[vacant] = items[n - 1]; - vacant = n - 1; - } - - art_pri_bubble_up(pq, vacant, missing); -} - -static ArtPriPoint * -art_pri_choose(ArtPriQ *pq) { - ArtPriPoint *result = pq->items[0]; - - art_pri_sift_down_from_root(pq, pq->items[--pq->n_items]); - return result; -} - -#else - -/* Choose least point in queue */ -static ArtPriPoint * -art_pri_choose(ArtPriQ *pq) { - int i; - int best = 0; - double best_x, best_y; - double y; - ArtPriPoint *result; - - if (pq->n_items == 0) - return NULL; - - best_x = pq->items[best]->x; - best_y = pq->items[best]->y; - - for (i = 1; i < pq->n_items; i++) { - y = pq->items[i]->y; - if (y < best_y || (y == best_y && pq->items[i]->x < best_x)) { - best = i; - best_x = pq->items[best]->x; - best_y = y; - } - } - result = pq->items[best]; - pq->items[best] = pq->items[--pq->n_items]; - return result; -} - -static void -art_pri_insert(ArtPriQ *pq, ArtPriPoint *point) { - if (pq->n_items == pq->n_items_max) - art_expand(pq->items, ArtPriPoint *, pq->n_items_max); - - pq->items[pq->n_items++] = point; -} - -#endif - -/* A virtual class for an "svp writer". A client of this object creates an - SVP by repeatedly calling "add segment" and "add point" methods on it. -*/ - -typedef struct _ArtSvpWriterRewind ArtSvpWriterRewind; - -/* An implementation of the svp writer virtual class that applies the - winding rule. */ - -struct _ArtSvpWriterRewind { - ArtSvpWriter super; - ArtWindRule rule; - ArtSVP *svp; - int n_segs_max; - int *n_points_max; -}; - -static int -art_svp_writer_rewind_add_segment(ArtSvpWriter *self, int wind_left, - int delta_wind, double x, double y) { - ArtSvpWriterRewind *swr = (ArtSvpWriterRewind *)self; - ArtSVP *svp; - ArtSVPSeg *seg; - art_boolean left_filled, right_filled; - int wind_right = wind_left + delta_wind; - int seg_num; - const int init_n_points_max = 4; - - switch (swr->rule) { - case ART_WIND_RULE_NONZERO: - left_filled = (wind_left != 0); - right_filled = (wind_right != 0); - break; - case ART_WIND_RULE_INTERSECT: - left_filled = (wind_left > 1); - right_filled = (wind_right > 1); - break; - case ART_WIND_RULE_ODDEVEN: - left_filled = (wind_left & 1); - right_filled = (wind_right & 1); - break; - case ART_WIND_RULE_POSITIVE: - left_filled = (wind_left > 0); - right_filled = (wind_right > 0); - break; - default: - art_die("Unknown wind rule %d\n", swr->rule); - } - if (left_filled == right_filled) { - /* discard segment now */ - return -1; - } - - svp = swr->svp; - seg_num = svp->n_segs++; - if (swr->n_segs_max == seg_num) { - swr->n_segs_max <<= 1; - svp = (ArtSVP *)realloc(svp, sizeof(ArtSVP) + - (swr->n_segs_max - 1) * - sizeof(ArtSVPSeg)); - swr->svp = svp; - swr->n_points_max = art_renew(swr->n_points_max, int, - swr->n_segs_max); - } - seg = &svp->segs[seg_num]; - seg->n_points = 1; - seg->dir = right_filled; - swr->n_points_max[seg_num] = init_n_points_max; - seg->bbox.x0 = x; - seg->bbox.y0 = y; - seg->bbox.x1 = x; - seg->bbox.y1 = y; - seg->points = art_new(ArtPoint, init_n_points_max); - seg->points[0].x = x; - seg->points[0].y = y; - return seg_num; -} - -static void -art_svp_writer_rewind_add_point(ArtSvpWriter *self, int seg_id, - double x, double y) { - ArtSvpWriterRewind *swr = (ArtSvpWriterRewind *)self; - ArtSVPSeg *seg; - int n_points; - - if (seg_id < 0) - /* omitted segment */ - return; - - seg = &swr->svp->segs[seg_id]; - n_points = seg->n_points++; - if (swr->n_points_max[seg_id] == n_points) - art_expand(seg->points, ArtPoint, swr->n_points_max[seg_id]); - seg->points[n_points].x = x; - seg->points[n_points].y = y; - if (x < seg->bbox.x0) - seg->bbox.x0 = x; - if (x > seg->bbox.x1) - seg->bbox.x1 = x; - seg->bbox.y1 = y; -} - -static void -art_svp_writer_rewind_close_segment(ArtSvpWriter *self, int seg_id) { - /* Not needed for this simple implementation. A potential future - optimization is to merge segments that can be merged safely. */ -} - -ArtSVP * -art_svp_writer_rewind_reap(ArtSvpWriter *self) { - ArtSvpWriterRewind *swr = (ArtSvpWriterRewind *)self; - ArtSVP *result = swr->svp; - - free(swr->n_points_max); - free(swr); - return result; -} - -ArtSvpWriter * -art_svp_writer_rewind_new(ArtWindRule rule) { - ArtSvpWriterRewind *result = art_new(ArtSvpWriterRewind, 1); - - result->super.add_segment = art_svp_writer_rewind_add_segment; - result->super.add_point = art_svp_writer_rewind_add_point; - result->super.close_segment = art_svp_writer_rewind_close_segment; - - result->rule = rule; - result->n_segs_max = 16; - result->svp = (ArtSVP *)malloc(sizeof(ArtSVP) + - (result->n_segs_max - 1) * sizeof(ArtSVPSeg)); - result->svp->n_segs = 0; - result->n_points_max = art_new(int, result->n_segs_max); - - return &result->super; -} - -/* Now, data structures for the active list */ - -typedef struct _ArtActiveSeg ArtActiveSeg; - -/* Note: BNEG is 1 for \ lines, and 0 for /. Thus, - x[(flags & BNEG) ^ 1] <= x[flags & BNEG] */ -#define ART_ACTIVE_FLAGS_BNEG 1 - -/* This flag is set if the segment has been inserted into the active - list. */ -#define ART_ACTIVE_FLAGS_IN_ACTIVE 2 - -/* This flag is set when the segment is to be deleted in the - horiz commit process. */ -#define ART_ACTIVE_FLAGS_DEL 4 - -/* This flag is set if the seg_id is a valid output segment. */ -#define ART_ACTIVE_FLAGS_OUT 8 - -/* This flag is set if the segment is in the horiz list. */ -#define ART_ACTIVE_FLAGS_IN_HORIZ 16 - -struct _ArtActiveSeg { - int flags; - int wind_left, delta_wind; - ArtActiveSeg *left, *right; /* doubly linked list structure */ - - const ArtSVPSeg *in_seg; - int in_curs; - - double x[2]; - double y0, y1; - double a, b, c; /* line equation; ax+by+c = 0 for the line, a^2 + b^2 = 1, - and a>0 */ - - /* bottom point and intersection point stack */ - int n_stack; - int n_stack_max; - ArtPoint *stack; - - /* horiz commit list */ - ArtActiveSeg *horiz_left, *horiz_right; - double horiz_x; - int horiz_delta_wind; - int seg_id; -}; - -typedef struct _ArtIntersectCtx ArtIntersectCtx; - -struct _ArtIntersectCtx { - const ArtSVP *in; - ArtSvpWriter *out; - - ArtPriQ *pq; - - ArtActiveSeg *active_head; - - double y; - ArtActiveSeg *horiz_first; - ArtActiveSeg *horiz_last; - - /* segment index of next input segment to be added to pri q */ - int in_curs; -}; - -#define EPSILON_A 1e-5 /* Threshold for breaking lines at point insertions */ - -/** - * art_svp_intersect_setup_seg: Set up an active segment from input segment. - * @seg: Active segment. - * @pri_pt: Priority queue point to initialize. - * - * Sets the x[], a, b, c, flags, and stack fields according to the - * line from the current cursor value. Sets the priority queue point - * to the bottom point of this line. Also advances the input segment - * cursor. - **/ -static void -art_svp_intersect_setup_seg(ArtActiveSeg *seg, ArtPriPoint *pri_pt) { - const ArtSVPSeg *in_seg = seg->in_seg; - int in_curs = seg->in_curs++; - double x0, y0, x1, y1; - double dx, dy, s; - double a, b, r2; - - x0 = in_seg->points[in_curs].x; - y0 = in_seg->points[in_curs].y; - x1 = in_seg->points[in_curs + 1].x; - y1 = in_seg->points[in_curs + 1].y; - pri_pt->x = x1; - pri_pt->y = y1; - dx = x1 - x0; - dy = y1 - y0; - r2 = dx * dx + dy * dy; - s = r2 == 0 ? 1 : 1 / sqrt(r2); - seg->a = a = dy * s; - seg->b = b = -dx * s; - seg->c = -(a * x0 + b * y0); - seg->flags = (seg->flags & ~ART_ACTIVE_FLAGS_BNEG) | (dx > 0); - seg->x[0] = x0; - seg->x[1] = x1; - seg->y0 = y0; - seg->y1 = y1; - seg->n_stack = 1; - seg->stack[0].x = x1; - seg->stack[0].y = y1; -} - -/** - * art_svp_intersect_add_horiz: Add point to horizontal list. - * @ctx: Intersector context. - * @seg: Segment with point to insert into horizontal list. - * - * Inserts @seg into horizontal list, keeping it in ascending horiz_x - * order. - * - * Note: the horiz_commit routine processes "clusters" of segs in the - * horiz list, all sharing the same horiz_x value. The cluster is - * processed in active list order, rather than horiz list order. Thus, - * the order of segs in the horiz list sharing the same horiz_x - * _should_ be irrelevant. Even so, we use b as a secondary sorting key, - * as a "belt and suspenders" defensive coding tactic. - **/ -static void -art_svp_intersect_add_horiz(ArtIntersectCtx *ctx, ArtActiveSeg *seg) { - ArtActiveSeg **pp = &ctx->horiz_last; - ArtActiveSeg *place; - ArtActiveSeg *place_right = NULL; - - -#ifdef CHEAP_SANITYCHECK - if (seg->flags & ART_ACTIVE_FLAGS_IN_HORIZ) { - art_warn("*** attempt to put segment in horiz list twice\n"); - return; - } - seg->flags |= ART_ACTIVE_FLAGS_IN_HORIZ; -#endif - - for (place = *pp; place != NULL && (place->horiz_x > seg->horiz_x || - (place->horiz_x == seg->horiz_x && - place->b < seg->b)); - place = *pp) { - place_right = place; - pp = &place->horiz_left; - } - *pp = seg; - seg->horiz_left = place; - seg->horiz_right = place_right; - if (place == NULL) - ctx->horiz_first = seg; - else - place->horiz_right = seg; -} - -static void -art_svp_intersect_push_pt(ArtIntersectCtx *ctx, ArtActiveSeg *seg, - double x, double y) { - ArtPriPoint *pri_pt; - int n_stack = seg->n_stack; - - if (n_stack == seg->n_stack_max) - art_expand(seg->stack, ArtPoint, seg->n_stack_max); - seg->stack[n_stack].x = x; - seg->stack[n_stack].y = y; - seg->n_stack++; - - seg->x[1] = x; - seg->y1 = y; - - pri_pt = art_new(ArtPriPoint, 1); - pri_pt->x = x; - pri_pt->y = y; - pri_pt->user_data = seg; - art_pri_insert(ctx->pq, pri_pt); -} - -typedef enum { - ART_BREAK_LEFT = 1, - ART_BREAK_RIGHT = 2 -} ArtBreakFlags; - -/** - * art_svp_intersect_break: Break an active segment. - * - * Note: y must be greater than the top point's y, and less than - * the bottom's. - * - * Return value: x coordinate of break point. - */ -static double -art_svp_intersect_break(ArtIntersectCtx *ctx, ArtActiveSeg *seg, - double x_ref, double y, ArtBreakFlags break_flags) { - double x0, y0, x1, y1; - const ArtSVPSeg *in_seg = seg->in_seg; - int in_curs = seg->in_curs; - double x; - - x0 = in_seg->points[in_curs - 1].x; - y0 = in_seg->points[in_curs - 1].y; - x1 = in_seg->points[in_curs].x; - y1 = in_seg->points[in_curs].y; - x = x0 + (x1 - x0) * ((y - y0) / (y1 - y0)); - if ((break_flags == ART_BREAK_LEFT && x > x_ref) || - (break_flags == ART_BREAK_RIGHT && x < x_ref)) { - } - - /* I think we can count on min(x0, x1) <= x <= max(x0, x1) with sane - arithmetic, but it might be worthwhile to check just in case. */ - - if (y > ctx->y) - art_svp_intersect_push_pt(ctx, seg, x, y); - else { - seg->x[0] = x; - seg->y0 = y; - seg->horiz_x = x; - art_svp_intersect_add_horiz(ctx, seg); - } - - return x; -} - -/** - * art_svp_intersect_add_point: Add a point, breaking nearby neighbors. - * @ctx: Intersector context. - * @x: X coordinate of point to add. - * @y: Y coordinate of point to add. - * @seg: "nearby" segment, or NULL if leftmost. - * - * Return value: Segment immediately to the left of the new point, or - * NULL if the new point is leftmost. - **/ -static ArtActiveSeg * -art_svp_intersect_add_point(ArtIntersectCtx *ctx, double x, double y, - ArtActiveSeg *seg, ArtBreakFlags break_flags) { - ArtActiveSeg *left, *right; - double x_min = x, x_max = x; - art_boolean left_live, right_live; - double d; - double new_x; - ArtActiveSeg *test, *result = NULL; - double x_test; - - left = seg; - if (left == NULL) - right = ctx->active_head; - else - right = left->right; - left_live = (break_flags & ART_BREAK_LEFT) && (left != NULL); - right_live = (break_flags & ART_BREAK_RIGHT) && (right != NULL); - while (left_live || right_live) { - if (left_live) { - if (x <= left->x[left->flags & ART_ACTIVE_FLAGS_BNEG] && - /* It may be that one of these conjuncts turns out to be always - true. We test both anyway, to be defensive. */ - y != left->y0 && y < left->y1) { - d = x_min * left->a + y * left->b + left->c; - if (d < EPSILON_A) { - new_x = art_svp_intersect_break(ctx, left, x_min, y, - ART_BREAK_LEFT); - if (new_x > x_max) { - x_max = new_x; - right_live = (right != NULL); - } else if (new_x < x_min) - x_min = new_x; - left = left->left; - left_live = (left != NULL); - } else - left_live = ART_FALSE; - } else - left_live = ART_FALSE; - } else if (right_live) { - if (x >= right->x[(right->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1] && - /* It may be that one of these conjuncts turns out to be always - true. We test both anyway, to be defensive. */ - y != right->y0 && y < right->y1) { - d = x_max * right->a + y * right->b + right->c; - if (d > -EPSILON_A) { - new_x = art_svp_intersect_break(ctx, right, x_max, y, - ART_BREAK_RIGHT); - if (new_x < x_min) { - x_min = new_x; - left_live = (left != NULL); - } else if (new_x >= x_max) - x_max = new_x; - right = right->right; - right_live = (right != NULL); - } else - right_live = ART_FALSE; - } else - right_live = ART_FALSE; - } - } - - /* Ascending order is guaranteed by break_flags. Thus, we don't need - to actually fix up non-ascending pairs. */ - - /* Now, (left, right) defines an interval of segments broken. Sort - into ascending x order. */ - test = left == NULL ? ctx->active_head : left->right; - result = left; - if (test != NULL && test != right) { - if (y == test->y0) - x_test = test->x[0]; - else /* assert y == test->y1, I think */ - x_test = test->x[1]; - for (;;) { - if (x_test <= x) - result = test; - test = test->right; - if (test == right) - break; - new_x = x_test; - if (new_x < x_test) { - art_warn("art_svp_intersect_add_point: non-ascending x\n"); - } - x_test = new_x; - } - } - return result; -} - -static void -art_svp_intersect_swap_active(ArtIntersectCtx *ctx, - ArtActiveSeg *left_seg, ArtActiveSeg *right_seg) { - right_seg->left = left_seg->left; - if (right_seg->left != NULL) - right_seg->left->right = right_seg; - else - ctx->active_head = right_seg; - left_seg->right = right_seg->right; - if (left_seg->right != NULL) - left_seg->right->left = left_seg; - left_seg->left = right_seg; - right_seg->right = left_seg; -} - -/** - * art_svp_intersect_test_cross: Test crossing of a pair of active segments. - * @ctx: Intersector context. - * @left_seg: Left segment of the pair. - * @right_seg: Right segment of the pair. - * @break_flags: Flags indicating whether to break neighbors. - * - * Tests crossing of @left_seg and @right_seg. If there is a crossing, - * inserts the intersection point into both segments. - * - * Return value: True if the intersection took place at the current - * scan line, indicating further iteration is needed. - **/ -static art_boolean -art_svp_intersect_test_cross(ArtIntersectCtx *ctx, - ArtActiveSeg *left_seg, ArtActiveSeg *right_seg, - ArtBreakFlags break_flags) { - double left_x0, left_y0, left_x1; - double left_y1 = left_seg->y1; - double right_y1 = right_seg->y1; - double d; - - const ArtSVPSeg *in_seg; - int in_curs; - double d0, d1, t; - double x, y; /* intersection point */ - - if (left_seg->y0 == right_seg->y0 && left_seg->x[0] == right_seg->x[0]) { - /* Top points of left and right segments coincide. This case - feels like a bit of duplication - we may want to merge it - with the cases below. However, this way, we're sure that this - logic makes only localized changes. */ - - if (left_y1 < right_y1) { - /* Test left (x1, y1) against right segment */ - left_x1 = left_seg->x[1]; - - if (left_x1 < - right_seg->x[(right_seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1] || - left_y1 == right_seg->y0) - return ART_FALSE; - d = left_x1 * right_seg->a + left_y1 * right_seg->b + right_seg->c; - if (d < -EPSILON_A) - return ART_FALSE; - else if (d < EPSILON_A) { - /* I'm unsure about the break flags here. */ - double right_x1 = art_svp_intersect_break(ctx, right_seg, - left_x1, left_y1, - ART_BREAK_RIGHT); - if (left_x1 <= right_x1) - return ART_FALSE; - } - } else if (left_y1 > right_y1) { - /* Test right (x1, y1) against left segment */ - double right_x1 = right_seg->x[1]; - - if (right_x1 > left_seg->x[left_seg->flags & ART_ACTIVE_FLAGS_BNEG] || - right_y1 == left_seg->y0) - return ART_FALSE; - d = right_x1 * left_seg->a + right_y1 * left_seg->b + left_seg->c; - if (d > EPSILON_A) - return ART_FALSE; - else if (d > -EPSILON_A) { - /* See above regarding break flags. */ - left_x1 = art_svp_intersect_break(ctx, left_seg, - right_x1, right_y1, - ART_BREAK_LEFT); - if (left_x1 <= right_x1) - return ART_FALSE; - } - } else { /* left_y1 == right_y1 */ - left_x1 = left_seg->x[1]; - double right_x1 = right_seg->x[1]; - - if (left_x1 <= right_x1) - return ART_FALSE; - } - art_svp_intersect_swap_active(ctx, left_seg, right_seg); - return ART_TRUE; - } - - if (left_y1 < right_y1) { - /* Test left (x1, y1) against right segment */ - left_x1 = left_seg->x[1]; - - if (left_x1 < - right_seg->x[(right_seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1] || - left_y1 == right_seg->y0) - return ART_FALSE; - d = left_x1 * right_seg->a + left_y1 * right_seg->b + right_seg->c; - if (d < -EPSILON_A) - return ART_FALSE; - else if (d < EPSILON_A) { - double right_x1 = art_svp_intersect_break(ctx, right_seg, - left_x1, left_y1, - ART_BREAK_RIGHT); - if (left_x1 <= right_x1) - return ART_FALSE; - } - } else if (left_y1 > right_y1) { - /* Test right (x1, y1) against left segment */ - double right_x1 = right_seg->x[1]; - - if (right_x1 > left_seg->x[left_seg->flags & ART_ACTIVE_FLAGS_BNEG] || - right_y1 == left_seg->y0) - return ART_FALSE; - d = right_x1 * left_seg->a + right_y1 * left_seg->b + left_seg->c; - if (d > EPSILON_A) - return ART_FALSE; - else if (d > -EPSILON_A) { - left_x1 = art_svp_intersect_break(ctx, left_seg, - right_x1, right_y1, - ART_BREAK_LEFT); - if (left_x1 <= right_x1) - return ART_FALSE; - } - } else { /* left_y1 == right_y1 */ - left_x1 = left_seg->x[1]; - double right_x1 = right_seg->x[1]; - - if (left_x1 <= right_x1) - return ART_FALSE; - } - - /* The segments cross. Find the intersection point. */ - - in_seg = left_seg->in_seg; - in_curs = left_seg->in_curs; - left_x0 = in_seg->points[in_curs - 1].x; - left_y0 = in_seg->points[in_curs - 1].y; - left_x1 = in_seg->points[in_curs].x; - left_y1 = in_seg->points[in_curs].y; - d0 = left_x0 * right_seg->a + left_y0 * right_seg->b + right_seg->c; - d1 = left_x1 * right_seg->a + left_y1 * right_seg->b + right_seg->c; - if (d0 == d1) { - x = left_x0; - y = left_y0; - } else { - /* Is this division always safe? It could possibly overflow. */ - t = d0 / (d0 - d1); - if (t <= 0) { - x = left_x0; - y = left_y0; - } else if (t >= 1) { - x = left_x1; - y = left_y1; - } else { - x = left_x0 + t * (left_x1 - left_x0); - y = left_y0 + t * (left_y1 - left_y0); - } - } - - /* Make sure intersection point is within bounds of right seg. */ - if (y < right_seg->y0) { - x = right_seg->x[0]; - y = right_seg->y0; - } else if (y > right_seg->y1) { - x = right_seg->x[1]; - y = right_seg->y1; - } else if (x < right_seg->x[(right_seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1]) - x = right_seg->x[(right_seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1]; - else if (x > right_seg->x[right_seg->flags & ART_ACTIVE_FLAGS_BNEG]) - x = right_seg->x[right_seg->flags & ART_ACTIVE_FLAGS_BNEG]; - - if (y == left_seg->y0) { - if (y != right_seg->y0) { - art_svp_intersect_push_pt(ctx, right_seg, x, y); - if ((break_flags & ART_BREAK_RIGHT) && right_seg->right != NULL) - art_svp_intersect_add_point(ctx, x, y, right_seg->right, - break_flags); - } else { - /* Intersection takes place at current scan line; process - immediately rather than queueing intersection point into - priq. */ - ArtActiveSeg *winner, *loser; - - /* Choose "most vertical" segement */ - if (left_seg->a > right_seg->a) { - winner = left_seg; - loser = right_seg; - } else { - winner = right_seg; - loser = left_seg; - } - - loser->x[0] = winner->x[0]; - loser->horiz_x = loser->x[0]; - loser->horiz_delta_wind += loser->delta_wind; - winner->horiz_delta_wind -= loser->delta_wind; - - art_svp_intersect_swap_active(ctx, left_seg, right_seg); - return ART_TRUE; - } - } else if (y == right_seg->y0) { - art_svp_intersect_push_pt(ctx, left_seg, x, y); - if ((break_flags & ART_BREAK_LEFT) && left_seg->left != NULL) - art_svp_intersect_add_point(ctx, x, y, left_seg->left, - break_flags); - } else { - /* Insert the intersection point into both segments. */ - art_svp_intersect_push_pt(ctx, left_seg, x, y); - art_svp_intersect_push_pt(ctx, right_seg, x, y); - if ((break_flags & ART_BREAK_LEFT) && left_seg->left != NULL) - art_svp_intersect_add_point(ctx, x, y, left_seg->left, break_flags); - if ((break_flags & ART_BREAK_RIGHT) && right_seg->right != NULL) - art_svp_intersect_add_point(ctx, x, y, right_seg->right, break_flags); - } - return ART_FALSE; -} - -/** - * art_svp_intersect_active_delete: Delete segment from active list. - * @ctx: Intersection context. - * @seg: Segment to delete. - * - * Deletes @seg from the active list. - **/ -static /* todo inline */ void -art_svp_intersect_active_delete(ArtIntersectCtx *ctx, ArtActiveSeg *seg) { - ArtActiveSeg *left = seg->left, *right = seg->right; - - if (left != NULL) - left->right = right; - else - ctx->active_head = right; - if (right != NULL) - right->left = left; -} - -/** - * art_svp_intersect_active_free: Free an active segment. - * @seg: Segment to delete. - * - * Frees @seg. - **/ -static /* todo inline */ void -art_svp_intersect_active_free(ArtActiveSeg *seg) { - free(seg->stack); - free(seg); -} - -/** - * art_svp_intersect_insert_cross: Test crossings of newly inserted line. - * - * Tests @seg against its left and right neighbors for intersections. - * Precondition: the line in @seg is not purely horizontal. - **/ -static void -art_svp_intersect_insert_cross(ArtIntersectCtx *ctx, - ArtActiveSeg *seg) { - ArtActiveSeg *left = seg, *right = seg; - - for (;;) { - if (left != NULL) { - ArtActiveSeg *leftc; - - for (leftc = left->left; leftc != NULL; leftc = leftc->left) - if (!(leftc->flags & ART_ACTIVE_FLAGS_DEL)) - break; - if (leftc != NULL && - art_svp_intersect_test_cross(ctx, leftc, left, - ART_BREAK_LEFT)) { - if (left == right || right == NULL) - right = left->right; - } else { - left = NULL; - } - } else if (right != NULL && right->right != NULL) { - ArtActiveSeg *rightc; - - for (rightc = right->right; rightc != NULL; rightc = rightc->right) - if (!(rightc->flags & ART_ACTIVE_FLAGS_DEL)) - break; - if (rightc != NULL && - art_svp_intersect_test_cross(ctx, right, rightc, - ART_BREAK_RIGHT)) { - if (left == right || left == NULL) - left = right->left; - } else { - right = NULL; - } - } else - break; - } -} - -/** - * art_svp_intersect_horiz: Add horizontal line segment. - * @ctx: Intersector context. - * @seg: Segment on which to add horizontal line. - * @x0: Old x position. - * @x1: New x position. - * - * Adds a horizontal line from @x0 to @x1, and updates the current - * location of @seg to @x1. - **/ -static void -art_svp_intersect_horiz(ArtIntersectCtx *ctx, ArtActiveSeg *seg, - double x0, double x1) { - ArtActiveSeg *hs; - - if (x0 == x1) - return; - - hs = art_new(ArtActiveSeg, 1); - - hs->flags = ART_ACTIVE_FLAGS_DEL | (seg->flags & ART_ACTIVE_FLAGS_OUT); - if (seg->flags & ART_ACTIVE_FLAGS_OUT) { - ArtSvpWriter *swr = ctx->out; - - swr->add_point(swr, seg->seg_id, x0, ctx->y); - } - hs->seg_id = seg->seg_id; - hs->horiz_x = x0; - hs->horiz_delta_wind = seg->delta_wind; - hs->stack = NULL; - - /* Ideally, the (a, b, c) values will never be read. However, there - are probably some tests remaining that don't check for _DEL - before evaluating the line equation. For those, these - initializations will at least prevent a UMR of the values, which - can crash on some platforms. */ - hs->a = 0.0; - hs->b = 0.0; - hs->c = 0.0; - - seg->horiz_delta_wind -= seg->delta_wind; - - art_svp_intersect_add_horiz(ctx, hs); - - if (x0 > x1) { - ArtActiveSeg *left; - art_boolean first = ART_TRUE; - - for (left = seg->left; left != NULL; left = seg->left) { - int left_bneg = left->flags & ART_ACTIVE_FLAGS_BNEG; - - if (left->x[left_bneg] <= x1) - break; - if (left->x[left_bneg ^ 1] <= x1 && - x1 *left->a + ctx->y *left->b + left->c >= 0) - break; - if (left->y0 != ctx->y && left->y1 != ctx->y) { - art_svp_intersect_break(ctx, left, x1, ctx->y, ART_BREAK_LEFT); - } - art_svp_intersect_swap_active(ctx, left, seg); - if (first && left->right != NULL) { - art_svp_intersect_test_cross(ctx, left, left->right, - ART_BREAK_RIGHT); - first = ART_FALSE; - } - } - } else { - ArtActiveSeg *right; - art_boolean first = ART_TRUE; - - for (right = seg->right; right != NULL; right = seg->right) { - int right_bneg = right->flags & ART_ACTIVE_FLAGS_BNEG; - - if (right->x[right_bneg ^ 1] >= x1) - break; - if (right->x[right_bneg] >= x1 && - x1 *right->a + ctx->y *right->b + right->c <= 0) - break; - if (right->y0 != ctx->y && right->y1 != ctx->y) { - art_svp_intersect_break(ctx, right, x1, ctx->y, - ART_BREAK_LEFT); - } - art_svp_intersect_swap_active(ctx, seg, right); - if (first && right->left != NULL) { - art_svp_intersect_test_cross(ctx, right->left, right, - ART_BREAK_RIGHT); - first = ART_FALSE; - } - } - } - - seg->x[0] = x1; - seg->x[1] = x1; - seg->horiz_x = x1; - seg->flags &= ~ART_ACTIVE_FLAGS_OUT; -} - -/** - * art_svp_intersect_insert_line: Insert a line into the active list. - * @ctx: Intersector context. - * @seg: Segment containing line to insert. - * - * Inserts the line into the intersector context, taking care of any - * intersections, and adding the appropriate horizontal points to the - * active list. - **/ -static void -art_svp_intersect_insert_line(ArtIntersectCtx *ctx, ArtActiveSeg *seg) { - if (seg->y1 == seg->y0) { - art_svp_intersect_horiz(ctx, seg, seg->x[0], seg->x[1]); - } else { - art_svp_intersect_insert_cross(ctx, seg); - art_svp_intersect_add_horiz(ctx, seg); - } -} - -static void -art_svp_intersect_process_intersection(ArtIntersectCtx *ctx, - ArtActiveSeg *seg) { - int n_stack = --seg->n_stack; - seg->x[1] = seg->stack[n_stack - 1].x; - seg->y1 = seg->stack[n_stack - 1].y; - seg->x[0] = seg->stack[n_stack].x; - seg->y0 = seg->stack[n_stack].y; - seg->horiz_x = seg->x[0]; - art_svp_intersect_insert_line(ctx, seg); -} - -static void -art_svp_intersect_advance_cursor(ArtIntersectCtx *ctx, ArtActiveSeg *seg, - ArtPriPoint *pri_pt) { - const ArtSVPSeg *in_seg = seg->in_seg; - int in_curs = seg->in_curs; - ArtSvpWriter *swr = seg->flags & ART_ACTIVE_FLAGS_OUT ? ctx->out : NULL; - - if (swr != NULL) - swr->add_point(swr, seg->seg_id, seg->x[1], seg->y1); - if (in_curs + 1 == in_seg->n_points) { - ArtActiveSeg *left = seg->left, *right = seg->right; - -#if 0 - if (swr != NULL) - swr->close_segment(swr, seg->seg_id); - seg->flags &= ~ART_ACTIVE_FLAGS_OUT; -#endif - seg->flags |= ART_ACTIVE_FLAGS_DEL; - art_svp_intersect_add_horiz(ctx, seg); - art_svp_intersect_active_delete(ctx, seg); - if (left != NULL && right != NULL) - art_svp_intersect_test_cross(ctx, left, right, - (ArtBreakFlags)(ART_BREAK_LEFT | ART_BREAK_RIGHT)); - free(pri_pt); - } else { - seg->horiz_x = seg->x[1]; - - art_svp_intersect_setup_seg(seg, pri_pt); - art_pri_insert(ctx->pq, pri_pt); - art_svp_intersect_insert_line(ctx, seg); - } -} - -static void -art_svp_intersect_add_seg(ArtIntersectCtx *ctx, const ArtSVPSeg *in_seg) { - ArtActiveSeg *seg = art_new(ArtActiveSeg, 1); - ArtActiveSeg *test; - double x0, y0; - ArtActiveSeg *beg_range; - ArtActiveSeg *last = NULL; - ArtActiveSeg *left, *right; - ArtPriPoint *pri_pt = art_new(ArtPriPoint, 1); - - seg->flags = 0; - seg->in_seg = in_seg; - seg->in_curs = 0; - - seg->n_stack_max = 4; - seg->stack = art_new(ArtPoint, seg->n_stack_max); - - seg->horiz_delta_wind = 0; - - seg->wind_left = 0; - - pri_pt->user_data = seg; - art_svp_intersect_setup_seg(seg, pri_pt); - art_pri_insert(ctx->pq, pri_pt); - - /* Find insertion place for new segment */ - /* This is currently a left-to-right scan, but should be replaced - with a binary search as soon as it's validated. */ - - x0 = in_seg->points[0].x; - y0 = in_seg->points[0].y; - beg_range = NULL; - for (test = ctx->active_head; test != NULL; test = test->right) { - double d; - int test_bneg = test->flags & ART_ACTIVE_FLAGS_BNEG; - - if (x0 < test->x[test_bneg]) { - if (x0 < test->x[test_bneg ^ 1]) - break; - d = x0 * test->a + y0 * test->b + test->c; - if (d < 0) - break; - } - last = test; - } - - left = art_svp_intersect_add_point(ctx, x0, y0, last, (ArtBreakFlags)(ART_BREAK_LEFT | ART_BREAK_RIGHT)); - seg->left = left; - if (left == NULL) { - right = ctx->active_head; - ctx->active_head = seg; - } else { - right = left->right; - left->right = seg; - } - seg->right = right; - if (right != NULL) - right->left = seg; - - seg->delta_wind = in_seg->dir ? 1 : -1; - seg->horiz_x = x0; - - art_svp_intersect_insert_line(ctx, seg); -} - -/** - * art_svp_intersect_horiz_commit: Commit points in horiz list to output. - * @ctx: Intersection context. - * - * The main function of the horizontal commit is to output new - * points to the output writer. - * - * This "commit" pass is also where winding numbers are assigned, - * because doing it here provides much greater tolerance for inputs - * which are not in strict SVP order. - * - * Each cluster in the horiz_list contains both segments that are in - * the active list (ART_ACTIVE_FLAGS_DEL is false) and that are not, - * and are scheduled to be deleted (ART_ACTIVE_FLAGS_DEL is true). We - * need to deal with both. - **/ -static void -art_svp_intersect_horiz_commit(ArtIntersectCtx *ctx) { - ArtActiveSeg *seg; - int winding_number = 0; /* initialization just to avoid warning */ - int horiz_wind = 0; - double last_x = 0; /* initialization just to avoid warning */ - - /* Output points to svp writer. */ - for (seg = ctx->horiz_first; seg != NULL;) { - /* Find a cluster with common horiz_x, */ - ArtActiveSeg *curs; - double x = seg->horiz_x; - - /* Generate any horizontal segments. */ - if (horiz_wind != 0) { - ArtSvpWriter *swr = ctx->out; - int seg_id; - - seg_id = swr->add_segment(swr, winding_number, horiz_wind, - last_x, ctx->y); - swr->add_point(swr, seg_id, x, ctx->y); - swr->close_segment(swr, seg_id); - } - - /* Find first active segment in cluster. */ - - for (curs = seg; curs != NULL && curs->horiz_x == x; - curs = curs->horiz_right) - if (!(curs->flags & ART_ACTIVE_FLAGS_DEL)) - break; - - if (curs != NULL && curs->horiz_x == x) { - /* There exists at least one active segment in this cluster. */ - - /* Find beginning of cluster. */ - for (; curs->left != NULL; curs = curs->left) - if (curs->left->horiz_x != x) - break; - - if (curs->left != NULL) - winding_number = curs->left->wind_left + curs->left->delta_wind; - else - winding_number = 0; - - do { - if (!(curs->flags & ART_ACTIVE_FLAGS_OUT) || - curs->wind_left != winding_number) { - ArtSvpWriter *swr = ctx->out; - - if (curs->flags & ART_ACTIVE_FLAGS_OUT) { - swr->add_point(swr, curs->seg_id, - curs->horiz_x, ctx->y); - swr->close_segment(swr, curs->seg_id); - } - - curs->seg_id = swr->add_segment(swr, winding_number, - curs->delta_wind, - x, ctx->y); - curs->flags |= ART_ACTIVE_FLAGS_OUT; - } - curs->wind_left = winding_number; - winding_number += curs->delta_wind; - curs = curs->right; - } while (curs != NULL && curs->horiz_x == x); - } - - /* Skip past cluster. */ - do { - ArtActiveSeg *next = seg->horiz_right; - - seg->flags &= ~ART_ACTIVE_FLAGS_IN_HORIZ; - horiz_wind += seg->horiz_delta_wind; - seg->horiz_delta_wind = 0; - if (seg->flags & ART_ACTIVE_FLAGS_DEL) { - if (seg->flags & ART_ACTIVE_FLAGS_OUT) { - ArtSvpWriter *swr = ctx->out; - swr->close_segment(swr, seg->seg_id); - } - art_svp_intersect_active_free(seg); - } - seg = next; - } while (seg != NULL && seg->horiz_x == x); - - last_x = x; - } - ctx->horiz_first = NULL; - ctx->horiz_last = NULL; -} - -void -art_svp_intersector(const ArtSVP *in, ArtSvpWriter *out) { - ArtIntersectCtx *ctx; - ArtPriQ *pq; - ArtPriPoint *first_point; - - if (in->n_segs == 0) - return; - - ctx = art_new(ArtIntersectCtx, 1); - ctx->in = in; - ctx->out = out; - pq = art_pri_new(); - ctx->pq = pq; - - ctx->active_head = NULL; - - ctx->horiz_first = NULL; - ctx->horiz_last = NULL; - - ctx->in_curs = 0; - first_point = art_new(ArtPriPoint, 1); - first_point->x = in->segs[0].points[0].x; - first_point->y = in->segs[0].points[0].y; - first_point->user_data = NULL; - ctx->y = first_point->y; - art_pri_insert(pq, first_point); - - while (!art_pri_empty(pq)) { - ArtPriPoint *pri_point = art_pri_choose(pq); - ArtActiveSeg *seg = (ArtActiveSeg *)pri_point->user_data; - - if (ctx->y != pri_point->y) { - art_svp_intersect_horiz_commit(ctx); - ctx->y = pri_point->y; - } - - if (seg == NULL) { - /* Insert new segment from input */ - const ArtSVPSeg *in_seg = &in->segs[ctx->in_curs++]; - art_svp_intersect_add_seg(ctx, in_seg); - if (ctx->in_curs < in->n_segs) { - const ArtSVPSeg *next_seg = &in->segs[ctx->in_curs]; - pri_point->x = next_seg->points[0].x; - pri_point->y = next_seg->points[0].y; - /* user_data is already NULL */ - art_pri_insert(pq, pri_point); - } else - free(pri_point); - } else { - int n_stack = seg->n_stack; - - if (n_stack > 1) { - art_svp_intersect_process_intersection(ctx, seg); - free(pri_point); - } else { - art_svp_intersect_advance_cursor(ctx, seg, pri_point); - } - } - } - - art_svp_intersect_horiz_commit(ctx); - - art_pri_free(pq); - free(ctx); -} diff --git a/engines/sword25/tools/swfdisplay/art_svp_intersect.h b/engines/sword25/tools/swfdisplay/art_svp_intersect.h deleted file mode 100644 index 5e70ac6d79..0000000000 --- a/engines/sword25/tools/swfdisplay/art_svp_intersect.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Libart_LGPL - library of basic graphic primitives - * Copyright (C) 2001 Raph Levien - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __ART_SVP_INTERSECT_H__ -#define __ART_SVP_INTERSECT_H__ - -/* The funky new SVP intersector. */ - -#include "art.h" - -#ifndef ART_WIND_RULE_DEFINED -#define ART_WIND_RULE_DEFINED -typedef enum { - ART_WIND_RULE_NONZERO, - ART_WIND_RULE_INTERSECT, - ART_WIND_RULE_ODDEVEN, - ART_WIND_RULE_POSITIVE -} ArtWindRule; -#endif - -typedef struct _ArtSvpWriter ArtSvpWriter; - -struct _ArtSvpWriter { - int (*add_segment)(ArtSvpWriter *self, int wind_left, int delta_wind, - double x, double y); - void (*add_point)(ArtSvpWriter *self, int seg_id, double x, double y); - void (*close_segment)(ArtSvpWriter *self, int seg_id); -}; - -ArtSvpWriter * -art_svp_writer_rewind_new(ArtWindRule rule); - -ArtSVP * -art_svp_writer_rewind_reap(ArtSvpWriter *self); - -int -art_svp_seg_compare(const void *s1, const void *s2); - -void -art_svp_intersector(const ArtSVP *in, ArtSvpWriter *out); - -#endif /* __ART_SVP_INTERSECT_H__ */ diff --git a/engines/sword25/tools/swfdisplay/art_svp_render_aa.cpp b/engines/sword25/tools/swfdisplay/art_svp_render_aa.cpp deleted file mode 100644 index 616977fb5e..0000000000 --- a/engines/sword25/tools/swfdisplay/art_svp_render_aa.cpp +++ /dev/null @@ -1,428 +0,0 @@ -/* Libart_LGPL - library of basic graphic primitives - * Copyright (C) 1998-2000 Raph Levien - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* The spiffy antialiased renderer for sorted vector paths. */ - -#include "art.h" -#include "art_svp_render_aa.h" - -#include <math.h> -#include <string.h> /* for memmove */ - -#include <stdio.h> - -typedef double artfloat; - -struct _ArtSVPRenderAAIter { - const ArtSVP *svp; - int x0, x1; - int y; - int seg_ix; - - int *active_segs; - int n_active_segs; - int *cursor; - artfloat *seg_x; - artfloat *seg_dx; - - ArtSVPRenderAAStep *steps; -}; - -static void -art_svp_render_insert_active(int i, int *active_segs, int n_active_segs, - artfloat *seg_x, artfloat *seg_dx) { - int j; - artfloat x; - int tmp1, tmp2; - - /* this is a cheap hack to get ^'s sorted correctly */ - x = seg_x[i] + 0.001 * seg_dx[i]; - for (j = 0; j < n_active_segs && seg_x[active_segs[j]] < x; j++); - - tmp1 = i; - while (j < n_active_segs) { - tmp2 = active_segs[j]; - active_segs[j] = tmp1; - tmp1 = tmp2; - j++; - } - active_segs[j] = tmp1; -} - -static void -art_svp_render_delete_active(int *active_segs, int j, int n_active_segs) { - int k; - - for (k = j; k < n_active_segs; k++) - active_segs[k] = active_segs[k + 1]; -} - -#define EPSILON 1e-6 - -/* Render the sorted vector path in the given rectangle, antialiased. - - This interface uses a callback for the actual pixel rendering. The - callback is called y1 - y0 times (once for each scan line). The y - coordinate is given as an argument for convenience (it could be - stored in the callback's private data and incremented on each - call). - - The rendered polygon is represented in a semi-runlength format: a - start value and a sequence of "steps". Each step has an x - coordinate and a value delta. The resulting value at position x is - equal to the sum of the start value and all step delta values for - which the step x coordinate is less than or equal to x. An - efficient algorithm will traverse the steps left to right, keeping - a running sum. - - All x coordinates in the steps are guaranteed to be x0 <= x < x1. - (This guarantee is a change from the gfonted vpaar renderer, and is - designed to simplify the callback). - - There is now a further guarantee that no two steps will have the - same x value. This may allow for further speedup and simplification - of renderers. - - The value 0x8000 represents 0% coverage by the polygon, while - 0xff8000 represents 100% coverage. This format is designed so that - >> 16 results in a standard 0x00..0xff value range, with nice - rounding. - - Status of this routine: - - Basic correctness: OK - - Numerical stability: pretty good, although probably not - bulletproof. - - Speed: Needs more aggressive culling of bounding boxes. Can - probably speed up the [x0,x1) clipping of step values. Can do more - of the step calculation in fixed point. - - Precision: No known problems, although it should be tested - thoroughly, especially for symmetry. - -*/ - -ArtSVPRenderAAIter * -art_svp_render_aa_iter(const ArtSVP *svp, - int x0, int y0, int x1, int y1) { - ArtSVPRenderAAIter *iter = art_new(ArtSVPRenderAAIter, 1); - - iter->svp = svp; - iter->y = y0; - iter->x0 = x0; - iter->x1 = x1; - iter->seg_ix = 0; - - iter->active_segs = art_new(int, svp->n_segs); - iter->cursor = art_new(int, svp->n_segs); - iter->seg_x = art_new(artfloat, svp->n_segs); - iter->seg_dx = art_new(artfloat, svp->n_segs); - iter->steps = art_new(ArtSVPRenderAAStep, x1 - x0); - iter->n_active_segs = 0; - - return iter; -} - -#define ADD_STEP(xpos, xdelta) \ - /* stereotype code fragment for adding a step */ \ - if (n_steps == 0 || steps[n_steps - 1].x < xpos) \ - { \ - sx = n_steps; \ - steps[sx].x = xpos; \ - steps[sx].delta = xdelta; \ - n_steps++; \ - } \ - else \ - { \ - for (sx = n_steps; sx > 0; sx--) \ - { \ - if (steps[sx - 1].x == xpos) \ - { \ - steps[sx - 1].delta += xdelta; \ - sx = n_steps; \ - break; \ - } \ - else if (steps[sx - 1].x < xpos) \ - { \ - break; \ - } \ - } \ - if (sx < n_steps) \ - { \ - memmove (&steps[sx + 1], &steps[sx], \ - (n_steps - sx) * sizeof(steps[0])); \ - steps[sx].x = xpos; \ - steps[sx].delta = xdelta; \ - n_steps++; \ - } \ - } - -void -art_svp_render_aa_iter_step(ArtSVPRenderAAIter *iter, int *p_start, - ArtSVPRenderAAStep **p_steps, int *p_n_steps) { - const ArtSVP *svp = iter->svp; - int *active_segs = iter->active_segs; - int n_active_segs = iter->n_active_segs; - int *cursor = iter->cursor; - artfloat *seg_x = iter->seg_x; - artfloat *seg_dx = iter->seg_dx; - int i = iter->seg_ix; - int j; - int x0 = iter->x0; - int x1 = iter->x1; - int y = iter->y; - int seg_index; - - int x; - ArtSVPRenderAAStep *steps = iter->steps; - int n_steps; - artfloat y_top, y_bot; - artfloat x_top, x_bot; - artfloat x_min, x_max; - int ix_min, ix_max; - artfloat delta; /* delta should be int too? */ - int last, this_; - int xdelta; - artfloat rslope, drslope; - int start; - const ArtSVPSeg *seg; - int curs; - artfloat dy; - - int sx; - - /* insert new active segments */ - for (; i < svp->n_segs && svp->segs[i].bbox.y0 < y + 1; i++) { - if (svp->segs[i].bbox.y1 > y && - svp->segs[i].bbox.x0 < x1) { - seg = &svp->segs[i]; - /* move cursor to topmost vector which overlaps [y,y+1) */ - for (curs = 0; seg->points[curs + 1].y < y; curs++); - cursor[i] = curs; - dy = seg->points[curs + 1].y - seg->points[curs].y; - if (fabs(dy) >= EPSILON) - seg_dx[i] = (seg->points[curs + 1].x - seg->points[curs].x) / - dy; - else - seg_dx[i] = 1e12; - seg_x[i] = seg->points[curs].x + - (y - seg->points[curs].y) * seg_dx[i]; - art_svp_render_insert_active(i, active_segs, n_active_segs++, - seg_x, seg_dx); - } - } - - n_steps = 0; - - /* render the runlengths, advancing and deleting as we go */ - start = 0x8000; - - for (j = 0; j < n_active_segs; j++) { - seg_index = active_segs[j]; - seg = &svp->segs[seg_index]; - curs = cursor[seg_index]; - while (curs != seg->n_points - 1 && - seg->points[curs].y < y + 1) { - y_top = y; - if (y_top < seg->points[curs].y) - y_top = seg->points[curs].y; - y_bot = y + 1; - if (y_bot > seg->points[curs + 1].y) - y_bot = seg->points[curs + 1].y; - if (y_top != y_bot) { - delta = (seg->dir ? 16711680.0 : -16711680.0) * - (y_bot - y_top); - x_top = seg_x[seg_index] + (y_top - y) * seg_dx[seg_index]; - x_bot = seg_x[seg_index] + (y_bot - y) * seg_dx[seg_index]; - if (x_top < x_bot) { - x_min = x_top; - x_max = x_bot; - } else { - x_min = x_bot; - x_max = x_top; - } - ix_min = (int)floor(x_min); - ix_max = (int)floor(x_max); - if (ix_min >= x1) { - /* skip; it starts to the right of the render region */ - } else if (ix_max < x0) - /* it ends to the left of the render region */ - start += (int)delta; - else if (ix_min == ix_max) { - /* case 1, antialias a single pixel */ - xdelta = (ix_min + 1 - (x_min + x_max) * 0.5) * delta; - - ADD_STEP(ix_min, xdelta) - - if (ix_min + 1 < x1) { - xdelta = delta - xdelta; - - ADD_STEP(ix_min + 1, xdelta) - } - } else { - /* case 2, antialias a run */ - rslope = 1.0 / fabs(seg_dx[seg_index]); - drslope = delta * rslope; - last = - drslope * 0.5 * - (ix_min + 1 - x_min) * (ix_min + 1 - x_min); - xdelta = last; - if (ix_min >= x0) { - ADD_STEP(ix_min, xdelta) - - x = ix_min + 1; - } else { - start += last; - x = x0; - } - if (ix_max > x1) - ix_max = x1; - for (; x < ix_max; x++) { - this_ = (seg->dir ? 16711680.0 : -16711680.0) * rslope * - (x + 0.5 - x_min); - xdelta = this_ - last; - last = this_; - - ADD_STEP(x, xdelta) - } - if (x < x1) { - this_ = - delta * (1 - 0.5 * - (x_max - ix_max) * (x_max - ix_max) * - rslope); - xdelta = this_ - last; - last = this_; - - ADD_STEP(x, xdelta) - - if (x + 1 < x1) { - xdelta = delta - last; - - ADD_STEP(x + 1, xdelta) - } - } - } - } - curs++; - if (curs != seg->n_points - 1 && - seg->points[curs].y < y + 1) { - dy = seg->points[curs + 1].y - seg->points[curs].y; - if (fabs(dy) >= EPSILON) - seg_dx[seg_index] = (seg->points[curs + 1].x - - seg->points[curs].x) / dy; - else - seg_dx[seg_index] = 1e12; - seg_x[seg_index] = seg->points[curs].x + - (y - seg->points[curs].y) * seg_dx[seg_index]; - } - /* break here, instead of duplicating predicate in while? */ - } - if (seg->points[curs].y >= y + 1) { - curs--; - cursor[seg_index] = curs; - seg_x[seg_index] += seg_dx[seg_index]; - } else { - art_svp_render_delete_active(active_segs, j--, - --n_active_segs); - } - } - - *p_start = start; - *p_steps = steps; - *p_n_steps = n_steps; - - iter->seg_ix = i; - iter->n_active_segs = n_active_segs; - iter->y++; -} - -void -art_svp_render_aa_iter_done(ArtSVPRenderAAIter *iter) { - free(iter->steps); - - free(iter->seg_dx); - free(iter->seg_x); - free(iter->cursor); - free(iter->active_segs); - free(iter); -} - -/** - * art_svp_render_aa: Render SVP antialiased. - * @svp: The #ArtSVP to render. - * @x0: Left coordinate of destination rectangle. - * @y0: Top coordinate of destination rectangle. - * @x1: Right coordinate of destination rectangle. - * @y1: Bottom coordinate of destination rectangle. - * @callback: The callback which actually paints the pixels. - * @callback_data: Private data for @callback. - * - * Renders the sorted vector path in the given rectangle, antialiased. - * - * This interface uses a callback for the actual pixel rendering. The - * callback is called @y1 - @y0 times (once for each scan line). The y - * coordinate is given as an argument for convenience (it could be - * stored in the callback's private data and incremented on each - * call). - * - * The rendered polygon is represented in a semi-runlength format: a - * start value and a sequence of "steps". Each step has an x - * coordinate and a value delta. The resulting value at position x is - * equal to the sum of the start value and all step delta values for - * which the step x coordinate is less than or equal to x. An - * efficient algorithm will traverse the steps left to right, keeping - * a running sum. - * - * All x coordinates in the steps are guaranteed to be @x0 <= x < @x1. - * (This guarantee is a change from the gfonted vpaar renderer from - * which this routine is derived, and is designed to simplify the - * callback). - * - * The value 0x8000 represents 0% coverage by the polygon, while - * 0xff8000 represents 100% coverage. This format is designed so that - * >> 16 results in a standard 0x00..0xff value range, with nice - * rounding. - * - **/ -void -art_svp_render_aa(const ArtSVP *svp, - int x0, int y0, int x1, int y1, - void (*callback)(void *callback_data, - int y, - int start, - ArtSVPRenderAAStep *steps, int n_steps), - void *callback_data) { - ArtSVPRenderAAIter *iter; - int y; - int start; - ArtSVPRenderAAStep *steps; - int n_steps; - - iter = art_svp_render_aa_iter(svp, x0, y0, x1, y1); - - - for (y = y0; y < y1; y++) { - art_svp_render_aa_iter_step(iter, &start, &steps, &n_steps); - (*callback)(callback_data, y, start, steps, n_steps); - } - - art_svp_render_aa_iter_done(iter); -} diff --git a/engines/sword25/tools/swfdisplay/art_svp_render_aa.h b/engines/sword25/tools/swfdisplay/art_svp_render_aa.h deleted file mode 100644 index ac4f538805..0000000000 --- a/engines/sword25/tools/swfdisplay/art_svp_render_aa.h +++ /dev/null @@ -1,55 +0,0 @@ -/* Libart_LGPL - library of basic graphic primitives - * Copyright (C) 1998 Raph Levien - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __ART_SVP_RENDER_AA_H__ -#define __ART_SVP_RENDER_AA_H__ - -/* The spiffy antialiased renderer for sorted vector paths. */ - -#include "art.h" - -typedef struct _ArtSVPRenderAAStep ArtSVPRenderAAStep; -typedef struct _ArtSVPRenderAAIter ArtSVPRenderAAIter; - -struct _ArtSVPRenderAAStep { - int x; - int delta; /* stored with 16 fractional bits */ -}; - -ArtSVPRenderAAIter * -art_svp_render_aa_iter(const ArtSVP *svp, - int x0, int y0, int x1, int y1); - -void -art_svp_render_aa_iter_step(ArtSVPRenderAAIter *iter, int *p_start, - ArtSVPRenderAAStep **p_steps, int *p_n_steps); - -void -art_svp_render_aa_iter_done(ArtSVPRenderAAIter *iter); - -void -art_svp_render_aa(const ArtSVP *svp, - int x0, int y0, int x1, int y1, - void (*callback)(void *callback_data, - int y, - int start, - ArtSVPRenderAAStep *steps, int n_steps), - void *callback_data); - -#endif /* __ART_SVP_RENDER_AA_H__ */ diff --git a/engines/sword25/tools/swfdisplay/art_svp_vpath.cpp b/engines/sword25/tools/swfdisplay/art_svp_vpath.cpp deleted file mode 100644 index e689e21e84..0000000000 --- a/engines/sword25/tools/swfdisplay/art_svp_vpath.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* Libart_LGPL - library of basic graphic primitives - * Copyright (C) 1998-2000 Raph Levien - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* Sort vector paths into sorted vector paths */ - -#include "art.h" - -#include <stdlib.h> -#include <math.h> - -/* reverse a list of points in place */ -static void -reverse_points(ArtPoint *points, int n_points) { - int i; - ArtPoint tmp_p; - - for (i = 0; i < (n_points >> 1); i++) { - tmp_p = points[i]; - points[i] = points[n_points - (i + 1)]; - points[n_points - (i + 1)] = tmp_p; - } -} - -/** - * art_svp_from_vpath: Convert a vpath to a sorted vector path. - * @vpath: #ArtVPath to convert. - * - * Converts a vector path into sorted vector path form. The svp form is - * more efficient for rendering and other vector operations. - * - * Basically, the implementation is to traverse the vector path, - * generating a new segment for each "run" of points in the vector - * path with monotonically increasing Y values. All the resulting - * values are then sorted. - * - * Note: I'm not sure that the sorting rule is correct with respect - * to numerical stability issues. - * - * Return value: Resulting sorted vector path. - **/ -ArtSVP * -art_svp_from_vpath(ArtVpath *vpath) { - int n_segs, n_segs_max; - ArtSVP *svp; - int dir; - int new_dir; - int i; - ArtPoint *points; - int n_points, n_points_max; - double x, y; - double x_min, x_max; - - n_segs = 0; - n_segs_max = 16; - svp = (ArtSVP *)malloc(sizeof(ArtSVP) + - (n_segs_max - 1) * sizeof(ArtSVPSeg)); - - dir = 0; - n_points = 0; - n_points_max = 0; - points = NULL; - i = 0; - - x = y = 0; /* unnecessary, given "first code must not be LINETO" invariant, - but it makes gcc -Wall -ansi -pedantic happier */ - x_min = x_max = 0; /* same */ - - while (vpath[i].code != ART_END) { - if (vpath[i].code == ART_MOVETO || vpath[i].code == ART_MOVETO_OPEN) { - if (points != NULL && n_points >= 2) { - if (n_segs == n_segs_max) { - n_segs_max <<= 1; - svp = (ArtSVP *)realloc(svp, sizeof(ArtSVP) + - (n_segs_max - 1) * - sizeof(ArtSVPSeg)); - } - svp->segs[n_segs].n_points = n_points; - svp->segs[n_segs].dir = (dir > 0); - if (dir < 0) - reverse_points(points, n_points); - svp->segs[n_segs].points = points; - svp->segs[n_segs].bbox.x0 = x_min; - svp->segs[n_segs].bbox.x1 = x_max; - svp->segs[n_segs].bbox.y0 = points[0].y; - svp->segs[n_segs].bbox.y1 = points[n_points - 1].y; - n_segs++; - points = NULL; - } - - if (points == NULL) { - n_points_max = 4; - points = art_new(ArtPoint, n_points_max); - } - - n_points = 1; - points[0].x = x = vpath[i].x; - points[0].y = y = vpath[i].y; - x_min = x; - x_max = x; - dir = 0; - } else { /* must be LINETO */ - new_dir = (vpath[i].y > y || - (vpath[i].y == y && vpath[i].x > x)) ? 1 : -1; - if (dir && dir != new_dir) { - /* new segment */ - x = points[n_points - 1].x; - y = points[n_points - 1].y; - if (n_segs == n_segs_max) { - n_segs_max <<= 1; - svp = (ArtSVP *)realloc(svp, sizeof(ArtSVP) + - (n_segs_max - 1) * - sizeof(ArtSVPSeg)); - } - svp->segs[n_segs].n_points = n_points; - svp->segs[n_segs].dir = (dir > 0); - if (dir < 0) - reverse_points(points, n_points); - svp->segs[n_segs].points = points; - svp->segs[n_segs].bbox.x0 = x_min; - svp->segs[n_segs].bbox.x1 = x_max; - svp->segs[n_segs].bbox.y0 = points[0].y; - svp->segs[n_segs].bbox.y1 = points[n_points - 1].y; - n_segs++; - - n_points = 1; - n_points_max = 4; - points = art_new(ArtPoint, n_points_max); - points[0].x = x; - points[0].y = y; - x_min = x; - x_max = x; - } - - if (points != NULL) { - if (n_points == n_points_max) - art_expand(points, ArtPoint, n_points_max); - points[n_points].x = x = vpath[i].x; - points[n_points].y = y = vpath[i].y; - if (x < x_min) x_min = x; - else if (x > x_max) x_max = x; - n_points++; - } - dir = new_dir; - } - i++; - } - - if (points != NULL) { - if (n_points >= 2) { - if (n_segs == n_segs_max) { - n_segs_max <<= 1; - svp = (ArtSVP *)realloc(svp, sizeof(ArtSVP) + - (n_segs_max - 1) * - sizeof(ArtSVPSeg)); - } - svp->segs[n_segs].n_points = n_points; - svp->segs[n_segs].dir = (dir > 0); - if (dir < 0) - reverse_points(points, n_points); - svp->segs[n_segs].points = points; - svp->segs[n_segs].bbox.x0 = x_min; - svp->segs[n_segs].bbox.x1 = x_max; - svp->segs[n_segs].bbox.y0 = points[0].y; - svp->segs[n_segs].bbox.y1 = points[n_points - 1].y; - n_segs++; - } else - free(points); - } - - svp->n_segs = n_segs; - - qsort(&svp->segs, n_segs, sizeof(ArtSVPSeg), art_svp_seg_compare); - - return svp; -} - diff --git a/engines/sword25/tools/swfdisplay/art_svp_vpath.h b/engines/sword25/tools/swfdisplay/art_svp_vpath.h deleted file mode 100644 index d0f5f51b28..0000000000 --- a/engines/sword25/tools/swfdisplay/art_svp_vpath.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Libart_LGPL - library of basic graphic primitives - * Copyright (C) 1998 Raph Levien - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __ART_SVP_VPATH_H__ -#define __ART_SVP_VPATH_H__ - -#include "art.h" - -/* Sort vector paths into sorted vector paths. */ - -ArtSVP * -art_svp_from_vpath(ArtVpath *vpath); - -#endif /* __ART_SVP_VPATH_H__ */ diff --git a/engines/sword25/tools/swfdisplay/art_svp_vpath_stroke.cpp b/engines/sword25/tools/swfdisplay/art_svp_vpath_stroke.cpp deleted file mode 100644 index 66cf3b783c..0000000000 --- a/engines/sword25/tools/swfdisplay/art_svp_vpath_stroke.cpp +++ /dev/null @@ -1,643 +0,0 @@ -/* Libart_LGPL - library of basic graphic primitives - * Copyright (C) 1998-2000 Raph Levien - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#include "art.h" -#include "art_svp_vpath_stroke.h" - -#include <stdlib.h> -#include <math.h> - -#include "art_svp_intersect.h" -#include "art_svp_vpath.h" - -#define EPSILON 1e-6 -#define EPSILON_2 1e-12 - -#define yes_OPTIMIZE_INNER - -/* Render an arc segment starting at (xc + x0, yc + y0) to (xc + x1, - yc + y1), centered at (xc, yc), and with given radius. Both x0^2 + - y0^2 and x1^2 + y1^2 should be equal to radius^2. - - A positive value of radius means curve to the left, negative means - curve to the right. -*/ -static void -art_svp_vpath_stroke_arc(ArtVpath **p_vpath, int *pn, int *pn_max, - double xc, double yc, - double x0, double y0, - double x1, double y1, - double radius, - double flatness) { - double theta; - double th_0, th_1; - int n_pts; - int i; - double aradius; - - aradius = fabs(radius); - theta = 2 * M_SQRT2 * sqrt(flatness / aradius); - th_0 = atan2(y0, x0); - th_1 = atan2(y1, x1); - if (radius > 0) { - /* curve to the left */ - if (th_0 < th_1) th_0 += M_PI * 2; - n_pts = ceil((th_0 - th_1) / theta); - } else { - /* curve to the right */ - if (th_1 < th_0) th_1 += M_PI * 2; - n_pts = ceil((th_1 - th_0) / theta); - } -#ifdef VERBOSE - printf("start %f %f; th_0 = %f, th_1 = %f, r = %f, theta = %f\n", x0, y0, th_0, th_1, radius, theta); -#endif - art_vpath_add_point(p_vpath, pn, pn_max, - ART_LINETO, xc + x0, yc + y0); - for (i = 1; i < n_pts; i++) { - theta = th_0 + (th_1 - th_0) * i / n_pts; - art_vpath_add_point(p_vpath, pn, pn_max, - ART_LINETO, xc + cos(theta) * aradius, - yc + sin(theta) * aradius); -#ifdef VERBOSE - printf("mid %f %f\n", cos(theta) * radius, sin(theta) * radius); -#endif - } - art_vpath_add_point(p_vpath, pn, pn_max, - ART_LINETO, xc + x1, yc + y1); -#ifdef VERBOSE - printf("end %f %f\n", x1, y1); -#endif -} - -/* Assume that forw and rev are at point i0. Bring them to i1, - joining with the vector i1 - i2. - - This used to be true, but isn't now that the stroke_raw code is - filtering out (near)zero length vectors: {It so happens that all - invocations of this function maintain the precondition i1 = i0 + 1, - so we could decrease the number of arguments by one. We haven't - done that here, though.} - - forw is to the line's right and rev is to its left. - - Precondition: no zero-length vectors, otherwise a divide by - zero will happen. */ -static void -render_seg(ArtVpath **p_forw, int *pn_forw, int *pn_forw_max, - ArtVpath **p_rev, int *pn_rev, int *pn_rev_max, - ArtVpath *vpath, int i0, int i1, int i2, - ArtPathStrokeJoinType join, - double line_width, double miter_limit, double flatness) { - double dx0, dy0; - double dx1, dy1; - double dlx0, dly0; - double dlx1, dly1; - double dmx, dmy; - double dmr2; - double scale; - double cross; - -#ifdef VERBOSE - printf("join style = %d\n", join); -#endif - - /* The vectors of the lines from i0 to i1 and i1 to i2. */ - dx0 = vpath[i1].x - vpath[i0].x; - dy0 = vpath[i1].y - vpath[i0].y; - - dx1 = vpath[i2].x - vpath[i1].x; - dy1 = vpath[i2].y - vpath[i1].y; - - /* Set dl[xy]0 to the vector from i0 to i1, rotated counterclockwise - 90 degrees, and scaled to the length of line_width. */ - scale = line_width / sqrt(dx0 * dx0 + dy0 * dy0); - dlx0 = dy0 * scale; - dly0 = -dx0 * scale; - - /* Set dl[xy]1 to the vector from i1 to i2, rotated counterclockwise - 90 degrees, and scaled to the length of line_width. */ - scale = line_width / sqrt(dx1 * dx1 + dy1 * dy1); - dlx1 = dy1 * scale; - dly1 = -dx1 * scale; - -#ifdef VERBOSE - printf("%% render_seg: (%g, %g) - (%g, %g) - (%g, %g)\n", - vpath[i0].x, vpath[i0].y, - vpath[i1].x, vpath[i1].y, - vpath[i2].x, vpath[i2].y); - - printf("%% render_seg: d[xy]0 = (%g, %g), dl[xy]0 = (%g, %g)\n", - dx0, dy0, dlx0, dly0); - - printf("%% render_seg: d[xy]1 = (%g, %g), dl[xy]1 = (%g, %g)\n", - dx1, dy1, dlx1, dly1); -#endif - - /* now, forw's last point is expected to be colinear along d[xy]0 - to point i0 - dl[xy]0, and rev with i0 + dl[xy]0. */ - - /* positive for positive area (i.e. left turn) */ - cross = dx1 * dy0 - dx0 * dy1; - - dmx = (dlx0 + dlx1) * 0.5; - dmy = (dly0 + dly1) * 0.5; - dmr2 = dmx * dmx + dmy * dmy; - - if (join == ART_PATH_STROKE_JOIN_MITER && - dmr2 * miter_limit * miter_limit < line_width * line_width) - join = ART_PATH_STROKE_JOIN_BEVEL; - - /* the case when dmr2 is zero or very small bothers me - (i.e. near a 180 degree angle) - ALEX: So, we avoid the optimization when dmr2 is very small. This should - be safe since dmx/y is only used in optimization and in MITER case, and MITER - should be converted to BEVEL when dmr2 is very small. */ - if (dmr2 > EPSILON_2) { - scale = line_width * line_width / dmr2; - dmx *= scale; - dmy *= scale; - } - - if (cross *cross < EPSILON_2 && dx0 *dx1 + dy0 *dy1 >= 0) { - /* going straight */ -#ifdef VERBOSE - printf("%% render_seg: straight\n"); -#endif - art_vpath_add_point(p_forw, pn_forw, pn_forw_max, - ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0); - art_vpath_add_point(p_rev, pn_rev, pn_rev_max, - ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0); - } else if (cross > 0) { - /* left turn, forw is outside and rev is inside */ - -#ifdef VERBOSE - printf("%% render_seg: left\n"); -#endif - if ( -#ifdef NO_OPTIMIZE_INNER - 0 && -#endif - (dmr2 > EPSILON_2) && - /* check that i1 + dm[xy] is inside i0-i1 rectangle */ - (dx0 + dmx) * dx0 + (dy0 + dmy) * dy0 > 0 && - /* and that i1 + dm[xy] is inside i1-i2 rectangle */ - ((dx1 - dmx) * dx1 + (dy1 - dmy) * dy1 > 0) -#ifdef PEDANTIC_INNER - && - /* check that i1 + dl[xy]1 is inside i0-i1 rectangle */ - (dx0 + dlx1) * dx0 + (dy0 + dly1) * dy0 > 0 && - /* and that i1 + dl[xy]0 is inside i1-i2 rectangle */ - ((dx1 - dlx0) * dx1 + (dy1 - dly0) * dy1 > 0) -#endif - ) { - /* can safely add single intersection point */ - art_vpath_add_point(p_rev, pn_rev, pn_rev_max, - ART_LINETO, vpath[i1].x + dmx, vpath[i1].y + dmy); - } else { - /* need to loop-de-loop the inside */ - art_vpath_add_point(p_rev, pn_rev, pn_rev_max, - ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0); - art_vpath_add_point(p_rev, pn_rev, pn_rev_max, - ART_LINETO, vpath[i1].x, vpath[i1].y); - art_vpath_add_point(p_rev, pn_rev, pn_rev_max, - ART_LINETO, vpath[i1].x + dlx1, vpath[i1].y + dly1); - } - - if (join == ART_PATH_STROKE_JOIN_BEVEL) { - /* bevel */ - art_vpath_add_point(p_forw, pn_forw, pn_forw_max, - ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0); - art_vpath_add_point(p_forw, pn_forw, pn_forw_max, - ART_LINETO, vpath[i1].x - dlx1, vpath[i1].y - dly1); - } else if (join == ART_PATH_STROKE_JOIN_MITER) { - art_vpath_add_point(p_forw, pn_forw, pn_forw_max, - ART_LINETO, vpath[i1].x - dmx, vpath[i1].y - dmy); - } else if (join == ART_PATH_STROKE_JOIN_ROUND) - art_svp_vpath_stroke_arc(p_forw, pn_forw, pn_forw_max, - vpath[i1].x, vpath[i1].y, - -dlx0, -dly0, - -dlx1, -dly1, - line_width, - flatness); - } else { - /* right turn, rev is outside and forw is inside */ -#ifdef VERBOSE - printf("%% render_seg: right\n"); -#endif - - if ( -#ifdef NO_OPTIMIZE_INNER - 0 && -#endif - (dmr2 > EPSILON_2) && - /* check that i1 - dm[xy] is inside i0-i1 rectangle */ - (dx0 - dmx) * dx0 + (dy0 - dmy) * dy0 > 0 && - /* and that i1 - dm[xy] is inside i1-i2 rectangle */ - ((dx1 + dmx) * dx1 + (dy1 + dmy) * dy1 > 0) -#ifdef PEDANTIC_INNER - && - /* check that i1 - dl[xy]1 is inside i0-i1 rectangle */ - (dx0 - dlx1) * dx0 + (dy0 - dly1) * dy0 > 0 && - /* and that i1 - dl[xy]0 is inside i1-i2 rectangle */ - ((dx1 + dlx0) * dx1 + (dy1 + dly0) * dy1 > 0) -#endif - ) { - /* can safely add single intersection point */ - art_vpath_add_point(p_forw, pn_forw, pn_forw_max, - ART_LINETO, vpath[i1].x - dmx, vpath[i1].y - dmy); - } else { - /* need to loop-de-loop the inside */ - art_vpath_add_point(p_forw, pn_forw, pn_forw_max, - ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0); - art_vpath_add_point(p_forw, pn_forw, pn_forw_max, - ART_LINETO, vpath[i1].x, vpath[i1].y); - art_vpath_add_point(p_forw, pn_forw, pn_forw_max, - ART_LINETO, vpath[i1].x - dlx1, vpath[i1].y - dly1); - } - - if (join == ART_PATH_STROKE_JOIN_BEVEL) { - /* bevel */ - art_vpath_add_point(p_rev, pn_rev, pn_rev_max, - ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0); - art_vpath_add_point(p_rev, pn_rev, pn_rev_max, - ART_LINETO, vpath[i1].x + dlx1, vpath[i1].y + dly1); - } else if (join == ART_PATH_STROKE_JOIN_MITER) { - art_vpath_add_point(p_rev, pn_rev, pn_rev_max, - ART_LINETO, vpath[i1].x + dmx, vpath[i1].y + dmy); - } else if (join == ART_PATH_STROKE_JOIN_ROUND) - art_svp_vpath_stroke_arc(p_rev, pn_rev, pn_rev_max, - vpath[i1].x, vpath[i1].y, - dlx0, dly0, - dlx1, dly1, - -line_width, - flatness); - - } -} - -/* caps i1, under the assumption of a vector from i0 */ -static void -render_cap(ArtVpath **p_result, int *pn_result, int *pn_result_max, - ArtVpath *vpath, int i0, int i1, - ArtPathStrokeCapType cap, double line_width, double flatness) { - double dx0, dy0; - double dlx0, dly0; - double scale; - int n_pts; - int i; - - dx0 = vpath[i1].x - vpath[i0].x; - dy0 = vpath[i1].y - vpath[i0].y; - - /* Set dl[xy]0 to the vector from i0 to i1, rotated counterclockwise - 90 degrees, and scaled to the length of line_width. */ - scale = line_width / sqrt(dx0 * dx0 + dy0 * dy0); - dlx0 = dy0 * scale; - dly0 = -dx0 * scale; - -#ifdef VERBOSE - printf("cap style = %d\n", cap); -#endif - - switch (cap) { - case ART_PATH_STROKE_CAP_BUTT: - art_vpath_add_point(p_result, pn_result, pn_result_max, - ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0); - art_vpath_add_point(p_result, pn_result, pn_result_max, - ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0); - break; - case ART_PATH_STROKE_CAP_ROUND: - n_pts = ceil(M_PI / (2.0 * M_SQRT2 * sqrt(flatness / line_width))); - art_vpath_add_point(p_result, pn_result, pn_result_max, - ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0); - for (i = 1; i < n_pts; i++) { - double theta, c_th, s_th; - - theta = M_PI * i / n_pts; - c_th = cos(theta); - s_th = sin(theta); - art_vpath_add_point(p_result, pn_result, pn_result_max, - ART_LINETO, - vpath[i1].x - dlx0 * c_th - dly0 * s_th, - vpath[i1].y - dly0 * c_th + dlx0 * s_th); - } - art_vpath_add_point(p_result, pn_result, pn_result_max, - ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0); - break; - case ART_PATH_STROKE_CAP_SQUARE: - art_vpath_add_point(p_result, pn_result, pn_result_max, - ART_LINETO, - vpath[i1].x - dlx0 - dly0, - vpath[i1].y - dly0 + dlx0); - art_vpath_add_point(p_result, pn_result, pn_result_max, - ART_LINETO, - vpath[i1].x + dlx0 - dly0, - vpath[i1].y + dly0 + dlx0); - break; - } -} - -/** - * art_svp_from_vpath_raw: Stroke a vector path, raw version - * @vpath: #ArtVPath to stroke. - * @join: Join style. - * @cap: Cap style. - * @line_width: Width of stroke. - * @miter_limit: Miter limit. - * @flatness: Flatness. - * - * Exactly the same as art_svp_vpath_stroke(), except that the resulting - * stroke outline may self-intersect and have regions of winding number - * greater than 1. - * - * Return value: Resulting raw stroked outline in svp format. - **/ -ArtVpath * -art_svp_vpath_stroke_raw(ArtVpath *vpath, - ArtPathStrokeJoinType join, - ArtPathStrokeCapType cap, - double line_width, - double miter_limit, - double flatness) { - int begin_idx, end_idx; - int i; - ArtVpath *forw, *rev; - int n_forw, n_rev; - int n_forw_max, n_rev_max; - ArtVpath *result; - int n_result, n_result_max; - double half_lw = 0.5 * line_width; - int closed; - int last, this_, next, second; - double dx, dy; - - n_forw_max = 16; - forw = art_new(ArtVpath, n_forw_max); - - n_rev_max = 16; - rev = art_new(ArtVpath, n_rev_max); - - n_result = 0; - n_result_max = 16; - result = art_new(ArtVpath, n_result_max); - - for (begin_idx = 0; vpath[begin_idx].code != ART_END; begin_idx = end_idx) { - n_forw = 0; - n_rev = 0; - - closed = (vpath[begin_idx].code == ART_MOVETO); - - /* we don't know what the first point joins with until we get to the - last point and see if it's closed. So we start with the second - line in the path. - - Note: this is not strictly true (we now know it's closed from - the opening pathcode), but why fix code that isn't broken? - */ - - this_ = begin_idx; - /* skip over identical points at the beginning of the subpath */ - for (i = this_ + 1; vpath[i].code == ART_LINETO; i++) { - dx = vpath[i].x - vpath[this_].x; - dy = vpath[i].y - vpath[this_].y; - if (dx * dx + dy * dy > EPSILON_2) - break; - } - next = i; - second = next; - - /* invariant: this doesn't coincide with next */ - while (vpath[next].code == ART_LINETO) { - last = this_; - this_ = next; - /* skip over identical points after the beginning of the subpath */ - for (i = this_ + 1; vpath[i].code == ART_LINETO; i++) { - dx = vpath[i].x - vpath[this_].x; - dy = vpath[i].y - vpath[this_].y; - if (dx * dx + dy * dy > EPSILON_2) - break; - } - next = i; - if (vpath[next].code != ART_LINETO) { - /* reached end of path */ - /* make "closed" detection conform to PostScript - semantics (i.e. explicit closepath code rather than - just the fact that end of the path is the beginning) */ - if (closed && - vpath[this_].x == vpath[begin_idx].x && - vpath[this_].y == vpath[begin_idx].y) { - int j; - - /* path is closed, render join to beginning */ - render_seg(&forw, &n_forw, &n_forw_max, - &rev, &n_rev, &n_rev_max, - vpath, last, this_, second, - join, half_lw, miter_limit, flatness); - -#ifdef VERBOSE - printf("%% forw %d, rev %d\n", n_forw, n_rev); -#endif - /* do forward path */ - art_vpath_add_point(&result, &n_result, &n_result_max, - ART_MOVETO, forw[n_forw - 1].x, - forw[n_forw - 1].y); - for (j = 0; j < n_forw; j++) - art_vpath_add_point(&result, &n_result, &n_result_max, - ART_LINETO, forw[j].x, - forw[j].y); - - /* do reverse path, reversed */ - art_vpath_add_point(&result, &n_result, &n_result_max, - ART_MOVETO, rev[0].x, - rev[0].y); - for (j = n_rev - 1; j >= 0; j--) - art_vpath_add_point(&result, &n_result, &n_result_max, - ART_LINETO, rev[j].x, - rev[j].y); - } else { - /* path is open */ - int j; - - /* add to forw rather than result to ensure that - forw has at least one point. */ - render_cap(&forw, &n_forw, &n_forw_max, - vpath, last, this_, - cap, half_lw, flatness); - art_vpath_add_point(&result, &n_result, &n_result_max, - ART_MOVETO, forw[0].x, - forw[0].y); - for (j = 1; j < n_forw; j++) - art_vpath_add_point(&result, &n_result, &n_result_max, - ART_LINETO, forw[j].x, - forw[j].y); - for (j = n_rev - 1; j >= 0; j--) - art_vpath_add_point(&result, &n_result, &n_result_max, - ART_LINETO, rev[j].x, - rev[j].y); - render_cap(&result, &n_result, &n_result_max, - vpath, second, begin_idx, - cap, half_lw, flatness); - art_vpath_add_point(&result, &n_result, &n_result_max, - ART_LINETO, forw[0].x, - forw[0].y); - } - } else - render_seg(&forw, &n_forw, &n_forw_max, - &rev, &n_rev, &n_rev_max, - vpath, last, this_, next, - join, half_lw, miter_limit, flatness); - } - end_idx = next; - } - - free(forw); - free(rev); -#ifdef VERBOSE - printf("%% n_result = %d\n", n_result); -#endif - art_vpath_add_point(&result, &n_result, &n_result_max, ART_END, 0, 0); - return result; -} - -#define noVERBOSE - -#ifdef VERBOSE - -#define XOFF 50 -#define YOFF 700 - -static void -print_ps_vpath(ArtVpath *vpath) { - int i; - - for (i = 0; vpath[i].code != ART_END; i++) { - switch (vpath[i].code) { - case ART_MOVETO: - printf("%g %g moveto\n", XOFF + vpath[i].x, YOFF - vpath[i].y); - break; - case ART_LINETO: - printf("%g %g lineto\n", XOFF + vpath[i].x, YOFF - vpath[i].y); - break; - default: - break; - } - } - printf("stroke showpage\n"); -} - -static void -print_ps_svp(ArtSVP *vpath) { - int i, j; - - printf("%% begin\n"); - for (i = 0; i < vpath->n_segs; i++) { - printf("%g setgray\n", vpath->segs[i].dir ? 0.7 : 0); - for (j = 0; j < vpath->segs[i].n_points; j++) { - printf("%g %g %s\n", - XOFF + vpath->segs[i].points[j].x, - YOFF - vpath->segs[i].points[j].y, - j ? "lineto" : "moveto"); - } - printf("stroke\n"); - } - - printf("showpage\n"); -} -#endif - -/* Render a vector path into a stroked outline. - - Status of this routine: - - Basic correctness: Only miter and bevel line joins are implemented, - and only butt line caps. Otherwise, seems to be fine. - - Numerical stability: We cheat (adding random perturbation). Thus, - it seems very likely that no numerical stability problems will be - seen in practice. - - Speed: Should be pretty good. - - Precision: The perturbation fuzzes the coordinates slightly, - but not enough to be visible. */ -/** - * art_svp_vpath_stroke: Stroke a vector path. - * @vpath: #ArtVPath to stroke. - * @join: Join style. - * @cap: Cap style. - * @line_width: Width of stroke. - * @miter_limit: Miter limit. - * @flatness: Flatness. - * - * Computes an svp representing the stroked outline of @vpath. The - * width of the stroked line is @line_width. - * - * Lines are joined according to the @join rule. Possible values are - * ART_PATH_STROKE_JOIN_MITER (for mitered joins), - * ART_PATH_STROKE_JOIN_ROUND (for round joins), and - * ART_PATH_STROKE_JOIN_BEVEL (for bevelled joins). The mitered join - * is converted to a bevelled join if the miter would extend to a - * distance of more than @miter_limit * @line_width from the actual - * join point. - * - * If there are open subpaths, the ends of these subpaths are capped - * according to the @cap rule. Possible values are - * ART_PATH_STROKE_CAP_BUTT (squared cap, extends exactly to end - * point), ART_PATH_STROKE_CAP_ROUND (rounded half-circle centered at - * the end point), and ART_PATH_STROKE_CAP_SQUARE (squared cap, - * extending half @line_width past the end point). - * - * The @flatness parameter controls the accuracy of the rendering. It - * is most important for determining the number of points to use to - * approximate circular arcs for round lines and joins. In general, the - * resulting vector path will be within @flatness pixels of the "ideal" - * path containing actual circular arcs. I reserve the right to use - * the @flatness parameter to convert bevelled joins to miters for very - * small turn angles, as this would reduce the number of points in the - * resulting outline path. - * - * The resulting path is "clean" with respect to self-intersections, i.e. - * the winding number is 0 or 1 at each point. - * - * Return value: Resulting stroked outline in svp format. - **/ -ArtSVP * -art_svp_vpath_stroke(ArtVpath *vpath, - ArtPathStrokeJoinType join, - ArtPathStrokeCapType cap, - double line_width, - double miter_limit, - double flatness) { - ArtVpath *vpath_stroke; - ArtSVP *svp, *svp2; - ArtSvpWriter *swr; - - vpath_stroke = art_svp_vpath_stroke_raw(vpath, join, cap, - line_width, miter_limit, flatness); - svp = art_svp_from_vpath(vpath_stroke); - free(vpath_stroke); - - swr = art_svp_writer_rewind_new(ART_WIND_RULE_NONZERO); - art_svp_intersector(svp, swr); - - svp2 = art_svp_writer_rewind_reap(swr); - art_svp_free(svp); - return svp2; -} diff --git a/engines/sword25/tools/swfdisplay/art_svp_vpath_stroke.h b/engines/sword25/tools/swfdisplay/art_svp_vpath_stroke.h deleted file mode 100644 index d16e324a3a..0000000000 --- a/engines/sword25/tools/swfdisplay/art_svp_vpath_stroke.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Libart_LGPL - library of basic graphic primitives - * Copyright (C) 1998 Raph Levien - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __ART_SVP_VPATH_STROKE_H__ -#define __ART_SVP_VPATH_STROKE_H__ - -/* Sort vector paths into sorted vector paths. */ - -#include "art.h" - -typedef enum { - ART_PATH_STROKE_JOIN_MITER, - ART_PATH_STROKE_JOIN_ROUND, - ART_PATH_STROKE_JOIN_BEVEL -} ArtPathStrokeJoinType; - -typedef enum { - ART_PATH_STROKE_CAP_BUTT, - ART_PATH_STROKE_CAP_ROUND, - ART_PATH_STROKE_CAP_SQUARE -} ArtPathStrokeCapType; - -ArtSVP * -art_svp_vpath_stroke(ArtVpath *vpath, - ArtPathStrokeJoinType join, - ArtPathStrokeCapType cap, - double line_width, - double miter_limit, - double flatness); - -/* This version may have winding numbers exceeding 1. */ -ArtVpath * -art_svp_vpath_stroke_raw(ArtVpath *vpath, - ArtPathStrokeJoinType join, - ArtPathStrokeCapType cap, - double line_width, - double miter_limit, - double flatness); - -#endif /* __ART_SVP_VPATH_STROKE_H__ */ diff --git a/engines/sword25/tools/swfdisplay/art_vpath_bpath.cpp b/engines/sword25/tools/swfdisplay/art_vpath_bpath.cpp deleted file mode 100644 index 82f1668ff7..0000000000 --- a/engines/sword25/tools/swfdisplay/art_vpath_bpath.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* Libart_LGPL - library of basic graphic primitives - * Copyright (C) 1998 Raph Levien - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* Basic constructors and operations for bezier paths */ - -#include "art.h" - -#include <math.h> - -#define RENDER_LEVEL 4 -#define RENDER_SIZE (1 << (RENDER_LEVEL)) - -/** - * art_vpath_render_bez: Render a bezier segment into the vpath. - * @p_vpath: Where the pointer to the #ArtVpath structure is stored. - * @pn_points: Pointer to the number of points in *@p_vpath. - * @pn_points_max: Pointer to the number of points allocated. - * @x0: X coordinate of starting bezier point. - * @y0: Y coordinate of starting bezier point. - * @x1: X coordinate of first bezier control point. - * @y1: Y coordinate of first bezier control point. - * @x2: X coordinate of second bezier control point. - * @y2: Y coordinate of second bezier control point. - * @x3: X coordinate of ending bezier point. - * @y3: Y coordinate of ending bezier point. - * @flatness: Flatness control. - * - * Renders a bezier segment into the vector path, reallocating and - * updating *@p_vpath and *@pn_vpath_max as necessary. *@pn_vpath is - * incremented by the number of vector points added. - * - * This step includes (@x0, @y0) but not (@x3, @y3). - * - * The @flatness argument guides the amount of subdivision. The Adobe - * PostScript reference manual defines flatness as the maximum - * deviation between the any point on the vpath approximation and the - * corresponding point on the "true" curve, and we follow this - * definition here. A value of 0.25 should ensure high quality for aa - * rendering. -**/ -static void -art_vpath_render_bez(ArtVpath **p_vpath, int *pn, int *pn_max, - double x0, double y0, - double x1, double y1, - double x2, double y2, - double x3, double y3, - double flatness) { - double x3_0, y3_0; - double z3_0_dot; - double z1_dot, z2_dot; - double z1_perp, z2_perp; - double max_perp_sq; - - double x_m, y_m; - double xa1, ya1; - double xa2, ya2; - double xb1, yb1; - double xb2, yb2; - - /* It's possible to optimize this routine a fair amount. - - First, once the _dot conditions are met, they will also be met in - all further subdivisions. So we might recurse to a different - routine that only checks the _perp conditions. - - Second, the distance _should_ decrease according to fairly - predictable rules (a factor of 4 with each subdivision). So it might - be possible to note that the distance is within a factor of 4 of - acceptable, and subdivide once. But proving this might be hard. - - Third, at the last subdivision, x_m and y_m can be computed more - expeditiously (as in the routine above). - - Finally, if we were able to subdivide by, say 2 or 3, this would - allow considerably finer-grain control, i.e. fewer points for the - same flatness tolerance. This would speed things up downstream. - - In any case, this routine is unlikely to be the bottleneck. It's - just that I have this undying quest for more speed... - - */ - - x3_0 = x3 - x0; - y3_0 = y3 - y0; - - /* z3_0_dot is dist z0-z3 squared */ - z3_0_dot = x3_0 * x3_0 + y3_0 * y3_0; - - if (z3_0_dot < 0.001) { - /* if start and end point are almost identical, the flatness tests - * don't work properly, so fall back on testing whether both of - * the other two control points are the same as the start point, - * too. - */ - if (hypot(x1 - x0, y1 - y0) < 0.001 - && hypot(x2 - x0, y2 - y0) < 0.001) - goto nosubdivide; - else - goto subdivide; - } - - /* we can avoid subdivision if: - - z1 has distance no more than flatness from the z0-z3 line - - z1 is no more z0'ward than flatness past z0-z3 - - z1 is more z0'ward than z3'ward on the line traversing z0-z3 - - and correspondingly for z2 */ - - /* perp is distance from line, multiplied by dist z0-z3 */ - max_perp_sq = flatness * flatness * z3_0_dot; - - z1_perp = (y1 - y0) * x3_0 - (x1 - x0) * y3_0; - if (z1_perp * z1_perp > max_perp_sq) - goto subdivide; - - z2_perp = (y3 - y2) * x3_0 - (x3 - x2) * y3_0; - if (z2_perp * z2_perp > max_perp_sq) - goto subdivide; - - z1_dot = (x1 - x0) * x3_0 + (y1 - y0) * y3_0; - if (z1_dot < 0 && z1_dot * z1_dot > max_perp_sq) - goto subdivide; - - z2_dot = (x3 - x2) * x3_0 + (y3 - y2) * y3_0; - if (z2_dot < 0 && z2_dot * z2_dot > max_perp_sq) - goto subdivide; - - if (z1_dot + z1_dot > z3_0_dot) - goto subdivide; - - if (z2_dot + z2_dot > z3_0_dot) - goto subdivide; - - -nosubdivide: - /* don't subdivide */ - art_vpath_add_point(p_vpath, pn, pn_max, - ART_LINETO, x3, y3); - return; - -subdivide: - - xa1 = (x0 + x1) * 0.5; - ya1 = (y0 + y1) * 0.5; - xa2 = (x0 + 2 * x1 + x2) * 0.25; - ya2 = (y0 + 2 * y1 + y2) * 0.25; - xb1 = (x1 + 2 * x2 + x3) * 0.25; - yb1 = (y1 + 2 * y2 + y3) * 0.25; - xb2 = (x2 + x3) * 0.5; - yb2 = (y2 + y3) * 0.5; - x_m = (xa2 + xb1) * 0.5; - y_m = (ya2 + yb1) * 0.5; -#ifdef VERBOSE - printf("%g,%g %g,%g %g,%g %g,%g\n", xa1, ya1, xa2, ya2, - xb1, yb1, xb2, yb2); -#endif - art_vpath_render_bez(p_vpath, pn, pn_max, - x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, flatness); - art_vpath_render_bez(p_vpath, pn, pn_max, - x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, flatness); -} - -/** - * art_bez_path_to_vec: Create vpath from bezier path. - * @bez: Bezier path. - * @flatness: Flatness control. - * - * Creates a vector path closely approximating the bezier path defined by - * @bez. The @flatness argument controls the amount of subdivision. In - * general, the resulting vpath deviates by at most @flatness pixels - * from the "ideal" path described by @bez. - * - * Return value: Newly allocated vpath. - **/ -ArtVpath * -art_bez_path_to_vec(const ArtBpath *bez, double flatness) { - ArtVpath *vec; - int vec_n, vec_n_max; - int bez_index; - double x, y; - - vec_n = 0; - vec_n_max = RENDER_SIZE; - vec = art_new(ArtVpath, vec_n_max); - - /* Initialization is unnecessary because of the precondition that the - bezier path does not begin with LINETO or CURVETO, but is here - to make the code warning-free. */ - x = 0; - y = 0; - - bez_index = 0; - do { -#ifdef VERBOSE - printf("%s %g %g\n", - bez[bez_index].code == ART_CURVETO ? "curveto" : - bez[bez_index].code == ART_LINETO ? "lineto" : - bez[bez_index].code == ART_MOVETO ? "moveto" : - bez[bez_index].code == ART_MOVETO_OPEN ? "moveto-open" : - "end", bez[bez_index].x3, bez[bez_index].y3); -#endif - /* make sure space for at least one more code */ - if (vec_n >= vec_n_max) - art_expand(vec, ArtVpath, vec_n_max); - switch (bez[bez_index].code) { - case ART_MOVETO_OPEN: - case ART_MOVETO: - case ART_LINETO: - x = bez[bez_index].x3; - y = bez[bez_index].y3; - vec[vec_n].code = bez[bez_index].code; - vec[vec_n].x = x; - vec[vec_n].y = y; - vec_n++; - break; - case ART_END: - vec[vec_n].code = bez[bez_index].code; - vec[vec_n].x = 0; - vec[vec_n].y = 0; - vec_n++; - break; - case ART_CURVETO: -#ifdef VERBOSE - printf("%g,%g %g,%g %g,%g %g,%g\n", x, y, - bez[bez_index].x1, bez[bez_index].y1, - bez[bez_index].x2, bez[bez_index].y2, - bez[bez_index].x3, bez[bez_index].y3); -#endif - art_vpath_render_bez(&vec, &vec_n, &vec_n_max, - x, y, - bez[bez_index].x1, bez[bez_index].y1, - bez[bez_index].x2, bez[bez_index].y2, - bez[bez_index].x3, bez[bez_index].y3, - flatness); - x = bez[bez_index].x3; - y = bez[bez_index].y3; - break; - } - } while (bez[bez_index++].code != ART_END); - return vec; -} - diff --git a/engines/sword25/tools/swfdisplay/bezierrender.cpp b/engines/sword25/tools/swfdisplay/bezierrender.cpp deleted file mode 100644 index ca0051fbe3..0000000000 --- a/engines/sword25/tools/swfdisplay/bezierrender.cpp +++ /dev/null @@ -1,584 +0,0 @@ -#include <libart_lgpl/art_misc.h> -#include <libart_lgpl/art_svp.h> -#include <libart_lgpl/art_vpath.h> -#include <libart_lgpl/art_bpath.h> -#include <libart_lgpl/art_vpath_bpath.h> -#include <libart_lgpl/art_svp_vpath.h> -#include <libart_lgpl/art_svp_vpath_stroke.h> -#include <libart_lgpl/art_svp_render_aa.h> -#include <libart_lgpl/art_rgb_svp.h> -#include <libart_lgpl/art_rgb.h> - -#define SAVING 1 - -#define WIDTH 1500 -#define HEIGHT 1500 -#define BYTES_PER_PIXEL 4 /* 24 packed rgb bits */ -#define ROWSTRIDE (WIDTH*BYTES_PER_PIXEL) - - -static unsigned char *render_path (void); - -#if SAVING -static void save_buffer (unsigned char *buffer, const char *filename); - -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <png.h> -#include <stdio.h> - -/** - * pixbuf_save_to_file: - * @pixbuf: pixel buffer to save. - * @filename: file name to save the pixel buffer into. - * - * Saves the pixel buffer in the given filename under - * the .png format. Returns TRUE is succesful and FALSE - * otherwise. - * - * Copyright is to Iain Holmes and Eazel, inc for this function. - * It was stolen from nautilus-gdk-pixbuf-extensions.c but - * was originally coming from gnome-iconedit by Iain Holmes - * It was hacked by Ramiro Estrugo for Eazel, inc. - */ -static gboolean -pixbuf_save_to_file (const GdkPixbuf *pixbuf, const char *file_name) -{ - FILE *handle; - unsigned char *buffer; - gboolean has_alpha; - int width, height, depth, rowstride; - guchar *pixels; - png_structp png_ptr; - png_infop info_ptr; - png_text text[2]; - int i; - - g_return_val_if_fail (pixbuf != NULL, FALSE); - g_return_val_if_fail (file_name != NULL, FALSE); - g_return_val_if_fail (file_name[0] != '\0', FALSE); - - handle = fopen (file_name, "wb"); - if (handle == NULL) { - return FALSE; - } - - png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (png_ptr == NULL) { - fclose (handle); - return FALSE; - } - - info_ptr = png_create_info_struct (png_ptr); - if (info_ptr == NULL) { - png_destroy_write_struct (&png_ptr, (png_infopp)NULL); - fclose (handle); - return FALSE; - } - - if (setjmp (png_ptr->jmpbuf)) { - png_destroy_write_struct (&png_ptr, &info_ptr); - fclose (handle); - return FALSE; - } - - png_init_io (png_ptr, handle); - - has_alpha = gdk_pixbuf_get_has_alpha (pixbuf); - width = gdk_pixbuf_get_width (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); - depth = gdk_pixbuf_get_bits_per_sample (pixbuf); - pixels = gdk_pixbuf_get_pixels (pixbuf); - rowstride = gdk_pixbuf_get_rowstride (pixbuf); - - png_set_IHDR (png_ptr, info_ptr, width, height, - depth, PNG_COLOR_TYPE_RGB_ALPHA, - PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - - /* Some text to go with the png image */ - text[0].key = "Title"; - text[0].text = (char *) file_name; - text[0].compression = PNG_TEXT_COMPRESSION_NONE; - text[1].key = "Software"; - text[1].text = "Nautilus Thumbnail"; - text[1].compression = PNG_TEXT_COMPRESSION_NONE; - png_set_text (png_ptr, info_ptr, text, 2); - - /* Write header data */ - png_write_info (png_ptr, info_ptr); - - /* if there is no alpha in the data, allocate buffer to expand into */ - if (has_alpha) { - buffer = NULL; - } else { - buffer = (unsigned char *)g_malloc(4 * width); - } - - /* pump the raster data into libpng, one scan line at a time */ - for (i = 0; i < height; i++) { - if (has_alpha) { - png_bytep row_pointer = pixels; - png_write_row (png_ptr, row_pointer); - } else { - /* expand RGB to RGBA using an opaque alpha value */ - int x; - unsigned char *buffer_ptr = buffer; - unsigned char *source_ptr = pixels; - for (x = 0; x < width; x++) { - *buffer_ptr++ = *source_ptr++; - *buffer_ptr++ = *source_ptr++; - *buffer_ptr++ = *source_ptr++; - *buffer_ptr++ = 255; - } - png_write_row (png_ptr, (png_bytep) buffer); - } - pixels += rowstride; - } - - png_write_end (png_ptr, info_ptr); - png_destroy_write_struct (&png_ptr, &info_ptr); - - g_free (buffer); - - fclose (handle); - return TRUE; -} - -static void -save_buffer (unsigned char *buffer, const char *filename) -{ - GdkPixbuf *pixbuf; - - g_type_init(); - - pixbuf = gdk_pixbuf_new_from_data (buffer, - GDK_COLORSPACE_RGB, - TRUE, 8, - WIDTH, HEIGHT, - ROWSTRIDE, - NULL, NULL); - - pixbuf_save_to_file (pixbuf, filename); - - gdk_pixbuf_unref (pixbuf); -} - -#endif - -void -art_rgb_fill_run1 (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, gint n) -{ - int i; - - if (r == g && g == b && r == 255) - { - memset (buf, g, n + n + n + n); - } - else - { - art_u32 *alt = (art_u32 *)buf; - art_u32 color = (r << 24) | (g << 16) | (b << 8) | 0xff; - for (i = 0; i < n; i++) - *alt++ = color; - } -} - -/** - * art_rgb_run_alpha: Render semitransparent color over RGB buffer. - * @buf: Buffer for rendering. - * @r: Red, range 0..255. - * @g: Green, range 0..255. - * @b: Blue, range 0..255. - * @alpha: Alpha, range 0..256. - * @n: Number of RGB triples to render. - * - * Renders a sequential run of solid (@r, @g, @b) color over @buf with - * opacity @alpha. - **/ -void -art_rgb_run_alpha1 (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n) -{ - int i; - int v; - - for (i = 0; i < n; i++) - { - v = *buf; - *buf++ = v + (((r - v) * alpha + 0x80) >> 8); - v = *buf; - *buf++ = v + (((g - v) * alpha + 0x80) >> 8); - v = *buf; - *buf++ = v + (((b - v) * alpha + 0x80) >> 8); - v = *buf + alpha; - if (v > 255) - v = 255; - *buf++ = v; - } -} - -typedef struct _ArtRgbSVPAlphaData ArtRgbSVPAlphaData; - -struct _ArtRgbSVPAlphaData { - int alphatab[256]; - art_u8 r, g, b, alpha; - art_u8 *buf; - int rowstride; - int x0, x1; -}; - -static void -art_rgb_svp_alpha_callback1 (void *callback_data, int y, - int start, ArtSVPRenderAAStep *steps, int n_steps) -{ - ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data; - art_u8 *linebuf; - int run_x0, run_x1; - art_u32 running_sum = start; - int x0, x1; - int k; - art_u8 r, g, b; - int *alphatab; - int alpha; - - linebuf = data->buf; - x0 = data->x0; - x1 = data->x1; - - r = data->r; - g = data->g; - b = data->b; - alphatab = data->alphatab; - - if (n_steps > 0) - { - run_x1 = steps[0].x; - if (run_x1 > x0) - { - alpha = (running_sum >> 16) & 0xff; - if (alpha) - art_rgb_run_alpha1 (linebuf, - r, g, b, alphatab[alpha], - run_x1 - x0); - } - - for (k = 0; k < n_steps - 1; k++) - { - running_sum += steps[k].delta; - run_x0 = run_x1; - run_x1 = steps[k + 1].x; - if (run_x1 > run_x0) - { - alpha = (running_sum >> 16) & 0xff; - if (alpha) - art_rgb_run_alpha1 (linebuf + (run_x0 - x0) * 4, - r, g, b, alphatab[alpha], - run_x1 - run_x0); - } - } - running_sum += steps[k].delta; - if (x1 > run_x1) - { - alpha = (running_sum >> 16) & 0xff; - if (alpha) - art_rgb_run_alpha1 (linebuf + (run_x1 - x0) * 4, - r, g, b, alphatab[alpha], - x1 - run_x1); - } - } - else - { - alpha = (running_sum >> 16) & 0xff; - if (alpha) - art_rgb_run_alpha1 (linebuf, - r, g, b, alphatab[alpha], - x1 - x0); - } - - data->buf += data->rowstride; -} - -static void -art_rgb_svp_alpha_opaque_callback1 (void *callback_data, int y, - int start, - ArtSVPRenderAAStep *steps, int n_steps) -{ - ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data; - art_u8 *linebuf; - int run_x0, run_x1; - art_u32 running_sum = start; - int x0, x1; - int k; - art_u8 r, g, b; - int *alphatab; - int alpha; - - linebuf = data->buf; - x0 = data->x0; - x1 = data->x1; - - r = data->r; - g = data->g; - b = data->b; - alphatab = data->alphatab; - - if (n_steps > 0) - { - run_x1 = steps[0].x; - if (run_x1 > x0) - { - alpha = running_sum >> 16; - if (alpha) - { - if (alpha >= 255) - art_rgb_fill_run1 (linebuf, - r, g, b, - run_x1 - x0); - else - art_rgb_run_alpha1 (linebuf, - r, g, b, alphatab[alpha], - run_x1 - x0); - } - } - - for (k = 0; k < n_steps - 1; k++) - { - running_sum += steps[k].delta; - run_x0 = run_x1; - run_x1 = steps[k + 1].x; - if (run_x1 > run_x0) - { - alpha = running_sum >> 16; - if (alpha) - { - if (alpha >= 255) - art_rgb_fill_run1 (linebuf + (run_x0 - x0) * 4, - r, g, b, - run_x1 - run_x0); - else - art_rgb_run_alpha1 (linebuf + (run_x0 - x0) * 4, - r, g, b, alphatab[alpha], - run_x1 - run_x0); - } - } - } - running_sum += steps[k].delta; - if (x1 > run_x1) - { - alpha = running_sum >> 16; - if (alpha) - { - if (alpha >= 255) - art_rgb_fill_run1 (linebuf + (run_x1 - x0) * 4, - r, g, b, - x1 - run_x1); - else - art_rgb_run_alpha1 (linebuf + (run_x1 - x0) * 4, - r, g, b, alphatab[alpha], - x1 - run_x1); - } - } - } - else - { - alpha = running_sum >> 16; - if (alpha) - { - if (alpha >= 255) - art_rgb_fill_run1 (linebuf, - r, g, b, - x1 - x0); - else - art_rgb_run_alpha1 (linebuf, - r, g, b, alphatab[alpha], - x1 - x0); - } - } - - data->buf += data->rowstride; -} - -/** - * art_rgb_svp_alpha: Alpha-composite sorted vector path over RGB buffer. - * @svp: The source sorted vector path. - * @x0: Left coordinate of destination rectangle. - * @y0: Top coordinate of destination rectangle. - * @x1: Right coordinate of destination rectangle. - * @y1: Bottom coordinate of destination rectangle. - * @rgba: Color in 0xRRGGBBAA format. - * @buf: Destination RGB buffer. - * @rowstride: Rowstride of @buf buffer. - * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing. - * - * Renders the shape specified with @svp over the @buf RGB buffer. - * @x1 - @x0 specifies the width, and @y1 - @y0 specifies the height, - * of the rectangle rendered. The new pixels are stored starting at - * the first byte of @buf. Thus, the @x0 and @y0 parameters specify - * an offset within @svp, and may be tweaked as a way of doing - * integer-pixel translations without fiddling with @svp itself. - * - * The @rgba argument specifies the color for the rendering. Pixels of - * entirely 0 winding number are left untouched. Pixels of entirely - * 1 winding number have the color @rgba composited over them (ie, - * are replaced by the red, green, blue components of @rgba if the alpha - * component is 0xff). Pixels of intermediate coverage are interpolated - * according to the rule in @alphagamma, or default to linear if - * @alphagamma is NULL. - **/ -void -art_rgb_svp_alpha1 (const ArtSVP *svp, - int x0, int y0, int x1, int y1, - art_u32 rgba, - art_u8 *buf, int rowstride, - ArtAlphaGamma *alphagamma) -{ - ArtRgbSVPAlphaData data; - int r, g, b, alpha; - int i; - int a, da; - - r = rgba >> 24; - g = (rgba >> 16) & 0xff; - b = (rgba >> 8) & 0xff; - alpha = rgba & 0xff; - - data.r = r; - data.g = g; - data.b = b; - data.alpha = alpha; - - a = 0x8000; - da = (alpha * 66051 + 0x80) >> 8; /* 66051 equals 2 ^ 32 / (255 * 255) */ - - for (i = 0; i < 256; i++) - { - data.alphatab[i] = a >> 16; - a += da; - } - - data.buf = buf; - data.rowstride = rowstride; - data.x0 = x0; - data.x1 = x1; - if (alpha == 255) - art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_alpha_opaque_callback1, - &data); - else - art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_alpha_callback1, &data); -} - - - -static unsigned char * -render_path () -{ - art_u8 *buffer = NULL; - art_u32 color1 = (0xFF << 24) | (0x00 <<16) | (0x00<<8) | (0xFF) ; /* RRGGBBAA */ - art_u32 color2 = (0x00 << 24) | (0x00 <<16) | (0xFF<<8) | (0xFF) ; /* RRGGBBAA */ - - ArtBpath *bez1 = NULL; - ArtVpath *vec = NULL; - ArtSVP *svp1 = NULL; - ArtSVP *svp2 = NULL; - - bez1 = art_new (ArtBpath, 30); - bez1[0].code = ART_MOVETO; - bez1[0].x3 = 352.000000; bez1[0].y3 = 59.000000; - bez1[1].code = ART_CURVETO; - bez1[1].x1 = 396.000000; bez1[1].y1 = 41.000000; - bez1[1].x2 = 434.333333; bez1[1].y2 = 57.666667; - bez1[1].x3 = 467.000000; bez1[1].y3 = 109.000000; - bez1[2].code = ART_CURVETO; - bez1[2].x1 = 481.666667; bez1[2].y1 = 137.666667; - bez1[2].x2 = 487.666667; bez1[2].y2 = 172.000000; - bez1[2].x3 = 485.000000; bez1[2].y3 = 212.000000; - bez1[3].code = ART_LINETO; - bez1[3].x3 = 485.000000; bez1[3].y3 = 216.000000; - bez1[4].code = ART_LINETO; - bez1[4].x3 = 483.000000; bez1[4].y3 = 231.000000; - bez1[5].code = ART_LINETO; - bez1[5].x3 = 468.000000; bez1[5].y3 = 291.000000; - bez1[6].code = ART_LINETO; - bez1[6].x3 = 466.000000; bez1[6].y3 = 299.000000; - bez1[7].code = ART_LINETO; - bez1[7].x3 = 446.000000; bez1[7].y3 = 349.000000; - bez1[8].code = ART_LINETO; - bez1[8].x3 = 445.000000; bez1[8].y3 = 351.000000; - bez1[9].code = ART_CURVETO; - bez1[9].x1 = 442.333333; bez1[9].y1 = 376.333333; - bez1[9].x2 = 450.000000; bez1[9].y2 = 394.000000; - bez1[9].x3 = 468.000000; bez1[9].y3 = 404.000000; - bez1[10].code = ART_CURVETO; - bez1[10].x1 = 373.333333; bez1[10].y1 = 428.666667; - bez1[10].x2 = 294.666667; bez1[10].y2 = 426.666667; - bez1[10].x3 = 232.000000; bez1[10].y3 = 398.000000; - bez1[11].code = ART_CURVETO; - bez1[11].x1 = 249.333333; bez1[11].y1 = 380.666667; - bez1[11].x2 = 257.666667; bez1[11].y2 = 365.000000; - bez1[11].x3 = 257.000000; bez1[11].y3 = 351.000000; - bez1[12].code = ART_LINETO; - bez1[12].x3 = 255.000000; bez1[12].y3 = 345.000000; - bez1[13].code = ART_CURVETO; - bez1[13].x1 = 244.333333; bez1[13].y1 = 326.333333; - bez1[13].x2 = 236.000000; bez1[13].y2 = 307.666667; - bez1[13].x3 = 230.000000; bez1[13].y3 = 289.000000; - bez1[14].code = ART_CURVETO; - bez1[14].x1 = 223.333333; bez1[14].y1 = 270.333333; - bez1[14].x2 = 219.000000; bez1[14].y2 = 252.000000; - bez1[14].x3 = 217.000000; bez1[14].y3 = 234.000000; - bez1[15].code = ART_LINETO; - bez1[15].x3 = 216.000000; bez1[15].y3 = 233.000000; - bez1[16].code = ART_LINETO; - bez1[16].x3 = 215.000000; bez1[16].y3 = 229.000000; - bez1[17].code = ART_CURVETO; - bez1[17].x1 = 201.666667; bez1[17].y1 = 187.666667; - bez1[17].x2 = 210.666667; bez1[17].y2 = 144.000000; - bez1[17].x3 = 242.000000; bez1[17].y3 = 98.000000; - bez1[18].code = ART_CURVETO; - bez1[18].x1 = 274.000000; bez1[18].y1 = 56.000000; - bez1[18].x2 = 310.333333; bez1[18].y2 = 43.333333; - bez1[18].x3 = 351.000000; bez1[18].y3 = 60.000000; - bez1[19].code = ART_LINETO; - bez1[19].x3 = 352.000000; bez1[19].y3 = 59.000000; - bez1[20].code = ART_END; - - vec = art_bez_path_to_vec (bez1, 0.5); - svp1 = art_svp_from_vpath (vec); - - int penWidth = 5; - svp2 = art_svp_vpath_stroke(vec, ART_PATH_STROKE_JOIN_ROUND, ART_PATH_STROKE_CAP_ROUND, penWidth, 1.0, 0.5); - - - buffer = art_new (art_u8, WIDTH*HEIGHT*BYTES_PER_PIXEL); - memset(buffer, 0, WIDTH*HEIGHT*BYTES_PER_PIXEL); - art_rgb_run_alpha (buffer, 0, 0, 0, 0, WIDTH*HEIGHT); - art_rgb_svp_alpha1 (svp1, 0, 0, WIDTH, HEIGHT, color1, buffer, ROWSTRIDE, NULL); - art_rgb_svp_alpha1 (svp2, 0, 0, WIDTH, HEIGHT, color2, buffer, ROWSTRIDE, NULL); - - art_free(svp2); - art_free(svp1); - art_free(vec); - art_free(bez1); - - return (unsigned char *) buffer; -} - -int main (int argc, char *argv[]) -{ - unsigned char *buffer; - - buffer = render_path (); - -#if SAVING - save_buffer (buffer, "foo.png"); -#endif - - return 0; -} - - - - - - - diff --git a/engines/sword25/tools/swfdisplay/func.h b/engines/sword25/tools/swfdisplay/func.h deleted file mode 100644 index 251c1b4e7c..0000000000 --- a/engines/sword25/tools/swfdisplay/func.h +++ /dev/null @@ -1,542 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/common/func.h $ - * $Id: func.h 46129 2009-11-24 22:10:34Z fingolfin $ - */ - -#ifndef COMMON_FUNC_H -#define COMMON_FUNC_H - -namespace Common { - -/** - * Generic unary function. - */ -template<class Arg, class Result> -struct UnaryFunction { - typedef Arg ArgumenType; - typedef Result ResultType; -}; - -/** - * Generic binary function. - */ -template<class Arg1, class Arg2, class Result> -struct BinaryFunction { - typedef Arg1 FirstArgumentType; - typedef Arg2 SecondArgumentType; - typedef Result ResultType; -}; - -/** - * Predicate to check for equallity of two data elements. - */ -template<class T> -struct EqualTo : public BinaryFunction<T, T, bool> { - bool operator()(const T &x, const T &y) const { return x == y; } -}; - -/** - * Predicate to check for x being less than y. - */ -template<class T> -struct Less : public BinaryFunction<T, T, bool> { - bool operator()(const T &x, const T &y) const { return x < y; } -}; - -/** - * Predicate to check for x being greater than y. - */ -template<class T> -struct Greater : public BinaryFunction<T, T, bool> { - bool operator()(const T &x, const T &y) const { return x > y; } -}; - -template<class Op> -class Binder1st : public UnaryFunction<typename Op::SecondArgumentType, typename Op::ResultType> { -private: - Op _op; - typename Op::FirstArgumentType _arg1; -public: - Binder1st(const Op &op, typename Op::FirstArgumentType arg1) : _op(op), _arg1(arg1) {} - - typename Op::ResultType operator()(typename Op::SecondArgumentType v) const { - return _op(_arg1, v); - } -}; - -/** - * Transforms a binary function object into an unary function object. - * To achieve that the first parameter is bound to the passed value t. - */ -template<class Op> -inline Binder1st<Op> bind1st(const Op &op, typename Op::FirstArgumentType t) { - return Binder1st<Op>(op, t); -} - -template<class Op> -class Binder2nd : public UnaryFunction<typename Op::FirstArgumentType, typename Op::ResultType> { -private: - Op _op; - typename Op::SecondArgumentType _arg2; -public: - Binder2nd(const Op &op, typename Op::SecondArgumentType arg2) : _op(op), _arg2(arg2) {} - - typename Op::ResultType operator()(typename Op::FirstArgumentType v) const { - return _op(v, _arg2); - } -}; - -/** - * Transforms a binary function object into an unary function object. - * To achieve that the first parameter is bound to the passed value t. - */ -template<class Op> -inline Binder2nd<Op> bind2nd(const Op &op, typename Op::SecondArgumentType t) { - return Binder2nd<Op>(op, t); -} - -template<class Arg, class Result> -class PointerToUnaryFunc : public UnaryFunction<Arg, Result> { -private: - Result (*_func)(Arg); -public: - typedef Result (*FuncType)(Arg); - - PointerToUnaryFunc(const FuncType &func) : _func(func) {} - Result operator()(Arg v) const { - return _func(v); - } -}; - -template<class Arg1, class Arg2, class Result> -class PointerToBinaryFunc : public BinaryFunction<Arg1, Arg2, Result> { -private: - Result (*_func)(Arg1, Arg2); -public: - typedef Result (*FuncType)(Arg1, Arg2); - - PointerToBinaryFunc(const FuncType &func) : _func(func) {} - Result operator()(Arg1 v1, Arg2 v2) const { - return _func(v1, v2); - } -}; - -/** - * Creates an unary function object from a function pointer. - */ -template<class Arg, class Result> -inline PointerToUnaryFunc<Arg, Result> ptr_fun(Result (*func)(Arg)) { - return PointerToUnaryFunc<Arg, Result>(func); -} - -/** - * Creates an binary function object from a function pointer. - */ -template<class Arg1, class Arg2, class Result> -inline PointerToBinaryFunc<Arg1, Arg2, Result> ptr_fun(Result (*func)(Arg1, Arg2)) { - return PointerToBinaryFunc<Arg1, Arg2, Result>(func); -} - -template<class Result, class T> -class MemFunc0 : public UnaryFunction<T *, Result> { -private: - Result (T::*_func)(); -public: - typedef Result (T::*FuncType)(); - - MemFunc0(const FuncType &func) : _func(func) {} - Result operator()(T *v) const { - return (v->*_func)(); - } -}; - -template<class Result, class T> -class ConstMemFunc0 : public UnaryFunction<T *, Result> { -private: - Result (T::*_func)() const; -public: - typedef Result (T::*FuncType)() const; - - ConstMemFunc0(const FuncType &func) : _func(func) {} - Result operator()(const T *v) const { - return (v->*_func)(); - } -}; - -template<class Result, class Arg, class T> -class MemFunc1 : public BinaryFunction<T *, Arg, Result> { -private: - Result (T::*_func)(Arg); -public: - typedef Result (T::*FuncType)(Arg); - - MemFunc1(const FuncType &func) : _func(func) {} - Result operator()(T *v1, Arg v2) const { - return (v1->*_func)(v2); - } -}; - -template<class Result, class Arg, class T> -class ConstMemFunc1 : public BinaryFunction<T *, Arg, Result> { -private: - Result (T::*_func)(Arg) const; -public: - typedef Result (T::*FuncType)(Arg) const; - - ConstMemFunc1(const FuncType &func) : _func(func) {} - Result operator()(const T *v1, Arg v2) const { - return (v1->*_func)(v2); - } -}; - -/** - * Creates a unary function object from a class member function pointer. - * The parameter passed to the function object is the 'this' pointer to - * be used for the function call. - */ -template<class Result, class T> -inline MemFunc0<Result, T> mem_fun(Result (T::*f)()) { - return MemFunc0<Result, T>(f); -} - -/** - * Creates a unary function object from a class member function pointer. - * The parameter passed to the function object is the 'this' pointer to - * be used for the function call. - */ -template<class Result, class T> -inline ConstMemFunc0<Result, T> mem_fun(Result (T::*f)() const) { - return ConstMemFunc0<Result, T>(f); -} - -/** - * Creates a binary function object from a class member function pointer. - * The first parameter passed to the function object is the 'this' pointer to - * be used for the function call. - * The second one is the parameter passed to the member function. - */ -template<class Result, class Arg, class T> -inline MemFunc1<Result, Arg, T> mem_fun(Result (T::*f)(Arg)) { - return MemFunc1<Result, Arg, T>(f); -} - -/** - * Creates a binary function object from a class member function pointer. - * The first parameter passed to the function object is the 'this' pointer to - * be used for the function call. - * The second one is the parameter passed to the member function. - */ -template<class Result, class Arg, class T> -inline ConstMemFunc1<Result, Arg, T> mem_fun(Result (T::*f)(Arg) const) { - return ConstMemFunc1<Result, Arg, T>(f); -} - -template<class Result, class T> -class MemFuncRef0 : public UnaryFunction<T &, Result> { -private: - Result (T::*_func)(); -public: - typedef Result (T::*FuncType)(); - - MemFuncRef0(const FuncType &func) : _func(func) {} - Result operator()(T &v) const { - return (v.*_func)(); - } -}; - -template<class Result, class T> -class ConstMemFuncRef0 : public UnaryFunction<T &, Result> { -private: - Result (T::*_func)() const; -public: - typedef Result (T::*FuncType)() const; - - ConstMemFuncRef0(const FuncType &func) : _func(func) {} - Result operator()(const T &v) const { - return (v.*_func)(); - } -}; - -template<class Result, class Arg, class T> -class MemFuncRef1 : public BinaryFunction<T &, Arg, Result> { -private: - Result (T::*_func)(Arg); -public: - typedef Result (T::*FuncType)(Arg); - - MemFuncRef1(const FuncType &func) : _func(func) {} - Result operator()(T &v1, Arg v2) const { - return (v1.*_func)(v2); - } -}; - -template<class Result, class Arg, class T> -class ConstMemFuncRef1 : public BinaryFunction<T &, Arg, Result> { -private: - Result (T::*_func)(Arg) const; -public: - typedef Result (T::*FuncType)(Arg) const; - - ConstMemFuncRef1(const FuncType &func) : _func(func) {} - Result operator()(const T &v1, Arg v2) const { - return (v1.*_func)(v2); - } -}; - -/** - * Creates a unary function object from a class member function pointer. - * The parameter passed to the function object is the object instance to - * be used for the function call. Note unlike mem_fun, it takes a reference - * as parameter. Note unlike mem_fun, it takes a reference - * as parameter. - */ -template<class Result, class T> -inline MemFuncRef0<Result, T> mem_fun_ref(Result (T::*f)()) { - return MemFuncRef0<Result, T>(f); -} - -/** - * Creates a unary function object from a class member function pointer. - * The parameter passed to the function object is the object instance to - * be used for the function call. Note unlike mem_fun, it takes a reference - * as parameter. - */ -template<class Result, class T> -inline ConstMemFuncRef0<Result, T> mem_fun_Ref(Result (T::*f)() const) { - return ConstMemFuncRef0<Result, T>(f); -} - -/** - * Creates a binary function object from a class member function pointer. - * The first parameter passed to the function object is the object instance to - * be used for the function call. Note unlike mem_fun, it takes a reference - * as parameter. - * The second one is the parameter passed to the member function. - */ -template<class Result, class Arg, class T> -inline MemFuncRef1<Result, Arg, T> mem_fun_ref(Result (T::*f)(Arg)) { - return MemFuncRef1<Result, Arg, T>(f); -} - -/** - * Creates a binary function object from a class member function pointer. - * The first parameter passed to the function object is the object instance to - * be used for the function call. Note unlike mem_fun, it takes a reference - * as parameter. - * The second one is the parameter passed to the member function. - */ -template<class Result, class Arg, class T> -inline ConstMemFuncRef1<Result, Arg, T> mem_fun_ref(Result (T::*f)(Arg) const) { - return ConstMemFuncRef1<Result, Arg, T>(f); -} - -// functor code - -/** - * Generic functor object for function objects without parameters. - * - * @see Functor1 - */ -template<class Res> -struct Functor0 { - virtual ~Functor0() {} - - virtual bool isValid() const = 0; - virtual Res operator()() const = 0; -}; - -/** - * Functor object for a class member function without parameter. - * - * Example creation: - * - * Foo bar; - * Functor0Mem<void, Foo> myFunctor(&bar, &Foo::myFunc); - * - * Example usage: - * - * myFunctor(); - */ -template<class Res, class T> -class Functor0Mem : public Functor0<Res> { -public: - typedef Res (T::*FuncType)(); - - Functor0Mem(T *t, const FuncType &func) : _t(t), _func(func) {} - - bool isValid() const { return _func != 0 && _t != 0; } - Res operator()() const { - return (_t->*_func)(); - } -private: - mutable T *_t; - const FuncType _func; -}; - -/** - * Generic functor object for unary function objects. - * - * A typical usage for an unary function object is for executing opcodes - * in a script interpreter. To achieve that one can create an Common::Array - * object with 'Functor1<Arg, Res> *' as type. Now after the right engine version - * has been determined and the opcode table to use is found one could easily - * add the opcode implementations like this: - * - * Common::Array<Functor1<ScriptState, void> *> opcodeTable; - * opcodeTable[0] = new Functor1Mem<ScriptState, void, MyEngine_v1>(&myEngine, &MyEngine_v1::o1_foo); - * opcodeTable[1] = new Functor1Mem<ScriptState, void, MyEngine_v2>(&myEngine, &MyEngine_v2::o2_foo); - * // unimplemented/unused opcode - * opcodeTable[2] = 0; - * etc. - * - * This makes it easy to add member functions of different classes as - * opcode functions to the function table. Since with the generic - * Functor1<ScriptState, void> object the only requirement for an - * function to be used is 'ScriptState' as argument and 'void' as return - * value. - * - * Now for calling the opcodes one has simple to do: - * if (opcodeTable[opcodeNum] && opcodeTable[opcodeNum]->isValid()) - * (*opcodeTable[opcodeNum])(scriptState); - * else - * warning("Unimplemented opcode %d", opcodeNum); - * - * If you want to see an real world example check the kyra engine. - * Files: engines/kyra/script.cpp and .h and engines/kyra/script_*.cpp - * are interesting for that matter. - */ -template<class Arg, class Res> -struct Functor1 : public Common::UnaryFunction<Arg, Res> { - virtual ~Functor1() {} - - virtual bool isValid() const = 0; - virtual Res operator()(Arg) const = 0; -}; - -/** - * Functor object for an unary class member function. - * Usage is like with Functor0Mem. The resulting functor object - * will take one parameter though. - * - * @see Functor0Mem - */ -template<class Arg, class Res, class T> -class Functor1Mem : public Functor1<Arg, Res> { -public: - typedef Res (T::*FuncType)(Arg); - - Functor1Mem(T *t, const FuncType &func) : _t(t), _func(func) {} - - bool isValid() const { return _func != 0 && _t != 0; } - Res operator()(Arg v1) const { - return (_t->*_func)(v1); - } -private: - mutable T *_t; - const FuncType _func; -}; - -/** - * Generic functor object for binary function objects. - * - * @see Functor1 - */ -template<class Arg1, class Arg2, class Res> -struct Functor2 : public Common::BinaryFunction<Arg1, Arg2, Res> { - virtual ~Functor2() {} - - virtual bool isValid() const = 0; - virtual Res operator()(Arg1, Arg2) const = 0; -}; - -/** - * Functor object for a binary function. - * - * @see Functor2Mem - */ -template<class Arg1, class Arg2, class Res> -class Functor2Fun : public Functor2<Arg1, Arg2, Res> { -public: - typedef Res (*FuncType)(Arg1, Arg2); - - Functor2Fun(const FuncType func) : _func(func) {} - - bool isValid() const { return _func != 0; } - Res operator()(Arg1 v1, Arg2 v2) const { - return (*_func)(v1, v2); - } -private: - const FuncType _func; -}; - -/** - * Functor object for a binary class member function. - * Usage is like with Functor0Mem. The resulting functor object - * will take two parameter though. - * - * @see Functor0Mem - */ -template<class Arg1, class Arg2, class Res, class T> -class Functor2Mem : public Functor2<Arg1, Arg2, Res> { -public: - typedef Res (T::*FuncType)(Arg1, Arg2); - - Functor2Mem(T *t, const FuncType &func) : _t(t), _func(func) {} - - bool isValid() const { return _func != 0 && _t != 0; } - Res operator()(Arg1 v1, Arg2 v2) const { - return (_t->*_func)(v1, v2); - } -private: - mutable T *_t; - const FuncType _func; -}; - -/** - * Base template for hash functor objects, used by HashMap. - * This needs to be specialized for every type that you need to hash. - */ -template<typename T> struct Hash; - - -#define GENERATE_TRIVIAL_HASH_FUNCTOR(T) \ - template<> struct Hash<T> : public UnaryFunction<T, uint> { \ - uint operator()(T val) const { return (uint)val; } \ - } - -GENERATE_TRIVIAL_HASH_FUNCTOR(bool); -GENERATE_TRIVIAL_HASH_FUNCTOR(char); -GENERATE_TRIVIAL_HASH_FUNCTOR(signed char); -GENERATE_TRIVIAL_HASH_FUNCTOR(unsigned char); -GENERATE_TRIVIAL_HASH_FUNCTOR(short); -GENERATE_TRIVIAL_HASH_FUNCTOR(int); -GENERATE_TRIVIAL_HASH_FUNCTOR(long); -GENERATE_TRIVIAL_HASH_FUNCTOR(unsigned short); -GENERATE_TRIVIAL_HASH_FUNCTOR(unsigned int); -GENERATE_TRIVIAL_HASH_FUNCTOR(unsigned long); - -#undef GENERATE_TRIVIAL_HASH_FUNCTOR - -} // End of namespace Common - -#endif - diff --git a/engines/sword25/tools/swfdisplay/rect.h b/engines/sword25/tools/swfdisplay/rect.h deleted file mode 100644 index 365dff09be..0000000000 --- a/engines/sword25/tools/swfdisplay/rect.h +++ /dev/null @@ -1,223 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/common/rect.h $ - * $Id: rect.h 52249 2010-08-21 08:17:06Z dreammaster $ - * - */ - -#ifndef COMMON_RECT_H -#define COMMON_RECT_H - -namespace Common { - -/** - * Simple class for handling both 2D position and size. - */ -struct Point { - int16 x; ///< The horizontal part of the point - int16 y; ///< The vertical part of the point - - Point() : x(0), y(0) {} - Point(int16 x1, int16 y1) : x(x1), y(y1) {} - bool operator==(const Point &p) const { return x == p.x && y == p.y; } - bool operator!=(const Point &p) const { return x != p.x || y != p.y; } - - /** - * Return the square of the distance between this point and the point p. - * - * @param p the other point - * @return the distance between this and p - */ -}; - -/** - * Simple class for handling a rectangular zone. - * - * Note: This implementation is built around the assumption that (top,left) is - * part of the rectangle, but (bottom,right) is not. This is reflected in - * various methods, including contains(), intersects() and others. - * - * Another very wide spread approach to rectangle classes treats (bottom,right) - * also as a part of the rectangle. - * - * Conceptually, both are sound, but the approach we use saves many intermediate - * computations (like computing the height in our case is done by doing this: - * height = bottom - top; - * while in the alternate system, it would be - * height = bottom - top + 1; - * - * When writing code using our Rect class, always keep this principle in mind! -*/ -struct Rect { - int16 top, left; ///< The point at the top left of the rectangle (part of the rect). - int16 bottom, right; ///< The point at the bottom right of the rectangle (not part of the rect). - - Rect() : top(0), left(0), bottom(0), right(0) {} - Rect(int16 w, int16 h) : top(0), left(0), bottom(h), right(w) {} - Rect(int16 x1, int16 y1, int16 x2, int16 y2) : top(y1), left(x1), bottom(y2), right(x2) { - assert(isValidRect()); - } - bool operator==(const Rect &rhs) const { return equals(rhs); } - bool operator!=(const Rect &rhs) const { return !equals(rhs); } - - int16 width() const { return right - left; } - int16 height() const { return bottom - top; } - - void setWidth(int16 aWidth) { - right = left + aWidth; - } - - void setHeight(int16 aHeight) { - bottom = top + aHeight; - } - - /** - * Check if given position is inside this rectangle. - * - * @param x the horizontal position to check - * @param y the vertical position to check - * - * @return true if the given position is inside this rectangle, false otherwise - */ - bool contains(int16 x, int16 y) const { - return (left <= x) && (x < right) && (top <= y) && (y < bottom); - } - - /** - * Check if given point is inside this rectangle. - * - * @param p the point to check - * - * @return true if the given point is inside this rectangle, false otherwise - */ - bool contains(const Point &p) const { - return contains(p.x, p.y); - } - - /** - * Check if the given rect is contained inside this rectangle. - * - * @param r The rectangle to check - * - * @return true if the given rect is inside, false otherwise - */ - bool contains(const Rect &r) const { - return (left <= r.left) && (r.right <= right) && (top <= r.top) && (r.bottom <= bottom); - } - - /** - * Check if the given rect is equal to this one. - * - * @param r The rectangle to check - * - * @return true if the given rect is equal, false otherwise - */ - bool equals(const Rect &r) const { - return (left == r.left) && (right == r.right) && (top == r.top) && (bottom == r.bottom); - } - - /** - * Check if given rectangle intersects with this rectangle - * - * @param r the rectangle to check - * - * @return true if the given rectangle is inside the rectangle, false otherwise - */ - bool intersects(const Rect &r) const { - return (left < r.right) && (r.left < right) && (top < r.bottom) && (r.top < bottom); - } - - /** - * Extend this rectangle so that it contains r - * - * @param r the rectangle to extend by - */ - - /** - * Extend this rectangle in all four directions by the given number of pixels - * - * @param offset the size to grow by - */ - void grow(int16 offset) { - top -= offset; - left -= offset; - bottom += offset; - right += offset; - } - - void clip(const Rect &r) { - assert(isValidRect()); - assert(r.isValidRect()); - - if (top < r.top) top = r.top; - else if (top > r.bottom) top = r.bottom; - - if (left < r.left) left = r.left; - else if (left > r.right) left = r.right; - - if (bottom > r.bottom) bottom = r.bottom; - else if (bottom < r.top) bottom = r.top; - - if (right > r.right) right = r.right; - else if (right < r.left) right = r.left; - } - - void clip(int16 maxw, int16 maxh) { - clip(Rect(0, 0, maxw, maxh)); - } - - bool isEmpty() const { - return (left >= right || top >= bottom); - } - - bool isValidRect() const { - return (left <= right && top <= bottom); - } - - void moveTo(int16 x, int16 y) { - bottom += y - top; - right += x - left; - top = y; - left = x; - } - - void translate(int16 dx, int16 dy) { - left += dx; right += dx; - top += dy; bottom += dy; - } - - void moveTo(const Point &p) { - moveTo(p.x, p.y); - } - - /** - * Create a rectangle around the given center. - */ - static Rect center(int16 cx, int16 cy, int16 w, int16 h) { - w /= 2; - h /= 2; - return Rect(cx - w, cy - h, cx + w, cy + h); - } -}; - -} // End of namespace Common - -#endif diff --git a/engines/sword25/tools/swfdisplay/swfrender.cpp b/engines/sword25/tools/swfdisplay/swfrender.cpp deleted file mode 100644 index af536978c0..0000000000 --- a/engines/sword25/tools/swfdisplay/swfrender.cpp +++ /dev/null @@ -1,172 +0,0 @@ -#include "art.h" -#include "vectorimage.h" - -#define SAVING 1 - -#if SAVING -static void save_buffer(unsigned char *buffer, uint width, uint height, const char *filename); - -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <png.h> -#include <stdio.h> - -static gboolean -pixbuf_save_to_file(const GdkPixbuf *pixbuf, const char *file_name) { - FILE *handle; - unsigned char *buffer; - gboolean has_alpha; - int width, height, depth, rowstride; - guchar *pixels; - png_structp png_ptr; - png_infop info_ptr; - png_text text[2]; - int i; - - g_return_val_if_fail(pixbuf != NULL, FALSE); - g_return_val_if_fail(file_name != NULL, FALSE); - g_return_val_if_fail(file_name[0] != '\0', FALSE); - - handle = fopen(file_name, "wb"); - if (handle == NULL) { - return FALSE; - } - - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (png_ptr == NULL) { - fclose(handle); - return FALSE; - } - - info_ptr = png_create_info_struct(png_ptr); - if (info_ptr == NULL) { - png_destroy_write_struct(&png_ptr, (png_infopp)NULL); - fclose(handle); - return FALSE; - } - - if (setjmp(png_ptr->jmpbuf)) { - png_destroy_write_struct(&png_ptr, &info_ptr); - fclose(handle); - return FALSE; - } - - png_init_io(png_ptr, handle); - - has_alpha = gdk_pixbuf_get_has_alpha(pixbuf); - width = gdk_pixbuf_get_width(pixbuf); - height = gdk_pixbuf_get_height(pixbuf); - depth = gdk_pixbuf_get_bits_per_sample(pixbuf); - pixels = gdk_pixbuf_get_pixels(pixbuf); - rowstride = gdk_pixbuf_get_rowstride(pixbuf); - - png_set_IHDR(png_ptr, info_ptr, width, height, - depth, PNG_COLOR_TYPE_RGB_ALPHA, - PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - - /* Some text to go with the png image */ - text[0].key = "Title"; - text[0].text = (char *) file_name; - text[0].compression = PNG_TEXT_COMPRESSION_NONE; - text[1].key = "Software"; - text[1].text = "Nautilus Thumbnail"; - text[1].compression = PNG_TEXT_COMPRESSION_NONE; - png_set_text(png_ptr, info_ptr, text, 2); - - /* Write header data */ - png_write_info(png_ptr, info_ptr); - - /* if there is no alpha in the data, allocate buffer to expand into */ - if (has_alpha) { - buffer = NULL; - } else { - buffer = (unsigned char *)g_malloc(4 * width); - } - - /* pump the raster data into libpng, one scan line at a time */ - for (i = 0; i < height; i++) { - if (has_alpha) { - png_bytep row_pointer = pixels; - png_write_row(png_ptr, row_pointer); - } else { - /* expand RGB to RGBA using an opaque alpha value */ - int x; - unsigned char *buffer_ptr = buffer; - unsigned char *source_ptr = pixels; - for (x = 0; x < width; x++) { - *buffer_ptr++ = *source_ptr++; - *buffer_ptr++ = *source_ptr++; - *buffer_ptr++ = *source_ptr++; - *buffer_ptr++ = 255; - } - png_write_row(png_ptr, (png_bytep) buffer); - } - pixels += rowstride; - } - - png_write_end(png_ptr, info_ptr); - png_destroy_write_struct(&png_ptr, &info_ptr); - - g_free(buffer); - - fclose(handle); - return TRUE; -} - -static void -save_buffer(unsigned char *buffer, uint width, uint height, const char *filename) { - GdkPixbuf *pixbuf; - - g_type_init(); - - pixbuf = gdk_pixbuf_new_from_data(buffer, - GDK_COLORSPACE_RGB, - TRUE, - 8, - width, height, - width * 4, - NULL, NULL); - - pixbuf_save_to_file(pixbuf, filename); - - gdk_pixbuf_unref(pixbuf); -} - -#endif - - -int main(int argc, char *argv[]) { - if (argc < 2) { - printf("Usage: %s <file>\n", argv[0]); - exit(0); - } - - int fnamelen = strlen(argv[1]); - char *fname = (char *)malloc(fnamelen + 1); - strcpy(fname, argv[1]); - fname[fnamelen-3] = 'p'; - fname[fnamelen-2] = 'n'; - fname[fnamelen-1] = 'g'; - - FILE *in = fopen(argv[1], "r"); - fseek(in, 0, SEEK_END); - uint32 len = ftell(in); - - byte *buf = (byte *)malloc(len); - fseek(in, 0, SEEK_SET); - - fread(buf, len, 1, in); - fclose(in); - - bool success; - Sword25::VectorImage img(buf, len, success); - - img.render(img.getWidth(), img.getHeight()); - -#if SAVING - save_buffer(img.getPixelData(), img.getWidth(), img.getHeight(), fname); -#endif - - return 0; -} diff --git a/engines/sword25/tools/swfdisplay/vectorimage.cpp b/engines/sword25/tools/swfdisplay/vectorimage.cpp deleted file mode 100644 index 7b266d8780..0000000000 --- a/engines/sword25/tools/swfdisplay/vectorimage.cpp +++ /dev/null @@ -1,658 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -/* - * This code is based on Broken Sword 2.5 engine - * - * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer - * - * Licensed under GNU GPL v2 - * - */ - -// ----------------------------------------------------------------------------- -// Includes -// ----------------------------------------------------------------------------- - -#include "art.h" -#include "vectorimage.h" - -namespace Sword25 { - -#define BS_LOG_PREFIX "VECTORIMAGE" - -#define BEZSMOOTHNESS 0.5 - -// ----------------------------------------------------------------------------- -// SWF Datentypen -// ----------------------------------------------------------------------------- - -// ----------------------------------------------------------------------------- -// Bitstream Hilfsklasse -// ----------------------------------------------------------------------------- -// Das Parsen von SWF-Dateien erfordert sowohl bitweises Auslesen als auch an -// Bytegrenzen ausgerichtetes Lesen. -// Diese Klasse ist speziell dafür ausgestattet. -// ----------------------------------------------------------------------------- - -class VectorImage::SWFBitStream { -public: - SWFBitStream(const byte *pData, uint dataSize) : - m_Pos(pData), m_End(pData + dataSize), m_WordMask(0) - {} - - inline uint32 getBits(uint bitCount) { - if (bitCount == 0 || bitCount > 32) { - error("SWFBitStream::GetBits() must read at least 1 and at most 32 bits at a time"); - } - - uint32 value = 0; - while (bitCount) { - if (m_WordMask == 0) - flushByte(); - - value <<= 1; - value |= ((m_Word & m_WordMask) != 0) ? 1 : 0; - m_WordMask >>= 1; - - --bitCount; - } - - return value; - } - - inline int32 getSignedBits(uint bitCount) { - // Bits einlesen - uint32 temp = getBits(bitCount); - - // Falls das Sign-Bit gesetzt ist, den Rest des Rückgabewertes mit 1-Bits auffüllen (Sign Extension) - if (temp & 1 << (bitCount - 1)) - return (0xffffffff << bitCount) | temp; - else - return temp; - } - - inline uint32 getUInt32() { - uint32 byte1 = getByte(); - uint32 byte2 = getByte(); - uint32 byte3 = getByte(); - uint32 byte4 = getByte(); - - return byte1 | (byte2 << 8) | (byte3 << 16) | (byte4 << 24); - } - - inline uint16 getUInt16() { - uint32 byte1 = getByte(); - uint32 byte2 = getByte(); - - return byte1 | (byte2 << 8); - } - - inline byte getByte() { - flushByte(); - byte value = m_Word; - m_WordMask = 0; - flushByte(); - - return value; - } - - inline void flushByte() { - if (m_WordMask != 128) { - if (m_Pos >= m_End) { - error("Attempted to read past end of file"); - } else { - m_Word = *m_Pos++; - m_WordMask = 128; - } - } - } - - inline void skipBytes(uint skipLength) { - flushByte(); - if (m_Pos + skipLength >= m_End) { - error("Attempted to read past end of file"); - } else { - m_Pos += skipLength; - m_Word = *(m_Pos - 1); - } - } - -private: - const byte *m_Pos; - const byte *m_End; - - byte m_Word; - uint m_WordMask; -}; - - -// ----------------------------------------------------------------------------- -// Konstanten und Hilfsfunktionen -// ----------------------------------------------------------------------------- - -namespace { -// ----------------------------------------------------------------------------- -// Konstanten -// ----------------------------------------------------------------------------- - -const uint32 MAX_ACCEPTED_FLASH_VERSION = 4; // Die höchste Flash-Dateiversion, die vom Lader akzeptiert wird - - -// ----------------------------------------------------------------------------- -// Konvertiert SWF-Rechteckdaten in einem Bitstrom in Common::Rect-Objekte -// ----------------------------------------------------------------------------- - -Common::Rect flashRectToBSRect(VectorImage::SWFBitStream &bs) { - bs.flushByte(); - - // Feststellen mit wie vielen Bits die einzelnen Komponenten kodiert sind - uint32 bitsPerValue = bs.getBits(5); - - // Die einzelnen Komponenten einlesen - int32 xMin = bs.getSignedBits(bitsPerValue); - int32 xMax = bs.getSignedBits(bitsPerValue); - int32 yMin = bs.getSignedBits(bitsPerValue); - int32 yMax = bs.getSignedBits(bitsPerValue); - - return Common::Rect(xMin, yMin, xMax + 1, yMax + 1); -} - -// ----------------------------------------------------------------------------- -// Berechnet die Bounding-Box eines BS_VectorImageElement -// ----------------------------------------------------------------------------- - -Common::Rect CalculateBoundingBox(const VectorImageElement &vectorImageElement) { - double x0 = 0.0, y0 = 0.0, x1 = 0.0, y1 = 0.0; - - for (int j = vectorImageElement.getPathCount() - 1; j >= 0; j--) { - ArtBpath *bez = vectorImageElement.getPathInfo(j).getVec(); - ArtVpath *vec = art_bez_path_to_vec(bez, 0.5); - - if (vec[0].code == ART_END) { - continue; - } else { - x0 = x1 = vec[0].x; - y0 = y1 = vec[0].y; - for (int i = 1; vec[i].code != ART_END; i++) { - if (vec[i].x < x0) x0 = vec[i].x; - if (vec[i].x > x1) x1 = vec[i].x; - if (vec[i].y < y0) y0 = vec[i].y; - if (vec[i].y > y1) y1 = vec[i].y; - } - } - free(vec); - } - - return Common::Rect(static_cast<int>(x0), static_cast<int>(y0), static_cast<int>(x1) + 1, static_cast<int>(y1) + 1); -} - -} - - -// ----------------------------------------------------------------------------- -// Konstruktion -// ----------------------------------------------------------------------------- - -VectorImage::VectorImage(const byte *pFileData, uint fileSize, bool &success) : _pixelData(0) { - success = false; - - // Bitstream-Objekt erzeugen - // Im Folgenden werden die Dateidaten aus diesem ausgelesen. - SWFBitStream bs(pFileData, fileSize); - - // SWF-Signatur überprüfen - uint32 signature[3]; - signature[0] = bs.getByte(); - signature[1] = bs.getByte(); - signature[2] = bs.getByte(); - if (signature[0] != 'F' || - signature[1] != 'W' || - signature[2] != 'S') { - BS_LOG_ERRORLN("File is not a valid SWF-file"); - return; - } - - // Versionsangabe überprüfen - uint32 version = bs.getByte(); - if (version > MAX_ACCEPTED_FLASH_VERSION) { - //BS_LOG_ERRORLN("File is of version %d. Highest accepted version is %d.", version, MAX_ACCEPTED_FLASH_VERSION); - return; - } - - // Dateigröße auslesen und mit der tatsächlichen Größe vergleichen - uint32 storedFileSize = bs.getUInt32(); - if (storedFileSize != fileSize) { - BS_LOG_ERRORLN("File is not a valid SWF-file"); - return; - } - - // SWF-Maße auslesen - Common::Rect movieRect = flashRectToBSRect(bs); - - // Framerate und Frameanzahl auslesen - /* uint32 frameRate = */ - bs.getUInt16(); - /* uint32 frameCount = */ - bs.getUInt16(); - - // Tags parsen - // Da wir uns nur für das erste DefineShape-Tag interessieren - bool keepParsing = true; - while (keepParsing) { - // Tags beginnen immer an Bytegrenzen - bs.flushByte(); - - // Tagtyp und Länge auslesen - uint16 tagTypeAndLength = bs.getUInt16(); - uint32 tagType = tagTypeAndLength >> 6; - uint32 tagLength = tagTypeAndLength & 0x3f; - if (tagLength == 0x3f) - tagLength = bs.getUInt32(); - - switch (tagType) { - case 2: - // DefineShape - success = parseDefineShape(2, bs); - return; - case 22: - // DefineShape2 - success = parseDefineShape(2, bs); - return; - case 32: - success = parseDefineShape(3, bs); - return; - default: - // Unbekannte Tags ignorieren - bs.skipBytes(tagLength); - } - } - - // Die Ausführung darf nicht an dieser Stelle ankommen: Entweder es wird ein Shape gefunden, dann wird die Funktion mit vorher verlassen, oder - // es wird keines gefunden, dann tritt eine Exception auf sobald über das Ende der Datei hinaus gelesen wird. - BS_ASSERT(false); -} - -VectorImage::~VectorImage() { - for (int j = _elements.size() - 1; j >= 0; j--) - for (int i = _elements[j].getPathCount() - 1; i >= 0; i--) - if (_elements[j].getPathInfo(i).getVec()) - free(_elements[j].getPathInfo(i).getVec()); - - if (_pixelData) - free(_pixelData); -} - - -ArtBpath *ensureBezStorage(ArtBpath *bez, int nodes, int *allocated) { - if (*allocated <= nodes) { - (*allocated) += 20; - - return art_renew(bez, ArtBpath, *allocated); - } - - return bez; -} - -ArtBpath *VectorImage::storeBez(ArtBpath *bez, int lineStyle, int fillStyle0, int fillStyle1, int *bezNodes, int *bezAllocated) { - (*bezNodes)++; - - bez = ensureBezStorage(bez, *bezNodes, bezAllocated); - bez[*bezNodes].code = ART_END; - - ArtBpath *bez1 = art_new(ArtBpath, *bezNodes + 1); - - for (int i = 0; i <= *bezNodes; i++) - bez1[i] = bez[i]; - -#if DEBUG - printf("storeBez(bez, %d, %d, %d, %d, %d)\n", lineStyle, fillStyle0, fillStyle1, *bezNodes, *bezAllocated); -#endif - - _elements.back()._pathInfos.push_back(VectorPathInfo(bez1, *bezNodes, lineStyle, fillStyle0, fillStyle1)); - - return bez; -} - -bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) { - /*uint32 shapeID = */bs.getUInt16(); - - // Bounding Box auslesen - _boundingBox = flashRectToBSRect(bs); - - // Erstes Image-Element erzeugen - _elements.resize(1); - - // Styles einlesen - uint numFillBits; - uint numLineBits; - if (!parseStyles(shapeType, bs, numFillBits, numLineBits)) - return false; - - uint lineStyle = 0; - uint fillStyle0 = 0; - uint fillStyle1 = 0; - - // Shaperecord parsen - // ------------------ - - double curX = 0; - double curY = 0; - int bezNodes = 0; - int bezAllocated = 10; - ArtBpath *bez = art_new(ArtBpath, bezAllocated); - - bool endOfShapeDiscovered = false; - while (!endOfShapeDiscovered) { - uint32 typeFlag = bs.getBits(1); - - // Non-Edge Record - if (typeFlag == 0) { - // Feststellen welche Parameter gesetzt werden - uint32 stateNewStyles = bs.getBits(1); - uint32 stateLineStyle = bs.getBits(1); - uint32 stateFillStyle1 = bs.getBits(1); - uint32 stateFillStyle0 = bs.getBits(1); - uint32 stateMoveTo = bs.getBits(1); - - uint prevLineStyle = lineStyle; - uint prevFillStyle0 = fillStyle0; - uint prevFillStyle1 = fillStyle1; - - // End der Shape-Definition erreicht? - if (!stateNewStyles && !stateLineStyle && !stateFillStyle0 && !stateFillStyle1 && !stateMoveTo) { - endOfShapeDiscovered = true; - // Parameter dekodieren - } else { - if (stateMoveTo) { - uint32 moveToBits = bs.getBits(5); - curX = bs.getSignedBits(moveToBits); - curY = bs.getSignedBits(moveToBits); - -#if DEBUG - printf("M --> %lf, %lf\n", curX, curY); -#endif - } - - if (stateFillStyle0) { - if (numFillBits > 0) - fillStyle0 = bs.getBits(numFillBits); - else - fillStyle0 = 0; -#if DEBUG - printf("0 --> %d\n", fillStyle0); -#endif - } - - if (stateFillStyle1) { - if (numFillBits > 0) - fillStyle1 = bs.getBits(numFillBits); - else - fillStyle1 = 0; -#if DEBUG - printf("1 --> %d\n", fillStyle1); -#endif - } - - if (stateLineStyle) { - if (numLineBits) - lineStyle = bs.getBits(numLineBits); - else - lineStyle = 0; -#if DEBUG - printf("L --> %d\n", lineStyle); -#endif - } - - if (stateNewStyles) { -#if DEBUG - printf("New Style\n"); -#endif - // An dieser Stelle werden in Flash die alten Style-Definitionen verworfen und mit den neuen überschrieben. - // Es wird ein neues Element begonnen. - _elements.resize(_elements.size() + 1); - if (!parseStyles(shapeType, bs, numFillBits, numLineBits)) - return false; - } - - // Ein neuen Pfad erzeugen, es sei denn, es wurden nur neue Styles definiert - if (stateLineStyle || stateFillStyle0 || stateFillStyle1 || stateMoveTo) { - // Store previous curve if any - if (bezNodes) { - bez = storeBez(bez, prevLineStyle, prevFillStyle0, prevFillStyle1, &bezNodes, &bezAllocated); - } - - // Start new curve - bez = ensureBezStorage(bez, 1, &bezAllocated); - bez[0].code = ART_MOVETO_OPEN; - bez[0].x3 = curX; - bez[0].y3 = curY; - bezNodes = 0; - } - } - } else { - // Edge Record - uint32 edgeFlag = bs.getBits(1); - uint32 numBits = bs.getBits(4) + 2; - - // Curved edge - if (edgeFlag == 0) { - double controlDeltaX = bs.getSignedBits(numBits); - double controlDeltaY = bs.getSignedBits(numBits); - double anchorDeltaX = bs.getSignedBits(numBits); - double anchorDeltaY = bs.getSignedBits(numBits); - - double controlX = curX + controlDeltaX; - double controlY = curY + controlDeltaY; - double newX = controlX + anchorDeltaX; - double newY = controlY + anchorDeltaY; - -#define WEIGHT (2.0/3.0) - - bezNodes++; - bez = ensureBezStorage(bez, bezNodes, &bezAllocated); - bez[bezNodes].code = ART_CURVETO; - bez[bezNodes].x1 = WEIGHT * controlX + (1 - WEIGHT) * curX; - bez[bezNodes].y1 = WEIGHT * controlY + (1 - WEIGHT) * curY; - bez[bezNodes].x2 = WEIGHT * controlX + (1 - WEIGHT) * newX; - bez[bezNodes].y2 = WEIGHT * controlY + (1 - WEIGHT) * newY; - bez[bezNodes].x3 = newX; - bez[bezNodes].y3 = newY; - - curX = newX; - curY = newY; - } else { - // Staight edge - int32 deltaX = 0; - int32 deltaY = 0; - - uint32 generalLineFlag = bs.getBits(1); - if (generalLineFlag) { - deltaX = bs.getSignedBits(numBits); - deltaY = bs.getSignedBits(numBits); - } else { - uint32 vertLineFlag = bs.getBits(1); - if (vertLineFlag) - deltaY = bs.getSignedBits(numBits); - else - deltaX = bs.getSignedBits(numBits); - } - - curX += deltaX; - curY += deltaY; - - bezNodes++; - bez = ensureBezStorage(bez, bezNodes, &bezAllocated); - bez[bezNodes].code = ART_LINETO; - bez[bezNodes].x3 = curX; - bez[bezNodes].y3 = curY; - } - } - } - - // Store last curve - if (bezNodes) - bez = storeBez(bez, lineStyle, fillStyle0, fillStyle1, &bezNodes, &bezAllocated); - - free(bez); - - // Bounding-Boxes der einzelnen Elemente berechnen - Common::Array<VectorImageElement>::iterator it = _elements.begin(); - for (; it != _elements.end(); ++it) - it->_boundingBox = CalculateBoundingBox(*it); - - return true; -} - - -// ----------------------------------------------------------------------------- - -bool VectorImage::parseStyles(uint shapeType, SWFBitStream &bs, uint &numFillBits, uint &numLineBits) { - bs.flushByte(); - - // Fillstyles parsen - // ----------------- - - // Anzahl an Fillstyles bestimmen - uint fillStyleCount = bs.getByte(); - if (fillStyleCount == 0xff) - fillStyleCount = bs.getUInt16(); - - // Alle Fillstyles einlesen, falls ein Fillstyle mit Typ != 0 gefunden wird, wird das Parsen abgebrochen. - // Es wird nur "solid fill" (Typ 0) unterstützt. - _elements.back()._fillStyles.reserve(fillStyleCount); - for (uint i = 0; i < fillStyleCount; ++i) { - byte type = bs.getByte(); - uint32 color; - byte r = bs.getByte(); - byte g = bs.getByte(); - byte b = bs.getByte(); - byte a = 0xff; - - if (shapeType == 3) - a = bs.getByte(); - - //color = Graphics::ARGBToColor<Graphics::ColorMasks<8888> >(a, r, g, b); - color = BS_ARGB(a, r, g, b); - - if (type != 0) - return false; - - _elements.back()._fillStyles.push_back(color); - } - - // Linestyles parsen - // ----------------- - - // Anzahl an Linestyles bestimmen - uint lineStyleCount = bs.getByte(); - if (lineStyleCount == 0xff) - lineStyleCount = bs.getUInt16(); - - // Alle Linestyles einlesen - _elements.back()._lineStyles.reserve(lineStyleCount); - for (uint i = 0; i < lineStyleCount; ++i) { - double width = bs.getUInt16(); - uint32 color; - byte r = bs.getByte(); - byte g = bs.getByte(); - byte b = bs.getByte(); - byte a = 0xff; - - if (shapeType == 3) - a = bs.getByte(); - - //color = Graphics::ARGBToColor<Graphics::ColorMasks<8888> >(a, r, g, b); - color = BS_ARGB(a, r, g, b); - - _elements.back()._lineStyles.push_back(VectorImageElement::LineStyleType(width, color)); - } - - // Bitbreite für die folgenden Styleindizes auslesen - numFillBits = bs.getBits(4); - numLineBits = bs.getBits(4); - - return true; -} - - -// ----------------------------------------------------------------------------- - -#if 0 -bool VectorImage::fill(const Common::Rect *pFillRect, uint color) { - BS_LOG_ERRORLN("Fill() is not supported."); - return false; -} -#endif - -// ----------------------------------------------------------------------------- - -uint VectorImage::getPixel(int x, int y) { - BS_LOG_ERRORLN("GetPixel() is not supported. Returning black."); - return 0; -} - -// ----------------------------------------------------------------------------- - -bool VectorImage::setContent(const byte *pixeldata, uint size, uint offset, uint stride) { - BS_LOG_ERRORLN("SetContent() is not supported."); - return 0; -} - -#if 0 -bool VectorImage::blit(int posX, int posY, - int flipping, - Common::Rect *pPartRect, - uint color, - int width, int height) { - static VectorImage *oldThis = 0; - static int oldWidth = -2; - static int oldHeight = -2; - - // Falls Breite oder Höhe 0 sind, muss nichts dargestellt werden. - if (width == 0 || height == 0) - return true; - - // Feststellen, ob das alte Bild im Cache nicht wiederbenutzt werden kann und neu Berechnet werden muss - if (!(oldThis == this && oldWidth == width && oldHeight == height)) { - render(width, height); - - oldThis = this; - oldHeight = height; - oldWidth = width; - } - - GLImage *rend = new GLImage(); - - rend->replaceContent(_pixelData, width, height); - rend->blit(posX, posY, flipping, pPartRect, color, width, height); - - delete rend; - - return true; -} -#endif - -} // End of namespace Sword25 diff --git a/engines/sword25/tools/swfdisplay/vectorimage.h b/engines/sword25/tools/swfdisplay/vectorimage.h deleted file mode 100644 index 70a46b62d7..0000000000 --- a/engines/sword25/tools/swfdisplay/vectorimage.h +++ /dev/null @@ -1,233 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -/* - * This code is based on Broken Sword 2.5 engine - * - * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer - * - * Licensed under GNU GPL v2 - * - */ - -#ifndef SWORD25_VECTORIMAGE_H -#define SWORD25_VECTORIMAGE_H - -// ----------------------------------------------------------------------------- -// Includes -// ----------------------------------------------------------------------------- - -#include "rect.h" -#include "array.h" - -#include "art.h" - -namespace Sword25 { - -class VectorImage; - -/** - @brief Pfadinformationen zu BS_VectorImageElement Objekten - - Jedes BS_VectorImageElement besteht aus Kantenzügen, oder auch Pfaden. Jeder dieser Pfad hat Eigenschaften, die in Objekten diesen Typs - gespeichert werden. -*/ - -class VectorPathInfo { -public: - VectorPathInfo(ArtBpath *vec, int len, uint lineStyle, uint fillStyle0, uint fillStyle1) : - _vec(vec), _lineStyle(lineStyle), _fillStyle0(fillStyle0), _fillStyle1(fillStyle1), _len(len) {} - - VectorPathInfo() { - _lineStyle = _fillStyle0 = _fillStyle1 = _len = 0; - _vec = 0; - } - - ArtBpath *getVec() const { - return _vec; - } - int getVecLen() const { - return _len; - } - uint getLineStyle() const { - return _lineStyle; - } - uint getFillStyle0() const { - return _fillStyle0; - } - uint getFillStyle1() const { - return _fillStyle1; - } - -private: - ArtBpath *_vec; - uint _lineStyle; - uint _fillStyle0; - uint _fillStyle1; - uint _len; -}; - -/** - @brief Ein Element eines Vektorbild. Ein BS_VectorImage besteht aus diesen Elementen, die jeweils einen Teil der Graphik definieren. - Werden alle Elemente eines Vektorbildes übereinandergelegt, ergibt sich das komplette Bild. -*/ -class VectorImageElement { - friend class VectorImage; -public: - uint getPathCount() const { - return _pathInfos.size(); - } - const VectorPathInfo &getPathInfo(uint pathNr) const { - BS_ASSERT(pathNr < getPathCount()); - return _pathInfos[pathNr]; - } - - double getLineStyleWidth(uint lineStyle) const { - BS_ASSERT(lineStyle < _lineStyles.size()); - return _lineStyles[lineStyle].width; - } - - uint getLineStyleCount() const { - return _lineStyles.size(); - } - - uint32 getLineStyleColor(uint lineStyle) const { - BS_ASSERT(lineStyle < _lineStyles.size()); - return _lineStyles[lineStyle].color; - } - - uint getFillStyleCount() const { - return _fillStyles.size(); - } - - uint32 getFillStyleColor(uint fillStyle) const { - BS_ASSERT(fillStyle < _fillStyles.size()); - return _fillStyles[fillStyle]; - } - - const Common::Rect &getBoundingBox() const { - return _boundingBox; - } - -private: - struct LineStyleType { - LineStyleType(double width_, uint32 color_) : width(width_), color(color_) {} - LineStyleType() { - width = 0; - color = 0; - } - double width; - uint32 color; - }; - - Common::Array<VectorPathInfo> _pathInfos; - Common::Array<LineStyleType> _lineStyles; - Common::Array<uint32> _fillStyles; - Common::Rect _boundingBox; -}; - - -/** - @brief Eine Vektorgraphik - - Objekte dieser Klasse enthalten die Informationen eines SWF-Shapes. -*/ - -class VectorImage { -public: - VectorImage(const byte *pFileData, uint fileSize, bool &success); - ~VectorImage(); - - uint getElementCount() const { - return _elements.size(); - } - const VectorImageElement &getElement(uint elementNr) const { - BS_ASSERT(elementNr < _elements.size()); - return _elements[elementNr]; - } - const Common::Rect &getBoundingBox() const { - return _boundingBox; - } - - // - // Die abstrakten Methoden von BS_Image - // - virtual int getWidth() const { - return _boundingBox.width(); - } - virtual int getHeight() const { - return _boundingBox.height(); - } - - void render(int width, int height); - - virtual uint getPixel(int x, int y); - virtual bool isBlitSource() const { - return true; - } - virtual bool isBlitTarget() const { - return false; - } - virtual bool isScalingAllowed() const { - return true; - } - virtual bool isFillingAllowed() const { - return false; - } - virtual bool isAlphaAllowed() const { - return true; - } - virtual bool isColorModulationAllowed() const { - return true; - } - virtual bool isSetContentAllowed() const { - return false; - } - virtual bool setContent(const byte *pixeldata, uint size, uint offset, uint stride); - - byte *getPixelData() { return _pixelData; } -#if 0 - virtual bool blit(int posX = 0, int posY = 0, - int flipping = FLIP_NONE, - Common::Rect *pPartRect = NULL, - uint color = BS_ARGB(255, 255, 255, 255), - int width = -1, int height = -1); -#endif - class SWFBitStream; - -private: - bool parseDefineShape(uint shapeType, SWFBitStream &bs); - bool parseStyles(uint shapeType, SWFBitStream &bs, uint &numFillBits, uint &numLineBits); - - ArtBpath *storeBez(ArtBpath *bez, int lineStyle, int fillStyle0, int fillStyle1, int *bezNodes, int *bezAllocated); - Common::Array<VectorImageElement> _elements; - Common::Rect _boundingBox; - - byte *_pixelData; -}; - -} // End of namespace Sword25 - -#endif diff --git a/engines/sword25/tools/swfdisplay/vectorimagerenderer.cpp b/engines/sword25/tools/swfdisplay/vectorimagerenderer.cpp deleted file mode 100644 index ba964b6a9d..0000000000 --- a/engines/sword25/tools/swfdisplay/vectorimagerenderer.cpp +++ /dev/null @@ -1,480 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -/* - * This code is based on Broken Sword 2.5 engine - * - * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer - * - * Licensed under GNU GPL v2 - * - */ - -#include "art_svp_vpath.h" -#include "art_svp_vpath_stroke.h" -#include "art_svp_render_aa.h" - -#include "vectorimage.h" - -namespace Sword25 { - -void art_rgb_fill_run1(art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n) { - int i; - - if (r == g && g == b && r == 255) { - memset(buf, g, n + n + n + n); - } else { - uint32 *alt = (uint32 *)buf; - //uint32 color = Graphics::ARGBToColor<Graphics::ColorMasks<8888> >(0xff, r, g, b); - uint32 color = BS_ARGB(0xff, r, g, b); - - for (i = 0; i < n; i++) - *alt++ = color; - } -} - -void art_rgb_run_alpha1(art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n) { - int i; - int v; - - for (i = 0; i < n; i++) { - v = *buf; - *buf++ = v + (((b - v) * alpha + 0x80) >> 8); - v = *buf; - *buf++ = v + (((g - v) * alpha + 0x80) >> 8); - v = *buf; - *buf++ = v + (((r - v) * alpha + 0x80) >> 8); - v = *buf; - if (v + alpha > 255) - *buf++ = 255; - else - *buf++ = v + alpha; //(((alpha - v) * alpha + 0x80) >> 8); - } -} - -typedef struct _ArtRgbSVPAlphaData ArtRgbSVPAlphaData; - -struct _ArtRgbSVPAlphaData { - int alphatab[256]; - art_u8 r, g, b, alpha; - art_u8 *buf; - int rowstride; - int x0, x1; -}; - -static void art_rgb_svp_alpha_callback1(void *callback_data, int y, - int start, ArtSVPRenderAAStep *steps, int n_steps) { - ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data; - art_u8 *linebuf; - int run_x0, run_x1; - art_u32 running_sum = start; - int x0, x1; - int k; - art_u8 r, g, b; - int *alphatab; - int alpha; - - linebuf = data->buf; - x0 = data->x0; - x1 = data->x1; - - r = data->r; - g = data->g; - b = data->b; - alphatab = data->alphatab; - - if (n_steps > 0) { - run_x1 = steps[0].x; - if (run_x1 > x0) { - alpha = (running_sum >> 16) & 0xff; - if (alpha) - art_rgb_run_alpha1(linebuf, r, g, b, alphatab[alpha], run_x1 - x0); - } - - for (k = 0; k < n_steps - 1; k++) { - running_sum += steps[k].delta; - run_x0 = run_x1; - run_x1 = steps[k + 1].x; - if (run_x1 > run_x0) { - alpha = (running_sum >> 16) & 0xff; - if (alpha) - art_rgb_run_alpha1(linebuf + (run_x0 - x0) * 4, r, g, b, alphatab[alpha], run_x1 - run_x0); - } - } - running_sum += steps[k].delta; - if (x1 > run_x1) { - alpha = (running_sum >> 16) & 0xff; - if (alpha) - art_rgb_run_alpha1(linebuf + (run_x1 - x0) * 4, r, g, b, alphatab[alpha], x1 - run_x1); - } - } else { - alpha = (running_sum >> 16) & 0xff; - if (alpha) - art_rgb_run_alpha1(linebuf, r, g, b, alphatab[alpha], x1 - x0); - } - - data->buf += data->rowstride; -} - -static void art_rgb_svp_alpha_opaque_callback1(void *callback_data, int y, - int start, - ArtSVPRenderAAStep *steps, int n_steps) { - ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data; - art_u8 *linebuf; - int run_x0, run_x1; - art_u32 running_sum = start; - int x0, x1; - int k; - art_u8 r, g, b; - int *alphatab; - int alpha; - - linebuf = data->buf; - x0 = data->x0; - x1 = data->x1; - - r = data->r; - g = data->g; - b = data->b; - alphatab = data->alphatab; - - if (n_steps > 0) { - run_x1 = steps[0].x; - if (run_x1 > x0) { - alpha = running_sum >> 16; - if (alpha) { - if (alpha >= 255) - art_rgb_fill_run1(linebuf, r, g, b, run_x1 - x0); - else - art_rgb_run_alpha1(linebuf, r, g, b, alphatab[alpha], run_x1 - x0); - } - } - - for (k = 0; k < n_steps - 1; k++) { - running_sum += steps[k].delta; - run_x0 = run_x1; - run_x1 = steps[k + 1].x; - if (run_x1 > run_x0) { - alpha = running_sum >> 16; - if (alpha) { - if (alpha >= 255) - art_rgb_fill_run1(linebuf + (run_x0 - x0) * 4, r, g, b, run_x1 - run_x0); - else - art_rgb_run_alpha1(linebuf + (run_x0 - x0) * 4, r, g, b, alphatab[alpha], run_x1 - run_x0); - } - } - } - running_sum += steps[k].delta; - if (x1 > run_x1) { - alpha = running_sum >> 16; - if (alpha) { - if (alpha >= 255) - art_rgb_fill_run1(linebuf + (run_x1 - x0) * 4, r, g, b, x1 - run_x1); - else - art_rgb_run_alpha1(linebuf + (run_x1 - x0) * 4, r, g, b, alphatab[alpha], x1 - run_x1); - } - } - } else { - alpha = running_sum >> 16; - if (alpha) { - if (alpha >= 255) - art_rgb_fill_run1(linebuf, r, g, b, x1 - x0); - else - art_rgb_run_alpha1(linebuf, r, g, b, alphatab[alpha], x1 - x0); - } - } - - data->buf += data->rowstride; -} - -void art_rgb_svp_alpha1(const ArtSVP *svp, - int x0, int y0, int x1, int y1, - uint32 color, - art_u8 *buf, int rowstride) { - ArtRgbSVPAlphaData data; - byte r, g, b, alpha; - int i; - int a, da; - - //Graphics::colorToARGB<Graphics::ColorMasks<8888> >(color, alpha, r, g, b); - alpha = (color >> 24) & 0xff; - b = (color >> 16) & 0xff; - g = (color >> 8) & 0xff; - r = (color >> 0) & 0xff; - - data.r = r; - data.g = g; - data.b = b; - data.alpha = alpha; - - a = 0x8000; - da = (alpha * 66051 + 0x80) >> 8; /* 66051 equals 2 ^ 32 / (255 * 255) */ - - for (i = 0; i < 256; i++) { - data.alphatab[i] = a >> 16; - a += da; - } - - data.buf = buf; - data.rowstride = rowstride; - data.x0 = x0; - data.x1 = x1; - if (alpha == 255) - art_svp_render_aa(svp, x0, y0, x1, y1, art_rgb_svp_alpha_opaque_callback1, &data); - else - art_svp_render_aa(svp, x0, y0, x1, y1, art_rgb_svp_alpha_callback1, &data); -} - -static int art_vpath_len(ArtVpath *a) { - int i; - - for (i = 0; a[i].code != ART_END; i++); - return i; -} - -ArtVpath *art_vpath_cat(ArtVpath *a, ArtVpath *b) { - ArtVpath *dest; - ArtVpath *p; - int len_a, len_b; - - len_a = art_vpath_len(a); - len_b = art_vpath_len(b); - dest = art_new(ArtVpath, len_a + len_b + 1); - p = dest; - - for (int i = 0; i < len_a; i++) - *p++ = *a++; - for (int i = 0; i <= len_b; i++) - *p++ = *b++; - - return dest; -} - -void art_svp_make_convex(ArtSVP *svp) { - int i; - - if (svp->n_segs > 0 && svp->segs[0].dir == 0) { - for (i = 0; i < svp->n_segs; i++) { - svp->segs[i].dir = !svp->segs[i].dir; - } - } -} - -ArtVpath *art_vpath_reverse(ArtVpath *a) { - ArtVpath *dest; - ArtVpath it; - int len; - int state = 0; - int i; - - len = art_vpath_len(a); - dest = art_new(ArtVpath, len + 1); - - for (i = 0; i < len; i++) { - it = a[len - i - 1]; - if (state) { - it.code = ART_LINETO; - } else { - it.code = ART_MOVETO_OPEN; - state = 1; - } - if (a[len - i - 1].code == ART_MOVETO || - a[len - i - 1].code == ART_MOVETO_OPEN) { - state = 0; - } - dest[i] = it; - } - dest[len] = a[len]; - - return dest; -} - -ArtVpath *art_vpath_reverse_free(ArtVpath *a) { - ArtVpath *dest; - - dest = art_vpath_reverse(a); - free(a); - - return dest; -} - -void drawBez(ArtBpath *bez1, ArtBpath *bez2, art_u8 *buffer, int width, int height, int deltaX, int deltaY, double scaleX, double scaleY, double penWidth, unsigned int color) { - ArtVpath *vec = NULL; - ArtVpath *vec1 = NULL; - ArtVpath *vec2 = NULL; - ArtSVP *svp = NULL; - -#if DEBUG - const char *codes[] = {"ART_MOVETO", "ART_MOVETO_OPEN", "ART_CURVETO", "ART_LINETO", "ART_END"}; - for (int i = 0;; i++) { - printf(" bez1[%d].code = %s;\n", i, codes[bez1[i].code]); - if (bez1[i].code == ART_END) - break; - if (bez1[i].code == ART_CURVETO) { - printf(" bez1[%d].x1 = %f; bez1[%d].y1 = %f;\n", i, bez1[i].x1, i, bez1[i].y1); - printf(" bez1[%d].x2 = %f; bez1[%d].y2 = %f;\n", i, bez1[i].x2, i, bez1[i].y2); - } - printf(" bez1[%d].x3 = %f; bez1[%d].y3 = %f;\n", i, bez1[i].x3, i, bez1[i].y3); - } - if (bez2 != 0) { - for (int i = 0;; i++) { - printf(" bez2[%d].code = %s;\n", i, codes[bez2[i].code]); - if (bez2[i].code == ART_END) - break; - if (bez2[i].code == ART_CURVETO) { - printf(" bez2[%d].x1 = %f; bez2[%d].y1 = %f;\n", i, bez2[i].x1, i, bez2[i].y1); - printf(" bez2[%d].x2 = %f; bez2[%d].y2 = %f;\n", i, bez2[i].x2, i, bez2[i].y2); - } - printf(" bez2[%d].x3 = %f; bez2[%d].y3 = %f;\n", i, bez2[i].x3, i, bez2[i].y3); - } - printf(" drawBez(bez1, bez2, buffer, 1.0, 1.0, %f, 0x%08x);\n", penWidth, color); - } else { - printf(" drawBez(bez1, 0, buffer, 1.0, 1.0, %f, 0x%08x);\n", penWidth, color); - } - -#endif - - vec1 = art_bez_path_to_vec(bez1, 0.5); - if (bez2 != 0) { - vec2 = art_bez_path_to_vec(bez2, 0.5); - vec2 = art_vpath_reverse_free(vec2); - vec = art_vpath_cat(vec1, vec2); - - free(vec1); - free(vec2); - } else { - vec = vec1; - } - - if (scaleX != 1.0 || scaleY != 1.0) { - ArtVpath *vect; - int size = art_vpath_len(vec); - - vect = art_new(ArtVpath, size + 1); - - int k; - for (k = 0; k < size; k++) { - vect[k].code = vec[k].code; - vect[k].x = vec[k].x * scaleX; - vect[k].y = vec[k].y * scaleY; - } - vect[k].code = ART_END; - free(vec); - - vec = vect; - } - - if (bez2 == 0) { // Line drawing - svp = art_svp_vpath_stroke(vec, ART_PATH_STROKE_JOIN_ROUND, ART_PATH_STROKE_CAP_ROUND, penWidth, 1.0, 0.5); - } else { - svp = art_svp_from_vpath(vec); - art_svp_make_convex(svp); - } - - art_rgb_svp_alpha1(svp, 0 + deltaX, 0 + deltaY, width + deltaX, height + deltaY, color, buffer, width * 4); - - free(svp); - free(vec); -} - -void VectorImage::render(int width, int height) { - double scaleX = (width == - 1) ? 1 : static_cast<double>(width) / static_cast<double>(getWidth()); - double scaleY = (height == - 1) ? 1 : static_cast<double>(height) / static_cast<double>(getHeight()); - - //debug(0, "VectorImage::render(%d, %d) %s", width, height, _fname.c_str()); - - printf("%d x %d\n", width, height); - printf("%d x %d - %d x %d\n", _boundingBox.left, _boundingBox.top, _boundingBox.right, _boundingBox.bottom); - - if (_pixelData) - free(_pixelData); - - _pixelData = (byte *)malloc(width * height * 4); - memset(_pixelData, 0, width * height * 4); - - for (uint e = 0; e < _elements.size(); e++) { -#if DEBUG - printf("----------------> Element\n"); -#endif - - //// Draw shapes - for (uint s = 0; s < _elements[e].getFillStyleCount(); s++) { - int fill0len = 0; - int fill1len = 0; - - // Count vector sizes in order to minimize memory - // fragmentation - for (uint p = 0; p < _elements[e].getPathCount(); p++) { - if (_elements[e].getPathInfo(p).getFillStyle0() == s + 1) - fill0len += _elements[e].getPathInfo(p).getVecLen(); - - if (_elements[e].getPathInfo(p).getFillStyle1() == s + 1) - fill1len += _elements[e].getPathInfo(p).getVecLen(); - } - - // Now lump together vectors - ArtBpath *fill1 = art_new(ArtBpath, fill1len + 1); - ArtBpath *fill0 = art_new(ArtBpath, fill0len + 1); - ArtBpath *fill1pos = fill1; - ArtBpath *fill0pos = fill0; - - for (uint p = 0; p < _elements[e].getPathCount(); p++) { - if (_elements[e].getPathInfo(p).getFillStyle0() == s + 1) { - for (int i = 0; i < _elements[e].getPathInfo(p).getVecLen(); i++) - *fill0pos++ = _elements[e].getPathInfo(p).getVec()[i]; - } - - if (_elements[e].getPathInfo(p).getFillStyle1() == s + 1) { - for (int i = 0; i < _elements[e].getPathInfo(p).getVecLen(); i++) - *fill1pos++ = _elements[e].getPathInfo(p).getVec()[i]; - } - } - - // Close vectors - (*fill0pos).code = ART_END; - (*fill1pos).code = ART_END; - - drawBez(fill1, fill0, _pixelData, width, height, _boundingBox.left, _boundingBox.top, scaleX, scaleY, -1, _elements[e].getFillStyleColor(s)); - - free(fill0); - free(fill1); - } - - //// Draw strokes - for (uint s = 0; s < _elements[e].getLineStyleCount(); s++) { - double penWidth = _elements[e].getLineStyleWidth(s); - penWidth *= sqrt(fabs(scaleX * scaleY)); - - for (uint p = 0; p < _elements[e].getPathCount(); p++) { - if (_elements[e].getPathInfo(p).getLineStyle() == s + 1) { - drawBez(_elements[e].getPathInfo(p).getVec(), 0, _pixelData, width, height, _boundingBox.left, _boundingBox.top, scaleX, scaleY, penWidth, _elements[e].getLineStyleColor(s)); - } - } - } - } -} - - -} // End of namespace Sword25 |