Permalink
Browse files

Add zoom out (related to issue #33)

Before the zoom was handle as a bits shift (scaled = value << zoom),
now the zoom is a fraction (scaled = value * zoom.num / zoom.den).

Changes:
* Add Zoom class to apply/remove zoom factor
* Split merge_zoomed_image template function into
  merge_zoomed_image_scale_down and merge_zoomed_image_scale_up
  to handle the special case where zoom.num/zoom.den < 1.0
  • Loading branch information...
dacap committed Nov 24, 2014
1 parent 17b0bee commit 4fc28d5639c56ebe83de0a6c901f982216fdd0b2
View
@@ -259,4 +259,5 @@ add_library(app-lib
webserver.cpp
widget_loader.cpp
xml_document.cpp
xml_exception.cpp)
xml_exception.cpp
zoom.cpp)
@@ -99,13 +99,13 @@ void MoveMaskCommand::onExecute(Context* context)
pixels = gridBounds.h;
break;
case ZoomedPixel:
pixels = 1 << current_editor->zoom();
pixels = current_editor->zoom().apply(1);
break;
case ZoomedTileWidth:
pixels = gridBounds.w << current_editor->zoom();
pixels = current_editor->zoom().apply(gridBounds.w);
break;
case ZoomedTileHeight:
pixels = gridBounds.h << current_editor->zoom();
pixels = current_editor->zoom().apply(gridBounds.h);
break;
case ViewportWidth:
pixels = vp.h;
@@ -63,7 +63,8 @@ class PreviewWindow : public Window {
, m_pal(m_sprite->getPalette(editor->frame()))
, m_index_bg_color(-1)
, m_doublebuf(Image::create(IMAGE_RGB, ui::display_w(), ui::display_h()))
, m_doublesur(she::instance()->createRgbaSurface(ui::display_w(), ui::display_h())) {
, m_doublesur(she::instance()->createRgbaSurface(ui::display_w(), ui::display_h()))
, m_zoom(editor->zoom()) {
// Do not use DocumentWriter (do not lock the document) because we
// will call other sub-commands (e.g. previous frame, next frame,
// etc.).
@@ -83,7 +84,6 @@ class PreviewWindow : public Window {
m_oldMousePos = ui::get_mouse_position();
m_pos.x = -scroll.x + vp.x + editor->offsetX();
m_pos.y = -scroll.y + vp.y + editor->offsetY();
m_zoom = editor->zoom();
setFocusStop(true);
captureMouse();
@@ -193,14 +193,14 @@ class PreviewWindow : public Window {
m_render.reset(
renderEngine.renderSprite(
0, 0, m_sprite->width(), m_sprite->height(),
m_editor->frame(), 0, false, false));
m_editor->frame(), Zoom(1, 1), false, false));
}
int x, y, w, h, u, v;
x = m_pos.x + ((m_delta.x >> m_zoom) << m_zoom);
y = m_pos.y + ((m_delta.y >> m_zoom) << m_zoom);
w = (m_sprite->width()<<m_zoom);
h = (m_sprite->height()<<m_zoom);
x = m_pos.x + m_zoom.apply(m_zoom.remove(m_delta.x));
y = m_pos.y + m_zoom.apply(m_zoom.remove(m_delta.y));
w = m_zoom.apply(m_sprite->width());
h = m_zoom.apply(m_sprite->height());
if (m_tiled & TILED_X_AXIS) x = SGN(x) * (ABS(x)%w);
if (m_tiled & TILED_Y_AXIS) y = SGN(y) * (ABS(y)%h);
@@ -243,7 +243,7 @@ class PreviewWindow : public Window {
gfx::Point m_pos;
gfx::Point m_oldMousePos;
gfx::Point m_delta;
int m_zoom;
Zoom m_zoom;
int m_index_bg_color;
base::UniquePtr<Image> m_render;
base::UniquePtr<Image> m_doublebuf;
@@ -117,13 +117,13 @@ void ScrollCommand::onExecute(Context* context)
pixels = gridBounds.h;
break;
case ZoomedPixel:
pixels = 1 << current_editor->zoom();
pixels = current_editor->zoom().apply(1);
break;
case ZoomedTileWidth:
pixels = gridBounds.w << current_editor->zoom();
pixels = current_editor->zoom().apply(gridBounds.w);
break;
case ZoomedTileHeight:
pixels = gridBounds.h << current_editor->zoom();
pixels = current_editor->zoom().apply(gridBounds.h);
break;
case ViewportWidth:
pixels = vp.h;
@@ -74,25 +74,23 @@ bool ZoomCommand::onEnabled(Context* context)
void ZoomCommand::onExecute(Context* context)
{
int zoom = current_editor->zoom();
Zoom zoom = current_editor->zoom();
switch (m_action) {
case In:
if (zoom < 5)
++zoom;
zoom.in();
break;
case Out:
if (zoom > 0)
--zoom;
zoom.out();
break;
case Set:
switch (m_percentage) {
case 3200: zoom = 5; break;
case 1600: zoom = 4; break;
case 800: zoom = 3; break;
case 400: zoom = 2; break;
case 200: zoom = 1; break;
default: zoom = 0; break;
case 3200: zoom = Zoom(32, 1); break;
case 1600: zoom = Zoom(16, 1); break;
case 800: zoom = Zoom(8, 1); break;
case 400: zoom = Zoom(4, 1); break;
case 200: zoom = Zoom(2, 1); break;
default: zoom = Zoom(1, 1); break;
}
break;
}
@@ -257,8 +257,8 @@ void FilterManagerImpl::flush()
m_x+m_offset_x,
m_y+m_offset_y+m_row-1)),
gfx::Size(
(m_w << editor->zoom()),
(1 << editor->zoom())));
editor->zoom().apply(m_w),
editor->zoom().apply(1)));
gfx::Region reg1(rect);
gfx::Region reg2;
@@ -85,7 +85,7 @@ class ThumbnailGenerator::Worker {
base::UniquePtr<Image> image(renderEngine.renderSprite(
0, 0, sprite->width(), sprite->height(),
FrameNumber(0), 0, true, false));
FrameNumber(0), Zoom(1, 1), true, false));
// Calculate the thumbnail size
int thumb_w = MAX_THUMBNAIL_SIZE * image->width() / MAX(image->width(), image->height());
@@ -22,6 +22,7 @@
#include "app/settings/selection_mode.h"
#include "app/tools/trace_policy.h"
#include "app/zoom.h"
#include "doc/frame_number.h"
#include "filters/tiled_mode.h"
#include "gfx/point.h"
@@ -104,6 +105,9 @@ namespace app {
// Gets mask X,Y origin coordinates
virtual gfx::Point getMaskOrigin() = 0;
// Returns the zoom
virtual const Zoom& zoom() = 0;
// Return the mouse button which start the tool-loop. It can be used
// by some tools that instead of using the primary/secondary color
// uses the pressed button for different behavior (like selection
@@ -213,7 +213,7 @@ void ToolLoopManager::doLoopStep(bool last_step)
// Calculate the area to be updated in all document observers.
Region& dirty_area = m_toolLoop->getDirtyArea();
calculateDirtyArea(m_toolLoop, points_to_interwine, dirty_area);
calculateDirtyArea(points_to_interwine, dirty_area);
if (m_toolLoop->getTracePolicy() == TracePolicyLast) {
Region prev_dirty_area = dirty_area;
@@ -235,7 +235,7 @@ void ToolLoopManager::snapToGrid(Point& point)
m_toolLoop->getDocumentSettings()->snapToGrid(point);
}
void ToolLoopManager::calculateDirtyArea(ToolLoop* loop, const Points& points, Region& dirty_area)
void ToolLoopManager::calculateDirtyArea(const Points& points, Region& dirty_area)
{
dirty_area.clear();
@@ -245,21 +245,21 @@ void ToolLoopManager::calculateDirtyArea(ToolLoop* loop, const Points& points, R
// Expand the dirty-area with the pen width
Rect r1, r2;
loop->getPointShape()->getModifiedArea(loop, minpt.x, minpt.y, r1);
loop->getPointShape()->getModifiedArea(loop, maxpt.x, maxpt.y, r2);
m_toolLoop->getPointShape()->getModifiedArea(m_toolLoop, minpt.x, minpt.y, r1);
m_toolLoop->getPointShape()->getModifiedArea(m_toolLoop, maxpt.x, maxpt.y, r2);
dirty_area.createUnion(dirty_area, Region(r1.createUnion(r2)));
}
// Apply offset mode
Point offset(loop->getOffset());
Point offset(m_toolLoop->getOffset());
dirty_area.offset(-offset);
// Apply tiled mode
TiledMode tiledMode = loop->getDocumentSettings()->getTiledMode();
TiledMode tiledMode = m_toolLoop->getDocumentSettings()->getTiledMode();
if (tiledMode != TILED_NONE) {
int w = loop->sprite()->width();
int h = loop->sprite()->height();
int w = m_toolLoop->sprite()->width();
int h = m_toolLoop->sprite()->height();
Region sprite_area(Rect(0, 0, w, h));
Region outside;
outside.createSubtraction(dirty_area, sprite_area);
@@ -312,6 +312,11 @@ void ToolLoopManager::calculateMinMax(const Points& points, Point& minpt, Point&
maxpt.x = MAX(maxpt.x, points[c].x);
maxpt.y = MAX(maxpt.y, points[c].y);
}
if (m_toolLoop->zoom().scale() < 1.0) {
maxpt.x += m_toolLoop->zoom().remove(1);
maxpt.y += m_toolLoop->zoom().remove(1);
}
}
} // namespace tools
@@ -103,13 +103,13 @@ namespace app {
void doLoopStep(bool last_step);
void snapToGrid(gfx::Point& point);
static void calculateDirtyArea(ToolLoop* loop,
const Points& points,
gfx::Region& dirty_area);
void calculateDirtyArea(
const Points& points,
gfx::Region& dirty_area);
static void calculateMinMax(const Points& points,
gfx::Point& minpt,
gfx::Point& maxpt);
void calculateMinMax(const Points& points,
gfx::Point& minpt,
gfx::Point& maxpt);
ToolLoop* m_toolLoop;
Points m_points;
@@ -55,7 +55,7 @@ namespace app {
using namespace ui;
// Returns true if the cursor of the editor needs subpixel movement.
#define IS_SUBPIXEL(editor) ((editor)->m_zoom >= 2)
#define IS_SUBPIXEL(editor) ((editor)->m_zoom.scale() >= 4.0)
// Maximum quantity of colors to save pixels overlapped by the cursor.
#define MAX_SAVED 4096
@@ -514,25 +514,22 @@ static void trace_thickcross_pixels(ui::Graphics* g, Editor* editor,
0, 0, 1, 1, 0, 0,
0, 0, 1, 1, 0, 0,
};
gfx::Point out;
gfx::Point out, outpt = editor->editorToScreen(pt);
int u, v;
int zoom = editor->zoom();
int size = editor->zoom().apply(thickness/2);
int size2 = editor->zoom().apply(thickness);
if (size2 == 0) size2 = 1;
for (v=0; v<6; v++) {
for (u=0; u<6; u++) {
if (cursor_cross[v*6+u]) {
out = editor->editorToScreen(pt);
out.x += ((u<3) ?
u-((thickness>>1)<<zoom)-3:
u-((thickness>>1)<<zoom)-3+(thickness<<zoom));
if (!cursor_cross[v*6+u])
continue;
out.y += ((v<3)?
v-((thickness>>1)<<zoom)-3:
v-((thickness>>1)<<zoom)-3+(thickness<<zoom));
out = outpt;
out.x += ((u<3) ? u-size-3: u-size-3+size2);
out.y += ((v<3) ? v-size-3: v-size-3+size2);
pixelDelegate(g, out, color);
}
pixelDelegate(g, out, color);
}
}
}
Oops, something went wrong.

0 comments on commit 4fc28d5

Please sign in to comment.