mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-15 21:40:34 +00:00
Fix a bug with invalid m_ptr in image iterators when we merge down layers (fix issue 358)
The ImageIteratorT implementation was simplified to avoid invalid m_ptrs.
This commit is contained in:
parent
316223cee9
commit
77cd0e9cc6
@ -19,19 +19,12 @@
|
|||||||
#ifndef RASTER_IMAGE_ITERATOR_H_INCLUDED
|
#ifndef RASTER_IMAGE_ITERATOR_H_INCLUDED
|
||||||
#define RASTER_IMAGE_ITERATOR_H_INCLUDED
|
#define RASTER_IMAGE_ITERATOR_H_INCLUDED
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#include "gfx/point.h"
|
||||||
#define RASTER_DEBUG_ITERATORS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "gfx/rect.h"
|
#include "gfx/rect.h"
|
||||||
#include "raster/color.h"
|
#include "raster/color.h"
|
||||||
#include "raster/image.h"
|
#include "raster/image.h"
|
||||||
#include "raster/image_traits.h"
|
#include "raster/image_traits.h"
|
||||||
|
|
||||||
#ifdef RASTER_DEBUG_ITERATORS
|
|
||||||
#include "gfx/point.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
@ -57,66 +50,53 @@ namespace raster {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImageIteratorT(const ImageIteratorT& other) :
|
ImageIteratorT(const ImageIteratorT& other) :
|
||||||
|
m_image(other.m_image),
|
||||||
m_ptr(other.m_ptr),
|
m_ptr(other.m_ptr),
|
||||||
m_x(other.m_x),
|
m_x(other.m_x),
|
||||||
m_width(other.m_width),
|
m_y(other.m_y),
|
||||||
m_nextRow(other.m_nextRow)
|
m_xbegin(other.m_xbegin),
|
||||||
#ifdef RASTER_DEBUG_ITERATORS
|
m_xend(other.m_xend)
|
||||||
, m_image(other.m_image)
|
|
||||||
, m_X0(other.m_X0), m_X(other.m_X), m_Y(other.m_Y)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageIteratorT(const Image* image, const gfx::Rect& bounds, int x, int y) :
|
ImageIteratorT(const Image* image, const gfx::Rect& bounds, int x, int y) :
|
||||||
|
m_image(const_cast<Image*>(image)),
|
||||||
m_ptr((pointer)image->getPixelAddress(x, y)),
|
m_ptr((pointer)image->getPixelAddress(x, y)),
|
||||||
m_x(x - bounds.x),
|
m_x(x),
|
||||||
m_width(bounds.w),
|
m_y(y),
|
||||||
m_nextRow(image->getWidth() - bounds.w)
|
m_xbegin(bounds.x),
|
||||||
#ifdef RASTER_DEBUG_ITERATORS
|
m_xend(bounds.x + bounds.w)
|
||||||
, m_image(const_cast<Image*>(image))
|
|
||||||
, m_X0(bounds.x)
|
|
||||||
, m_X(x), m_Y(y)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
ASSERT(bounds.contains(gfx::Point(x, y)));
|
ASSERT(bounds.contains(gfx::Point(x, y)));
|
||||||
ASSERT(image->getBounds().contains(bounds));
|
ASSERT(image->getBounds().contains(bounds));
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageIteratorT& operator=(const ImageIteratorT& other) {
|
ImageIteratorT& operator=(const ImageIteratorT& other) {
|
||||||
|
m_image = other.m_image;
|
||||||
m_ptr = other.m_ptr;
|
m_ptr = other.m_ptr;
|
||||||
m_x = other.m_x;
|
m_x = other.m_x;
|
||||||
m_width = other.m_width;
|
m_y = other.m_y;
|
||||||
m_nextRow = other.m_nextRow;
|
m_xbegin = other.m_xbegin;
|
||||||
#ifdef RASTER_DEBUG_ITERATORS
|
m_xend = other.m_xend;
|
||||||
m_image = other.m_image;
|
|
||||||
m_X0 = other.m_X0;
|
|
||||||
m_X = other.m_X;
|
|
||||||
m_Y = other.m_Y;
|
|
||||||
#endif
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const ImageIteratorT& other) const {
|
bool operator==(const ImageIteratorT& other) const {
|
||||||
#ifdef RASTER_DEBUG_ITERATORS
|
|
||||||
if (m_ptr == other.m_ptr) {
|
if (m_ptr == other.m_ptr) {
|
||||||
ASSERT(m_X == other.m_X && m_Y == other.m_Y);
|
ASSERT(m_x == other.m_x && m_y == other.m_y);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ASSERT(m_X != other.m_X || m_Y != other.m_Y);
|
ASSERT(m_x != other.m_x || m_y != other.m_y);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return m_ptr == other.m_ptr;
|
return m_ptr == other.m_ptr;
|
||||||
}
|
}
|
||||||
bool operator!=(const ImageIteratorT& other) const {
|
bool operator!=(const ImageIteratorT& other) const {
|
||||||
#ifdef RASTER_DEBUG_ITERATORS
|
|
||||||
if (m_ptr != other.m_ptr) {
|
if (m_ptr != other.m_ptr) {
|
||||||
ASSERT(m_X != other.m_X || m_Y != other.m_Y);
|
ASSERT(m_x != other.m_x || m_y != other.m_y);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ASSERT(m_X == other.m_X && m_Y == other.m_Y);
|
ASSERT(m_x == other.m_x && m_y == other.m_y);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return m_ptr != other.m_ptr;
|
return m_ptr != other.m_ptr;
|
||||||
}
|
}
|
||||||
bool operator<(const ImageIteratorT& other) const { return m_ptr < other.m_ptr; }
|
bool operator<(const ImageIteratorT& other) const { return m_ptr < other.m_ptr; }
|
||||||
@ -125,37 +105,18 @@ namespace raster {
|
|||||||
bool operator>=(const ImageIteratorT& other) const { return m_ptr >= other.m_ptr; }
|
bool operator>=(const ImageIteratorT& other) const { return m_ptr >= other.m_ptr; }
|
||||||
|
|
||||||
ImageIteratorT& operator++() {
|
ImageIteratorT& operator++() {
|
||||||
#ifdef RASTER_DEBUG_ITERATORS
|
ASSERT(m_image->getBounds().contains(gfx::Point(m_x, m_y)));
|
||||||
ASSERT(m_image->getBounds().contains(gfx::Point(m_X, m_Y)));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
++m_ptr;
|
++m_ptr;
|
||||||
++m_x;
|
++m_x;
|
||||||
|
|
||||||
#ifdef RASTER_DEBUG_ITERATORS
|
if (m_x == m_xend) {
|
||||||
++m_X;
|
m_x = m_xbegin;
|
||||||
#endif
|
++m_y;
|
||||||
|
|
||||||
if (m_x == m_width) {
|
if (m_y < m_image->getHeight())
|
||||||
m_ptr += m_nextRow;
|
m_ptr = (pointer)m_image->getPixelAddress(m_x, m_y);
|
||||||
m_x = 0;
|
|
||||||
|
|
||||||
#ifdef RASTER_DEBUG_ITERATORS
|
|
||||||
m_X = m_X0;
|
|
||||||
++m_Y;
|
|
||||||
|
|
||||||
if (m_Y < m_image->getHeight()) {
|
|
||||||
pointer expected_ptr = (pointer)m_image->getPixelAddress(m_X, m_Y);
|
|
||||||
ASSERT(expected_ptr == m_ptr);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#ifdef RASTER_DEBUG_ITERATORS
|
|
||||||
else {
|
|
||||||
pointer expected_ptr = (pointer)m_image->getPixelAddress(m_X, m_Y);
|
|
||||||
ASSERT(expected_ptr == m_ptr);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -175,15 +136,11 @@ namespace raster {
|
|||||||
reference operator*() { return *m_ptr; }
|
reference operator*() { return *m_ptr; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
pointer m_ptr;
|
|
||||||
int m_bit;
|
|
||||||
int m_x;
|
|
||||||
int m_width;
|
|
||||||
int m_nextRow;
|
|
||||||
#ifdef RASTER_DEBUG_ITERATORS // Data used for debugging purposes.
|
|
||||||
Image* m_image;
|
Image* m_image;
|
||||||
int m_X0, m_X, m_Y;
|
pointer m_ptr;
|
||||||
#endif
|
int m_x, m_y;
|
||||||
|
int m_xbegin;
|
||||||
|
int m_xend;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ImageTraits>
|
template<typename ImageTraits>
|
||||||
@ -329,122 +286,81 @@ namespace raster {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImageIteratorT(const ImageIteratorT& other) :
|
ImageIteratorT(const ImageIteratorT& other) :
|
||||||
|
m_image(other.m_image),
|
||||||
m_ptr(other.m_ptr),
|
m_ptr(other.m_ptr),
|
||||||
m_x(other.m_x),
|
m_x(other.m_x),
|
||||||
|
m_y(other.m_y),
|
||||||
m_subPixel(other.m_subPixel),
|
m_subPixel(other.m_subPixel),
|
||||||
m_subPixel0(other.m_subPixel0),
|
m_xbegin(other.m_xbegin),
|
||||||
m_width(other.m_width),
|
m_xend(other.m_xend)
|
||||||
m_nextRow(other.m_nextRow)
|
|
||||||
#ifdef RASTER_DEBUG_ITERATORS
|
|
||||||
, m_image(other.m_image)
|
|
||||||
, m_X0(other.m_X0), m_X(other.m_X), m_Y(other.m_Y)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageIteratorT(const Image* image, const gfx::Rect& bounds, int x, int y) :
|
ImageIteratorT(const Image* image, const gfx::Rect& bounds, int x, int y) :
|
||||||
|
m_image(const_cast<Image*>(image)),
|
||||||
m_ptr((pointer)image->getPixelAddress(x, y)),
|
m_ptr((pointer)image->getPixelAddress(x, y)),
|
||||||
m_x(x - bounds.x),
|
m_x(x),
|
||||||
|
m_y(y),
|
||||||
m_subPixel(x % 8),
|
m_subPixel(x % 8),
|
||||||
m_subPixel0(bounds.x % 8),
|
m_xbegin(bounds.x),
|
||||||
m_width(bounds.w),
|
m_xend(bounds.x + bounds.w)
|
||||||
m_nextRow(// Bytes on the right of this row to jump to the beginning of the next one
|
|
||||||
BitmapTraits::getRowStrideBytes((pixels_per_byte*BitmapTraits::getRowStrideBytes(image->getWidth()))
|
|
||||||
- (bounds.x+bounds.w))
|
|
||||||
// Bytes on the left of the next row to go to bounds.x byte
|
|
||||||
+ bounds.x/pixels_per_byte)
|
|
||||||
|
|
||||||
#ifdef RASTER_DEBUG_ITERATORS
|
|
||||||
, m_image(const_cast<Image*>(image))
|
|
||||||
, m_X0(bounds.x)
|
|
||||||
, m_X(x), m_Y(y)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
ASSERT(bounds.contains(gfx::Point(x, y)));
|
ASSERT(bounds.contains(gfx::Point(x, y)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageIteratorT& operator=(const ImageIteratorT& other) {
|
ImageIteratorT& operator=(const ImageIteratorT& other) {
|
||||||
|
m_image = other.m_image;
|
||||||
m_ptr = other.m_ptr;
|
m_ptr = other.m_ptr;
|
||||||
m_x = other.m_x;
|
m_x = other.m_x;
|
||||||
|
m_y = other.m_y;
|
||||||
m_subPixel = other.m_subPixel;
|
m_subPixel = other.m_subPixel;
|
||||||
m_subPixel0 = other.m_subPixel0;
|
m_xbegin = other.m_xbegin;
|
||||||
m_width = other.m_width;
|
m_xend = other.m_xend;
|
||||||
m_nextRow = other.m_nextRow;
|
|
||||||
#ifdef RASTER_DEBUG_ITERATORS
|
|
||||||
m_image = other.m_image;
|
|
||||||
m_X0 = other.m_X0;
|
|
||||||
m_X = other.m_X;
|
|
||||||
m_Y = other.m_Y;
|
|
||||||
#endif
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const ImageIteratorT& other) const {
|
bool operator==(const ImageIteratorT& other) const {
|
||||||
#ifdef RASTER_DEBUG_ITERATORS
|
|
||||||
if (m_ptr == other.m_ptr &&
|
if (m_ptr == other.m_ptr &&
|
||||||
m_subPixel == other.m_subPixel) {
|
m_subPixel == other.m_subPixel) {
|
||||||
ASSERT(m_X == other.m_X && m_Y == other.m_Y);
|
ASSERT(m_x == other.m_x && m_y == other.m_y);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ASSERT(m_X != other.m_X || m_Y != other.m_Y);
|
ASSERT(m_x != other.m_x || m_y != other.m_y);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return m_ptr == other.m_ptr;
|
return m_ptr == other.m_ptr;
|
||||||
}
|
}
|
||||||
bool operator!=(const ImageIteratorT& other) const {
|
bool operator!=(const ImageIteratorT& other) const {
|
||||||
#ifdef RASTER_DEBUG_ITERATORS
|
|
||||||
if (m_ptr != other.m_ptr ||
|
if (m_ptr != other.m_ptr ||
|
||||||
m_subPixel != other.m_subPixel) {
|
m_subPixel != other.m_subPixel) {
|
||||||
ASSERT(m_X != other.m_X || m_Y != other.m_Y);
|
ASSERT(m_x != other.m_x || m_y != other.m_y);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ASSERT(m_X == other.m_X && m_Y == other.m_Y);
|
ASSERT(m_x == other.m_x && m_y == other.m_y);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return m_ptr != other.m_ptr;
|
return m_ptr != other.m_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageIteratorT& operator++() {
|
ImageIteratorT& operator++() {
|
||||||
#ifdef RASTER_DEBUG_ITERATORS
|
ASSERT(m_image->getBounds().contains(gfx::Point(m_x, m_y)));
|
||||||
ASSERT(m_image->getBounds().contains(gfx::Point(m_X, m_Y)));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
++m_x;
|
++m_x;
|
||||||
++m_subPixel;
|
++m_subPixel;
|
||||||
|
|
||||||
if (m_subPixel == 8) {
|
if (m_x == m_xend) {
|
||||||
|
m_x = m_xbegin;
|
||||||
|
m_subPixel = m_x % 8;
|
||||||
|
++m_y;
|
||||||
|
|
||||||
|
if (m_y < m_image->getHeight())
|
||||||
|
m_ptr = (pointer)m_image->getPixelAddress(m_x, m_y);
|
||||||
|
else
|
||||||
|
++m_ptr;
|
||||||
|
}
|
||||||
|
else if (m_subPixel == 8) {
|
||||||
m_subPixel = 0;
|
m_subPixel = 0;
|
||||||
++m_ptr;
|
++m_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef RASTER_DEBUG_ITERATORS
|
|
||||||
++m_X;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (m_x == m_width) {
|
|
||||||
m_ptr += m_nextRow;
|
|
||||||
m_x = 0;
|
|
||||||
m_subPixel = m_subPixel0;
|
|
||||||
|
|
||||||
#ifdef RASTER_DEBUG_ITERATORS
|
|
||||||
m_X = m_X0;
|
|
||||||
++m_Y;
|
|
||||||
|
|
||||||
if (m_Y < m_image->getHeight()) {
|
|
||||||
pointer expected_ptr = (pointer)m_image->getPixelAddress(m_X, m_Y);
|
|
||||||
ASSERT(expected_ptr == m_ptr);
|
|
||||||
ASSERT(m_subPixel == m_X % 8);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#ifdef RASTER_DEBUG_ITERATORS
|
|
||||||
else {
|
|
||||||
pointer expected_ptr = (pointer)m_image->getPixelAddress(m_X, m_Y);
|
|
||||||
ASSERT(expected_ptr == m_ptr);
|
|
||||||
ASSERT(m_subPixel == m_X % 8);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,15 +387,13 @@ namespace raster {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
pointer m_ptr;
|
|
||||||
int m_x, m_subPixel, m_subPixel0;
|
|
||||||
int m_width;
|
|
||||||
int m_nextRow;
|
|
||||||
mutable BitPixelAccess m_access;
|
|
||||||
#ifdef RASTER_DEBUG_ITERATORS // Data used for debugging purposes.
|
|
||||||
Image* m_image;
|
Image* m_image;
|
||||||
int m_X0, m_X, m_Y;
|
pointer m_ptr;
|
||||||
#endif
|
int m_x, m_y;
|
||||||
|
int m_subPixel;
|
||||||
|
int m_xbegin;
|
||||||
|
int m_xend;
|
||||||
|
mutable BitPixelAccess m_access;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user