Permalink
Browse files

Redo scaling. Now scaling is fully supported for infinite grid.

  • Loading branch information...
1 parent 99ded11 commit 116dd8074c1b3a56c6fd2189d51fe38e1f656e1e @wishstudio committed Dec 21, 2011
Showing with 219 additions and 120 deletions.
  1. +1 −1 src/AbstractAlgorithm.h
  2. +40 −0 src/BigInteger.cpp
  3. +8 −0 src/BigInteger.h
  4. +7 −7 src/CanvasPainter.cpp
  5. +1 −1 src/CanvasPainter.h
  6. +52 −29 src/Editor.cpp
  7. +3 −2 src/Editor.h
  8. +104 −77 src/NaiveLife.cpp
  9. +3 −3 src/NaiveLife.h
View
@@ -38,7 +38,7 @@ class AbstractAlgorithm: public QThread
virtual BigInteger population() const = 0;
virtual void getRect(BigInteger *x, BigInteger *y, BigInteger *w, BigInteger *h);
virtual void setRect(const BigInteger &x, const BigInteger &y, const BigInteger &w, const BigInteger &h);
- virtual void paint(CanvasPainter *painter, const BigInteger &x, const BigInteger &y, int w, int h) = 0;
+ virtual void paint(CanvasPainter *painter, const BigInteger &x, const BigInteger &y, int w, int h, size_t scale) = 0;
virtual void runStep() = 0;
virtual bool acceptInfinity() { return m_acceptInfinity; }
View
@@ -188,6 +188,13 @@ BigInteger BigInteger::operator + (int num) const
return ret;
}
+BigInteger BigInteger::operator + (unsigned long num) const
+{
+ BigInteger ret;
+ mpz_add_ui(ret.data, data, num);
+ return ret;
+}
+
BigInteger& BigInteger::operator += (const BigInteger &num)
{
mpz_add(data, data, num.data);
@@ -220,6 +227,13 @@ BigInteger BigInteger::operator - (int num) const
return ret;
}
+BigInteger BigInteger::operator - (unsigned long num) const
+{
+ BigInteger ret;
+ mpz_sub_ui(ret.data, data, num);
+ return ret;
+}
+
BigInteger& BigInteger::operator -= (const BigInteger &num)
{
mpz_sub(data, data, num.data);
@@ -255,6 +269,32 @@ BigInteger BigInteger::operator / (int num) const
return ret;
}
+BigInteger BigInteger::operator << (size_t num) const
+{
+ BigInteger ret;
+ mpz_mul_2exp(ret.data, data, num);
+ return ret;
+}
+
+BigInteger& BigInteger::operator <<= (size_t num)
+{
+ mpz_mul_2exp(data, data, num);
+ return *this;
+}
+
+BigInteger BigInteger::operator >> (size_t num) const
+{
+ BigInteger ret;
+ mpz_div_2exp(ret.data, data, num);
+ return ret;
+}
+
+BigInteger& BigInteger::operator >>= (size_t num)
+{
+ mpz_div_2exp(data, data, num);
+ return *this;
+}
+
bool BigInteger::operator == (const BigInteger &num) const
{
return mpz_cmp(data, num.data) == 0;
View
@@ -56,17 +56,25 @@ class BigInteger
BigInteger operator + (const BigInteger &num) const;
BigInteger operator + (int num) const;
+ BigInteger operator + (unsigned long num) const;
BigInteger& operator += (const BigInteger &num);
BigInteger& operator += (int num);
BigInteger operator - (const BigInteger &num) const;
BigInteger operator - (int num) const;
+ BigInteger operator - (unsigned long num) const;
BigInteger& operator -= (const BigInteger &num);
BigInteger& operator -= (int num);
BigInteger operator * (int num) const;
BigInteger operator / (int num) const;
+ BigInteger operator << (size_t num) const;
+ BigInteger& operator <<= (size_t num);
+
+ BigInteger operator >> (size_t num) const;
+ BigInteger& operator >>= (size_t num);
+
bool operator == (const BigInteger &num) const;
bool operator == (int num) const;
bool operator != (const BigInteger &num) const;
View
@@ -22,29 +22,29 @@
#include "BigInteger.h"
#include "CanvasPainter.h"
-CanvasPainter::CanvasPainter(QPaintDevice *device, const BigInteger &view_x, const BigInteger &view_y, int x1, int x2, int y1, int y2, int scalePixel)
+CanvasPainter::CanvasPainter(QPaintDevice *device, const BigInteger &view_x, const BigInteger &view_y, int x1, int x2, int y1, int y2, int scale, int scalePixel)
: QPainter(device), m_scalePixel(scalePixel), m_x(x1), m_y(y1)
{
// Draw background
fillRect(0, 0, device->width(), device->height(), QColor(0x80, 0x80, 0x80));
// Draw grid
- AlgorithmManager::algorithm()->paint(this, view_x + x1, view_y + y1, x2 - x1 + 1, y2 - y1 + 1);
+ AlgorithmManager::algorithm()->paint(this, view_x + x1, view_y + y1, x2 - x1 + 1, y2 - y1 + 1, scale);
// Draw grid line
- if (scalePixel > 2)
+ if (scalePixel > 1)
{
// Draw vertical grid line
for (int i = x1; i < x2; i++)
{
setPen((i + 1 + view_x) % 10 == 0? QColor(0x70, 0x70, 0x70): QColor(0x50, 0x50, 0x50));
- drawLine((i + 1) * scalePixel - 1, y1 * scalePixel, (i + 1) * scalePixel - 1, (y2 + 1) * scalePixel - 1);
+ drawLine(((i + 1) << scalePixel) - 1, y1 << scalePixel, ((i + 1) << scalePixel) - 1, ((y2 + 1) << scalePixel) - 1);
}
// Draw horizontal grid line
for (int i = y1; i < y2; i++)
{
setPen((i + 1 + view_y) % 10 == 0? QColor(0x70, 0x70, 0x70): QColor(0x50, 0x50, 0x50));
- drawLine(x1 * scalePixel, (i + 1) * scalePixel - 1, (x2 + 1) * scalePixel - 1, (i + 1) * scalePixel - 1);
+ drawLine(x1 << scalePixel, ((i + 1) << scalePixel) - 1, ((x2 + 1) << scalePixel) - 1, ((i + 1) << scalePixel) - 1);
}
}
}
@@ -56,11 +56,11 @@ CanvasPainter::~CanvasPainter()
void CanvasPainter::drawGrid(int x, int y, int state)
{
QColor gridColor = state? Qt::white: QColor(0x30, 0x30, 0x30);
- fillRect((m_x + x) * m_scalePixel, (m_y + y) * m_scalePixel, m_scalePixel, m_scalePixel, gridColor);
+ fillRect((m_x + x) << m_scalePixel, (m_y + y) << m_scalePixel, 1 << m_scalePixel, 1 << m_scalePixel, gridColor);
}
void CanvasPainter::fillGrid(int x, int y, int w, int h, int state)
{
QColor gridColor = state? Qt::white: QColor(0x30, 0x30, 0x30);
- fillRect((m_x + x) * m_scalePixel, (m_y + y) * m_scalePixel, m_scalePixel * w, m_scalePixel * h, gridColor);
+ fillRect((m_x + x) << m_scalePixel, (m_y + y) << m_scalePixel, (1 << m_scalePixel) * w, (1 << m_scalePixel) * h, gridColor);
}
View
@@ -26,7 +26,7 @@ class BigInteger;
class CanvasPainter: public QPainter
{
public:
- CanvasPainter(QPaintDevice *device, const BigInteger &view_x, const BigInteger &view_y, int x1, int x2, int y1, int y2, int scalePixel);
+ CanvasPainter(QPaintDevice *device, const BigInteger &view_x, const BigInteger &view_y, int x1, int x2, int y1, int y2, int scale, int scalePixel);
virtual ~CanvasPainter();
void drawGrid(int x, int y, int state);
View
@@ -35,13 +35,14 @@
#include "CanvasPainter.h"
#include "Editor.h"
-static const int scalePixelCnt = 4;
-static const int scalePixel[5] = {1, 2, 4, 8, 16};
+static const size_t maxScalePixel = 4;
+// Scale ratio is: 2^scale: 2^scalePixel
+// Max scale: 1: 16
Editor::Editor(QWidget *parent)
: QWidget(parent), m_rect_x1(0), m_rect_y1(0), m_rect_x2(0), m_rect_y2(0), m_view_x(0), m_view_y(0),
m_scroll_last_x(0), m_scroll_last_y(0),
- m_scale(-scalePixelCnt), m_scalePixel(scalePixel[scalePixelCnt])
+ m_scale(0), m_scalePixel(maxScalePixel)
{
QToolBar *toolbar = new QToolBar();
KAction *stepAction = new KAction(this);
@@ -98,8 +99,8 @@ void Editor::rectChanged()
void Editor::viewResized()
{
- m_vertGridCount = m_canvas->height() / m_scalePixel;
- m_horiGridCount = m_canvas->width() / m_scalePixel;
+ m_vertGridCount = m_canvas->height() >> m_scalePixel;
+ m_horiGridCount = m_canvas->width() >> m_scalePixel;
m_vertEdgeSpacing = m_horiEdgeSpacing = 5;
disconnect(m_vertScroll, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int)));
if (AlgorithmManager::algorithm()->isVerticalInfinity())
@@ -174,6 +175,7 @@ void Editor::scrollChanged(int)
emit update();
return;
}
+ // FIXME: This is not correct now, fix me when adding back finite grid support
if (scrollBar->orientation() == Qt::Vertical)
{
if (!AlgorithmManager::algorithm()->isVerticalInfinity())
@@ -194,6 +196,7 @@ void Editor::scrollReleased()
void Editor::setViewPoint(const BigInteger &x, const BigInteger &y)
{
+ // FIXME: This is not correct now, fix me when adding back finite grid support
if (!AlgorithmManager::algorithm()->isVerticalInfinity())
m_vertScroll->setSliderPosition(y - m_rect_y1 + m_vertEdgeSpacing);
else
@@ -210,21 +213,34 @@ void Editor::resetViewPoint()
setViewPoint(m_view_x, m_view_y);
}
-void Editor::scaleView(int scale, int anchor_x, int anchor_y)
+void Editor::scaleView(int scaleDelta, size_t anchor_x, size_t anchor_y)
{
- if (scale != m_scale)
+ if (scaleDelta)
{
- int old_scalePixel = m_scalePixel;
- if ((m_scale = scale) >= 0)
- m_scalePixel = 1;
+ size_t old_scale = m_scale, old_scalePixel = m_scalePixel;
+ if (scaleDelta > 0)
+ {
+ size_t d = qMin(m_scale, static_cast<size_t>(scaleDelta));
+ m_scale -= d;
+ m_scalePixel = qMin(maxScalePixel, m_scalePixel + scaleDelta - d);
+ }
else
- m_scalePixel = scalePixel[-m_scale];
- m_view_y += anchor_y - anchor_y * old_scalePixel / m_scalePixel;
+ {
+ size_t d = qMin(m_scalePixel, static_cast<size_t>(-scaleDelta));
+ m_scalePixel -= d;
+ m_scale += -scaleDelta - d;
+ }
+ // Formula:
+ // (view_x + x / 2^scalePixel) << scale == (old_view_x + x / 2^old_scalePixel) << old_scale
+ // FIXME: This is not correct now, fix me when adding back finite grid support
+ m_view_y = ((m_view_y + (anchor_y >> old_scalePixel)) << old_scale >> m_scale) - (anchor_y >> m_scalePixel);
if (!AlgorithmManager::algorithm()->isVerticalInfinity())
m_view_y = qBound(m_rect_y1, m_view_y, m_rect_y2);
- m_view_x += anchor_x - anchor_x * old_scalePixel / m_scalePixel;
+
+ m_view_x = ((m_view_x + (anchor_x >> old_scalePixel)) << old_scale >> m_scale) - (anchor_x >> m_scalePixel);
if (!AlgorithmManager::algorithm()->isHorizontalInfinity())
m_view_x = qBound(m_rect_x1, m_view_x, m_rect_x2);
+
viewResized();
}
}
@@ -237,37 +253,42 @@ bool Editor::eventFilter(QObject *obj, QEvent *event)
{
case QEvent::Paint:
{
+ size_t scale = qMax(m_scale, 0UL);
// Calculate grid size
int y1 = 0, y2 = m_vertGridCount;
if (!AlgorithmManager::algorithm()->isVerticalInfinity())
{
- y1 = qMax(y1, (int) (m_rect_y1 - m_view_y));
- y2 = qMin(y2, (int) (m_rect_y2 - m_view_y));
+ y1 = qMax(y1, (int) ((m_rect_y1 >> scale) - m_view_y));
+ y2 = qMin(y2, (int) ((m_rect_y2 >> scale) - m_view_y));
}
int x1 = 0, x2 = m_horiGridCount;
if (!AlgorithmManager::algorithm()->isHorizontalInfinity())
{
- x1 = qMax(x1, (int) (m_rect_x1 - m_view_x));
- x2 = qMin(x2, (int) (m_rect_x2 - m_view_x));
+ x1 = qMax(x1, (int) ((m_rect_x1 >> scale) - m_view_x));
+ x2 = qMin(x2, (int) ((m_rect_x2 >> scale) - m_view_x));
}
- CanvasPainter painter(m_canvas, m_view_x, m_view_y, x1, x2, y1, y2, m_scalePixel);
+ CanvasPainter painter(m_canvas, m_view_x, m_view_y, x1, x2, y1, y2, qMax(m_scale, 0UL), m_scalePixel);
break;
}
case QEvent::MouseMove:
case QEvent::MouseButtonPress:
{
QMouseEvent *e = static_cast<QMouseEvent *>(event);
- BigInteger x = m_view_x + e->x() / m_scalePixel, y = m_view_y + e->y() / m_scalePixel;
- if (e->buttons() & Qt::LeftButton)
+ BigInteger x = (m_view_x + (e->x() >> m_scalePixel)) << m_scale;
+ BigInteger y = (m_view_y + (e->y() >> m_scalePixel)) << m_scale;
+ if (!m_scale)
{
- bool inRange = true;
- if (!AlgorithmManager::algorithm()->isVerticalInfinity())
- inRange &= m_rect_x1 <= x && x <= m_rect_x2;
- if (!AlgorithmManager::algorithm()->isHorizontalInfinity())
- inRange &= m_rect_y1 <= y && y <= m_rect_y2;
- if (inRange)
- AlgorithmManager::algorithm()->setGrid(x, y, 1);
+ if (e->buttons() & Qt::LeftButton)
+ {
+ bool inRange = true;
+ if (!AlgorithmManager::algorithm()->isVerticalInfinity())
+ inRange &= m_rect_x1 <= x && x <= m_rect_x2;
+ if (!AlgorithmManager::algorithm()->isHorizontalInfinity())
+ inRange &= m_rect_y1 <= y && y <= m_rect_y2;
+ if (inRange)
+ AlgorithmManager::algorithm()->setGrid(x, y, 1);
+ }
}
emit coordinateChanged(x, y);
break;
@@ -278,7 +299,7 @@ bool Editor::eventFilter(QObject *obj, QEvent *event)
QWheelEvent *e = static_cast<QWheelEvent *>(event);
if (e->modifiers() & Qt::ControlModifier) // Scale view
{
- scaleView(qMax(-scalePixelCnt, m_scale - e->delta() / 120), e->x() / m_scalePixel, e->y() / m_scalePixel);
+ scaleView(e->delta() / 120, e->x(), e->y());
emit update();
}
else
@@ -288,7 +309,9 @@ bool Editor::eventFilter(QObject *obj, QEvent *event)
else
QApplication::sendEvent(m_horiScroll, e);
}
- emit coordinateChanged(m_view_x + e->x() / m_scalePixel, m_view_y + e->y() / m_scalePixel);
+ BigInteger x = (m_view_x + (e->x() >> m_scalePixel)) << m_scale;
+ BigInteger y = (m_view_y + (e->y() >> m_scalePixel)) << m_scale;
+ emit coordinateChanged(x, y);
break;
}
View
@@ -49,7 +49,7 @@ public slots:
private:
void resetViewPoint();
void viewResized();
- void scaleView(int scale, int anchor_x, int anchor_y);
+ void scaleView(int scaleDelta, size_t anchor_x, size_t anchor_y);
bool eventFilter(QObject *obj, QEvent *event);
QWidget *m_canvas;
@@ -59,7 +59,8 @@ public slots:
BigInteger m_view_x, m_view_y;
int m_scroll_last_x, m_scroll_last_y;
int m_vertEdgeSpacing, m_horiEdgeSpacing;
- int m_scale, m_scalePixel, m_vertGridCount, m_horiGridCount;
+ int m_vertGridCount, m_horiGridCount;
+ size_t m_scale, m_scalePixel;
};
#endif
Oops, something went wrong.

0 comments on commit 116dd80

Please sign in to comment.