mirror of https://github.com/aseprite/aseprite.git
				
				
				
			Add pixel ratio support to the Editor & Render
This commit is contained in:
		
							parent
							
								
									73bda9bd19
								
							
						
					
					
						commit
						37209a0f5b
					
				|  | @ -1,5 +1,5 @@ | |||
| // Aseprite
 | ||||
| // Copyright (C) 2001-2015  David Capello
 | ||||
| // Copyright (C) 2001-2016  David Capello
 | ||||
| //
 | ||||
| // This program is free software; you can redistribute it and/or modify
 | ||||
| // it under the terms of the GNU General Public License version 2 as
 | ||||
|  | @ -51,7 +51,7 @@ public: | |||
|     , m_doc(editor->document()) | ||||
|     , m_sprite(editor->sprite()) | ||||
|     , m_pal(m_sprite->palette(editor->frame())) | ||||
|     , m_zoom(editor->zoom()) | ||||
|     , m_proj(editor->projection()) | ||||
|     , 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())) { | ||||
|  | @ -174,11 +174,12 @@ protected: | |||
|   virtual void onPaint(PaintEvent& ev) override { | ||||
|     Graphics* g = ev.graphics(); | ||||
|     AppRender& render = m_editor->renderEngine(); | ||||
|     render.setProjection(render::Projection()); | ||||
|     render.disableOnionskin(); | ||||
|     render.setBgType(render::BgType::TRANSPARENT); | ||||
| 
 | ||||
|     // Render sprite and leave the result in 'm_render' variable
 | ||||
|     if (m_render == NULL) { | ||||
|     if (m_render == nullptr) { | ||||
|       ImageBufferPtr buf = Editor::getRenderImageBuffer(); | ||||
|       m_render.reset(Image::create(IMAGE_RGB, | ||||
|           m_sprite->width(), m_sprite->height(), buf)); | ||||
|  | @ -188,19 +189,20 @@ protected: | |||
|     } | ||||
| 
 | ||||
|     int x, y, w, h, u, v; | ||||
|     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()); | ||||
|     x = m_pos.x + m_proj.applyX(m_proj.removeX(m_delta.x)); | ||||
|     y = m_pos.y + m_proj.applyY(m_proj.removeY(m_delta.y)); | ||||
|     w = m_proj.applyX(m_sprite->width()); | ||||
|     h = m_proj.applyY(m_sprite->height()); | ||||
| 
 | ||||
|     if (int(m_tiled) & int(TiledMode::X_AXIS)) x = SGN(x) * (ABS(x)%w); | ||||
|     if (int(m_tiled) & int(TiledMode::Y_AXIS)) y = SGN(y) * (ABS(y)%h); | ||||
| 
 | ||||
|     render.setProjection(m_proj); | ||||
|     if (m_index_bg_color == -1) { | ||||
|       render.setupBackground(m_doc, m_doublebuf->pixelFormat()); | ||||
|       render.renderBackground(m_doublebuf, | ||||
|         gfx::Clip(0, 0, -m_pos.x, -m_pos.y, | ||||
|           m_doublebuf->width(), m_doublebuf->height()), m_zoom); | ||||
|           m_doublebuf->width(), m_doublebuf->height())); | ||||
|     } | ||||
|     else { | ||||
|       doc::clear_image(m_doublebuf, m_pal->getEntry(m_index_bg_color)); | ||||
|  | @ -209,23 +211,23 @@ protected: | |||
|     switch (m_tiled) { | ||||
|       case TiledMode::NONE: | ||||
|         render.renderImage(m_doublebuf, m_render, m_pal, x, y, | ||||
|                            m_zoom, 255, BlendMode::NORMAL); | ||||
|                            255, BlendMode::NORMAL); | ||||
|         break; | ||||
|       case TiledMode::X_AXIS: | ||||
|         for (u=x-w; u<ui::display_w()+w; u+=w) | ||||
|           render.renderImage(m_doublebuf, m_render, m_pal, u, y, | ||||
|                              m_zoom, 255, BlendMode::NORMAL); | ||||
|                              255, BlendMode::NORMAL); | ||||
|         break; | ||||
|       case TiledMode::Y_AXIS: | ||||
|         for (v=y-h; v<ui::display_h()+h; v+=h) | ||||
|           render.renderImage(m_doublebuf, m_render, m_pal, x, v, | ||||
|                              m_zoom, 255, BlendMode::NORMAL); | ||||
|                              255, BlendMode::NORMAL); | ||||
|         break; | ||||
|       case TiledMode::BOTH: | ||||
|         for (v=y-h; v<ui::display_h()+h; v+=h) | ||||
|           for (u=x-w; u<ui::display_w()+w; u+=w) | ||||
|             render.renderImage(m_doublebuf, m_render, m_pal, u, v, | ||||
|                                m_zoom, 255, BlendMode::NORMAL); | ||||
|                                255, BlendMode::NORMAL); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|  | @ -243,7 +245,7 @@ private: | |||
|   gfx::Point m_pos; | ||||
|   gfx::Point m_oldMousePos; | ||||
|   gfx::Point m_delta; | ||||
|   render::Zoom m_zoom; | ||||
|   render::Projection m_proj; | ||||
|   int m_index_bg_color; | ||||
|   base::UniquePtr<Image> m_render; | ||||
|   base::UniquePtr<Image> m_doublebuf; | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // Aseprite
 | ||||
| // Copyright (C) 2001-2015  David Capello
 | ||||
| // Copyright (C) 2001-2016  David Capello
 | ||||
| //
 | ||||
| // This program is free software; you can redistribute it and/or modify
 | ||||
| // it under the terms of the GNU General Public License version 2 as
 | ||||
|  | @ -258,9 +258,9 @@ void FilterManagerImpl::flush() | |||
|           m_x+m_offset_x, | ||||
|           m_y+m_offset_y+m_row-1)), | ||||
|       gfx::Size( | ||||
|         editor->zoom().apply(m_w), | ||||
|         (editor->zoom().scale() >= 1 ? editor->zoom().apply(1): | ||||
|                                        editor->zoom().remove(1)))); | ||||
|         editor->projection().applyX(m_w), | ||||
|         (editor->projection().scaleY() >= 1 ? editor->projection().applyY(1): | ||||
|                                               editor->projection().removeY(1)))); | ||||
| 
 | ||||
|     gfx::Region reg1(rect); | ||||
|     gfx::Region reg2; | ||||
|  |  | |||
|  | @ -408,19 +408,22 @@ void BrushPreview::traceSelectionCrossPixels( | |||
|     0, 0, 1, 1, 0, 0, | ||||
|   }; | ||||
|   gfx::Point out, outpt = m_editor->editorToScreen(pt); | ||||
|   int u, v; | ||||
|   int size = m_editor->zoom().apply(thickness/2); | ||||
|   int size2 = m_editor->zoom().apply(thickness); | ||||
|   if (size2 == 0) size2 = 1; | ||||
|   const render::Projection& proj = m_editor->projection(); | ||||
|   gfx::Size size(proj.applyX(thickness/2), | ||||
|                  proj.applyY(thickness/2)); | ||||
|   gfx::Size size2(proj.applyX(thickness), | ||||
|                   proj.applyY(thickness)); | ||||
|   if (size2.w == 0) size2.w = 1; | ||||
|   if (size2.h == 0) size2.h = 1; | ||||
| 
 | ||||
|   for (v=0; v<6; v++) { | ||||
|     for (u=0; u<6; u++) { | ||||
|   for (int v=0; v<6; v++) { | ||||
|     for (int u=0; u<6; u++) { | ||||
|       if (!cross[v*6+u]) | ||||
|         continue; | ||||
| 
 | ||||
|       out = outpt; | ||||
|       out.x += ((u<3) ? u-size-3: u-size-3+size2); | ||||
|       out.y += ((v<3) ? v-size-3: v-size-3+size2); | ||||
|       out.x += ((u<3) ? u-size.w-3: u-size.w-3+size2.w); | ||||
|       out.y += ((v<3) ? v-size.h-3: v-size.h-3+size2.h); | ||||
| 
 | ||||
|       (this->*pixelDelegate)(g, out, color); | ||||
|     } | ||||
|  |  | |||
|  | @ -66,38 +66,38 @@ using namespace render; | |||
| 
 | ||||
| class EditorPreRenderImpl : public EditorPreRender { | ||||
| public: | ||||
|   EditorPreRenderImpl(Editor* editor, Image* image, const Point& offset, Zoom zoom) | ||||
|   EditorPreRenderImpl(Editor* editor, Image* image, | ||||
|                       const Point& offset, | ||||
|                       const Projection& proj) | ||||
|     : m_editor(editor) | ||||
|     , m_image(image) | ||||
|     , m_offset(offset) | ||||
|     , m_zoom(zoom) | ||||
|   { | ||||
|     , m_proj(proj) { | ||||
|   } | ||||
| 
 | ||||
|   Editor* getEditor() override | ||||
|   { | ||||
|   Editor* getEditor() override { | ||||
|     return m_editor; | ||||
|   } | ||||
| 
 | ||||
|   Image* getImage() override | ||||
|   { | ||||
|   Image* getImage() override { | ||||
|     return m_image; | ||||
|   } | ||||
| 
 | ||||
|   void fillRect(const gfx::Rect& rect, uint32_t rgbaColor, int opacity) override | ||||
|   { | ||||
|     blend_rect(m_image, | ||||
|       m_offset.x + m_zoom.apply(rect.x), | ||||
|       m_offset.y + m_zoom.apply(rect.y), | ||||
|       m_offset.x + m_zoom.apply(rect.x+rect.w) - 1, | ||||
|       m_offset.y + m_zoom.apply(rect.y+rect.h) - 1, rgbaColor, opacity); | ||||
|     blend_rect( | ||||
|       m_image, | ||||
|       m_offset.x + m_proj.applyX(rect.x), | ||||
|       m_offset.y + m_proj.applyY(rect.y), | ||||
|       m_offset.x + m_proj.applyX(rect.x+rect.w) - 1, | ||||
|       m_offset.y + m_proj.applyY(rect.y+rect.h) - 1, rgbaColor, opacity); | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   Editor* m_editor; | ||||
|   Image* m_image; | ||||
|   Point m_offset; | ||||
|   Zoom m_zoom; | ||||
|   Projection m_proj; | ||||
| }; | ||||
| 
 | ||||
| class EditorPostRenderImpl : public EditorPostRender { | ||||
|  | @ -154,7 +154,6 @@ Editor::Editor(Document* document, EditorFlags flags) | |||
|   , m_sprite(m_document->sprite()) | ||||
|   , m_layer(m_sprite->folder()->getFirstLayer()) | ||||
|   , m_frame(frame_t(0)) | ||||
|   , m_zoom(1, 1) | ||||
|   , m_docPref(Preferences::instance().document(document)) | ||||
|   , m_brushPreview(this) | ||||
|   , m_lastDrawingPosition(-1, -1) | ||||
|  | @ -169,6 +168,8 @@ Editor::Editor(Document* document, EditorFlags flags) | |||
|   , m_secondaryButton(false) | ||||
|   , m_aniSpeed(1.0) | ||||
| { | ||||
|   m_proj.setPixelRatio(m_sprite->pixelRatio()); | ||||
| 
 | ||||
|   // Add the first state into the history.
 | ||||
|   m_statesHistory.push(m_state); | ||||
| 
 | ||||
|  | @ -365,15 +366,15 @@ Site Editor::getSite() const | |||
| 
 | ||||
| void Editor::setZoom(const render::Zoom& zoom) | ||||
| { | ||||
|   if (m_zoom != zoom) { | ||||
|     m_zoom = zoom; | ||||
|   if (m_proj.zoom() != zoom) { | ||||
|     m_proj.setZoom(zoom); | ||||
|     notifyZoomChanged(); | ||||
|   } | ||||
|   else { | ||||
|     // Just copy the zoom as the internal "Zoom::m_internalScale"
 | ||||
|     // value might be different and we want to keep this value updated
 | ||||
|     // for better zooming experience in StateWithWheelBehavior.
 | ||||
|     m_zoom = zoom; | ||||
|     m_proj.setZoom(zoom); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
|  | @ -384,8 +385,8 @@ void Editor::setDefaultScroll() | |||
| 
 | ||||
|   setEditorScroll( | ||||
|     gfx::Point( | ||||
|       m_padding.x - vp.w/2 + m_zoom.apply(m_sprite->width())/2, | ||||
|       m_padding.y - vp.h/2 + m_zoom.apply(m_sprite->height())/2)); | ||||
|       m_padding.x - vp.w/2 + m_proj.applyX(m_sprite->width())/2, | ||||
|       m_padding.y - vp.h/2 + m_proj.applyY(m_sprite->height())/2)); | ||||
| } | ||||
| 
 | ||||
| // Sets the scroll position of the editor
 | ||||
|  | @ -410,7 +411,7 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& sprite | |||
| { | ||||
|   // Clip from sprite and apply zoom
 | ||||
|   gfx::Rect rc = m_sprite->bounds().createIntersection(spriteRectToDraw); | ||||
|   rc = m_zoom.apply(rc); | ||||
|   rc = m_proj.apply(rc); | ||||
| 
 | ||||
|   int dest_x = dx + m_padding.x + rc.x; | ||||
|   int dest_y = dy + m_padding.y + rc.y; | ||||
|  | @ -447,26 +448,33 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& sprite | |||
|     // tool managers that need to validate this region (copy pixels from
 | ||||
|     // the original cel) before it can be used by the RenderEngine.
 | ||||
|     { | ||||
|       gfx::Rect expose = m_zoom.remove(rc); | ||||
|       gfx::Rect expose = m_proj.remove(rc); | ||||
| 
 | ||||
|       // If the zoom level is less than 100%, we add extra pixels to
 | ||||
|       // the exposed area. Those pixels could be shown in the
 | ||||
|       // rendering process depending on each cel position.
 | ||||
|       // E.g. when we are drawing in a cel with position < (0,0)
 | ||||
|       if (m_zoom.scale() < 1.0) { | ||||
|         expose.enlarge(int(1./m_zoom.scale())); | ||||
|       } | ||||
|       if (m_proj.scaleX() < 1.0) | ||||
|         expose.enlargeXW(int(1./m_proj.scaleX())); | ||||
|       // If the zoom level is more than %100 we add an extra pixel to
 | ||||
|       // expose just in case the zoom requires to display it.  Note:
 | ||||
|       // this is really necessary to avoid showing invalid destination
 | ||||
|       // areas in ToolLoopImpl.
 | ||||
|       else if (m_zoom.scale() > 1.0) { | ||||
|         expose.enlarge(1); | ||||
|       } | ||||
|       else if (m_proj.scaleX() > 1.0) | ||||
|         expose.enlargeXW(1); | ||||
| 
 | ||||
|       if (m_proj.scaleY() < 1.0) | ||||
|         expose.enlargeYH(int(1./m_proj.scaleY())); | ||||
|       else if (m_proj.scaleY() > 1.0) | ||||
|         expose.enlargeYH(1); | ||||
| 
 | ||||
|       m_document->notifyExposeSpritePixels(m_sprite, gfx::Region(expose)); | ||||
|     } | ||||
| 
 | ||||
|     // Create a temporary RGB bitmap to draw all to it
 | ||||
|     rendered.reset(Image::create(IMAGE_RGB, rc.w, rc.h, m_renderBuffer)); | ||||
| 
 | ||||
|     m_renderEngine.setProjection(m_proj); | ||||
|     m_renderEngine.setupBackground(m_document, rendered->pixelFormat()); | ||||
|     m_renderEngine.disableOnionskin(); | ||||
| 
 | ||||
|  | @ -505,8 +513,8 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& sprite | |||
|         m_layer, m_frame); | ||||
|     } | ||||
| 
 | ||||
|     m_renderEngine.renderSprite(rendered, m_sprite, m_frame, | ||||
|       gfx::Clip(0, 0, rc), m_zoom); | ||||
|     m_renderEngine.renderSprite( | ||||
|       rendered, m_sprite, m_frame, gfx::Clip(0, 0, rc)); | ||||
| 
 | ||||
|     m_renderEngine.removeExtraImage(); | ||||
|   } | ||||
|  | @ -518,7 +526,7 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& sprite | |||
|     // Pre-render decorator.
 | ||||
|     if ((m_flags & kShowDecorators) && m_decorator) { | ||||
|       EditorPreRenderImpl preRender(this, rendered, | ||||
|         Point(-rc.x, -rc.y), m_zoom); | ||||
|                                     Point(-rc.x, -rc.y), m_proj); | ||||
|       m_decorator->preRenderDecorator(&preRender); | ||||
|     } | ||||
| 
 | ||||
|  | @ -549,15 +557,15 @@ void Editor::drawSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& _rc) | |||
|   gfx::Rect rc = _rc; | ||||
|   // For odd zoom scales minor than 100% we have to add an extra window
 | ||||
|   // just to make sure the whole rectangle is drawn.
 | ||||
|   if (m_zoom.scale() < 1.0) | ||||
|     rc.inflate(int(1./m_zoom.scale()), int(1./m_zoom.scale())); | ||||
|   if (m_proj.scaleX() < 1.0) rc.w += int(1./m_proj.scaleX()); | ||||
|   if (m_proj.scaleY() < 1.0) rc.h += int(1./m_proj.scaleY()); | ||||
| 
 | ||||
|   gfx::Rect client = clientBounds(); | ||||
|   gfx::Rect spriteRect( | ||||
|     client.x + m_padding.x, | ||||
|     client.y + m_padding.y, | ||||
|     m_zoom.apply(m_sprite->width()), | ||||
|     m_zoom.apply(m_sprite->height())); | ||||
|     m_proj.applyX(m_sprite->width()), | ||||
|     m_proj.applyY(m_sprite->height())); | ||||
|   gfx::Rect enclosingRect = spriteRect; | ||||
| 
 | ||||
|   // Draw the main sprite at the center.
 | ||||
|  | @ -611,11 +619,11 @@ void Editor::drawSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& _rc) | |||
|       IntersectClip clip(g, cliprc); | ||||
| 
 | ||||
|       // Draw the pixel grid
 | ||||
|       if ((m_zoom.scale() > 2.0) && m_docPref.show.pixelGrid()) { | ||||
|       if ((m_proj.zoom().scale() > 2.0) && m_docPref.show.pixelGrid()) { | ||||
|         int alpha = m_docPref.pixelGrid.opacity(); | ||||
| 
 | ||||
|         if (m_docPref.pixelGrid.autoOpacity()) { | ||||
|           alpha = int(alpha * (m_zoom.scale()-2.) / (16.-2.)); | ||||
|           alpha = int(alpha * (m_proj.zoom().scale()-2.) / (16.-2.)); | ||||
|           alpha = MID(0, alpha, 255); | ||||
|         } | ||||
| 
 | ||||
|  | @ -626,12 +634,13 @@ void Editor::drawSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& _rc) | |||
|       // Draw the grid
 | ||||
|       if (m_docPref.show.grid()) { | ||||
|         gfx::Rect gridrc = m_docPref.grid.bounds(); | ||||
|         if (m_zoom.apply(gridrc.w) > 2 && | ||||
|           m_zoom.apply(gridrc.h) > 2) { | ||||
|         if (m_proj.applyX(gridrc.w) > 2 && | ||||
|             m_proj.applyY(gridrc.h) > 2) { | ||||
|           int alpha = m_docPref.grid.opacity(); | ||||
| 
 | ||||
|           if (m_docPref.grid.autoOpacity()) { | ||||
|             double len = (m_zoom.apply(gridrc.w) + m_zoom.apply(gridrc.h)) / 2.; | ||||
|             double len = (m_proj.applyX(gridrc.w) + | ||||
|                           m_proj.applyY(gridrc.h)) / 2.; | ||||
|             alpha = int(alpha * len / 32.); | ||||
|             alpha = MID(0, alpha, 255); | ||||
|           } | ||||
|  | @ -657,7 +666,7 @@ void Editor::drawSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& _rc) | |||
|         if (x > 0) { | ||||
|           gfx::Color color = color_utils::color_for_ui(m_docPref.grid.color()); | ||||
|           g->drawVLine(color, | ||||
|                        spriteRect.x + m_zoom.apply(x), | ||||
|                        spriteRect.x + m_proj.applyX(x), | ||||
|                        enclosingRect.y, | ||||
|                        enclosingRect.h); | ||||
|         } | ||||
|  | @ -669,7 +678,7 @@ void Editor::drawSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& _rc) | |||
|           gfx::Color color = color_utils::color_for_ui(m_docPref.grid.color()); | ||||
|           g->drawHLine(color, | ||||
|                        enclosingRect.x, | ||||
|                        spriteRect.y + m_zoom.apply(y), | ||||
|                        spriteRect.y + m_proj.applyY(y), | ||||
|                        enclosingRect.w); | ||||
|         } | ||||
|         break; | ||||
|  | @ -747,13 +756,16 @@ void Editor::drawMask(Graphics* g) | |||
| 
 | ||||
|   for (const auto& seg : *m_document->getMaskBoundaries()) { | ||||
|     CheckedDrawMode checked(g, m_antsOffset); | ||||
|     gfx::Rect bounds = m_zoom.apply(seg.bounds()); | ||||
|     gfx::Rect bounds = m_proj.apply(seg.bounds()); | ||||
| 
 | ||||
|     if (m_zoom.scale() >= 1.0) { | ||||
|       if (!seg.open()) { | ||||
|         if (seg.vertical()) --bounds.x; | ||||
|         else --bounds.y; | ||||
|       } | ||||
|     if (m_proj.scaleX() >= 1.0) { | ||||
|       if (!seg.open() && seg.vertical()) | ||||
|         --bounds.x; | ||||
|     } | ||||
| 
 | ||||
|     if (m_proj.scaleY() >= 1.0) { | ||||
|       if (!seg.open() && !seg.vertical()) | ||||
|         --bounds.y; | ||||
|     } | ||||
| 
 | ||||
|     // The color doesn't matter, we are using CheckedDrawMode
 | ||||
|  | @ -945,8 +957,8 @@ gfx::Point Editor::screenToEditor(const gfx::Point& pt) | |||
|   Point scroll = view->viewScroll(); | ||||
| 
 | ||||
|   return gfx::Point( | ||||
|     m_zoom.remove(pt.x - vp.x + scroll.x - m_padding.x), | ||||
|     m_zoom.remove(pt.y - vp.y + scroll.y - m_padding.y)); | ||||
|     m_proj.removeX(pt.x - vp.x + scroll.x - m_padding.x), | ||||
|     m_proj.removeY(pt.y - vp.y + scroll.y - m_padding.y)); | ||||
| } | ||||
| 
 | ||||
| Point Editor::editorToScreen(const gfx::Point& pt) | ||||
|  | @ -956,8 +968,8 @@ Point Editor::editorToScreen(const gfx::Point& pt) | |||
|   Point scroll = view->viewScroll(); | ||||
| 
 | ||||
|   return Point( | ||||
|     (vp.x - scroll.x + m_padding.x + m_zoom.apply(pt.x)), | ||||
|     (vp.y - scroll.y + m_padding.y + m_zoom.apply(pt.y))); | ||||
|     (vp.x - scroll.x + m_padding.x + m_proj.applyX(pt.x)), | ||||
|     (vp.y - scroll.y + m_padding.y + m_proj.applyY(pt.y))); | ||||
| } | ||||
| 
 | ||||
| Rect Editor::screenToEditor(const Rect& rc) | ||||
|  | @ -1013,8 +1025,8 @@ void Editor::centerInSpritePoint(const gfx::Point& spritePos) | |||
|   Rect vp = view->viewportBounds(); | ||||
| 
 | ||||
|   gfx::Point scroll( | ||||
|     m_padding.x - (vp.w/2) + m_zoom.apply(1)/2 + m_zoom.apply(spritePos.x), | ||||
|     m_padding.y - (vp.h/2) + m_zoom.apply(1)/2 + m_zoom.apply(spritePos.y)); | ||||
|     m_padding.x - (vp.w/2) + m_proj.applyX(1)/2 + m_proj.applyX(spritePos.x), | ||||
|     m_padding.y - (vp.h/2) + m_proj.applyY(1)/2 + m_proj.applyY(spritePos.y)); | ||||
| 
 | ||||
|   updateEditor(); | ||||
|   setEditorScroll(scroll); | ||||
|  | @ -1316,9 +1328,9 @@ void Editor::onSizeHint(SizeHintEvent& ev) | |||
|   gfx::Size sz(0, 0); | ||||
| 
 | ||||
|   if (m_sprite) { | ||||
|     gfx::Point padding = calcExtraPadding(m_zoom); | ||||
|     sz.w = m_zoom.apply(m_sprite->width()) + padding.x*2; | ||||
|     sz.h = m_zoom.apply(m_sprite->height()) + padding.y*2; | ||||
|     gfx::Point padding = calcExtraPadding(m_proj); | ||||
|     sz.w = m_proj.applyX(m_sprite->width()) + padding.x*2; | ||||
|     sz.h = m_proj.applyY(m_sprite->height()) + padding.y*2; | ||||
|   } | ||||
|   else { | ||||
|     sz.w = 4; | ||||
|  | @ -1330,7 +1342,7 @@ void Editor::onSizeHint(SizeHintEvent& ev) | |||
| void Editor::onResize(ui::ResizeEvent& ev) | ||||
| { | ||||
|   Widget::onResize(ev); | ||||
|   m_padding = calcExtraPadding(m_zoom); | ||||
|   m_padding = calcExtraPadding(m_proj); | ||||
| } | ||||
| 
 | ||||
| void Editor::onPaint(ui::PaintEvent& ev) | ||||
|  | @ -1440,11 +1452,14 @@ bool Editor::isInsideSelection() | |||
| } | ||||
| 
 | ||||
| void Editor::setZoomAndCenterInMouse(const Zoom& zoom, | ||||
|   const gfx::Point& mousePos, ZoomBehavior zoomBehavior) | ||||
|                                      const gfx::Point& mousePos, | ||||
|                                      ZoomBehavior zoomBehavior) | ||||
| { | ||||
|   HideBrushPreview hide(m_brushPreview); | ||||
|   View* view = View::getView(this); | ||||
|   Rect vp = view->viewportBounds(); | ||||
|   Projection proj = m_proj; | ||||
|   proj.setZoom(zoom); | ||||
| 
 | ||||
|   gfx::Point screenPos; | ||||
|   gfx::Point spritePos; | ||||
|  | @ -1461,27 +1476,36 @@ void Editor::setZoomAndCenterInMouse(const Zoom& zoom, | |||
|   } | ||||
|   spritePos = screenToEditor(screenPos); | ||||
| 
 | ||||
|   if (zoomBehavior == ZoomBehavior::MOUSE && | ||||
|       m_zoom.scale() > 1.0) { | ||||
|   if (zoomBehavior == ZoomBehavior::MOUSE) { | ||||
|     gfx::Point screenPos2 = editorToScreen(spritePos); | ||||
|     subpixelPos.x = (0.5 + screenPos.x - screenPos2.x) / m_zoom.scale(); | ||||
|     subpixelPos.y = (0.5 + screenPos.y - screenPos2.y) / m_zoom.scale(); | ||||
| 
 | ||||
|     if (zoom.scale() > m_zoom.scale()) { | ||||
|       double t = 1.0 / zoom.scale(); | ||||
|       if (subpixelPos.x >= 0.5-t && subpixelPos.x <= 0.5+t) subpixelPos.x = 0.5; | ||||
|       if (subpixelPos.y >= 0.5-t && subpixelPos.y <= 0.5+t) subpixelPos.y = 0.5; | ||||
|     if (m_proj.scaleX() > 1.0) { | ||||
|       subpixelPos.x = (0.5 + screenPos.x - screenPos2.x) / m_proj.scaleX(); | ||||
|       if (proj.scaleX() > m_proj.scaleX()) { | ||||
|         double t = 1.0 / proj.scaleX(); | ||||
|         if (subpixelPos.x >= 0.5-t && subpixelPos.x <= 0.5+t) | ||||
|           subpixelPos.x = 0.5; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     if (m_proj.scaleY() > 1.0) { | ||||
|       subpixelPos.y = (0.5 + screenPos.y - screenPos2.y) / m_proj.scaleY(); | ||||
|       if (proj.scaleY() > m_proj.scaleY()) { | ||||
|         double t = 1.0 / proj.scaleY(); | ||||
|         if (subpixelPos.y >= 0.5-t && subpixelPos.y <= 0.5+t) | ||||
|           subpixelPos.y = 0.5; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   gfx::Point padding = calcExtraPadding(zoom); | ||||
|   gfx::Point padding = calcExtraPadding(proj); | ||||
|   gfx::Point scrollPos( | ||||
|     padding.x - (screenPos.x-vp.x) + zoom.apply(spritePos.x+zoom.remove(1)/2) + int(zoom.apply(subpixelPos.x)), | ||||
|     padding.y - (screenPos.y-vp.y) + zoom.apply(spritePos.y+zoom.remove(1)/2) + int(zoom.apply(subpixelPos.y))); | ||||
|     padding.x - (screenPos.x-vp.x) + proj.applyX(spritePos.x+proj.removeX(1)/2) + int(proj.applyX(subpixelPos.x)), | ||||
|     padding.y - (screenPos.y-vp.y) + proj.applyY(spritePos.y+proj.removeY(1)/2) + int(proj.applyY(subpixelPos.y))); | ||||
| 
 | ||||
|   setZoom(zoom); | ||||
| 
 | ||||
|   if ((m_zoom != zoom) || (screenPos != view->viewScroll())) { | ||||
|   if ((m_proj.zoom() != zoom) || (screenPos != view->viewScroll())) { | ||||
|     updateEditor(); | ||||
|     setEditorScroll(scrollPos); | ||||
|   } | ||||
|  | @ -1675,14 +1699,14 @@ ImageBufferPtr Editor::getRenderImageBuffer() | |||
| } | ||||
| 
 | ||||
| // static
 | ||||
| gfx::Point Editor::calcExtraPadding(const Zoom& zoom) | ||||
| gfx::Point Editor::calcExtraPadding(const Projection& proj) | ||||
| { | ||||
|   View* view = View::getView(this); | ||||
|   if (view) { | ||||
|     Rect vp = view->viewportBounds(); | ||||
|     return gfx::Point( | ||||
|       std::max<int>(vp.w/2, vp.w - zoom.apply(m_sprite->width())), | ||||
|       std::max<int>(vp.h/2, vp.h - zoom.apply(m_sprite->height()))); | ||||
|       std::max<int>(vp.w/2, vp.w - proj.applyX(m_sprite->width())), | ||||
|       std::max<int>(vp.h/2, vp.h - proj.applyY(m_sprite->height()))); | ||||
|   } | ||||
|   else | ||||
|     return gfx::Point(0, 0); | ||||
|  |  | |||
|  | @ -131,7 +131,8 @@ namespace app { | |||
|     void setLayer(const Layer* layer); | ||||
|     void setFrame(frame_t frame); | ||||
| 
 | ||||
|     const render::Zoom& zoom() const { return m_zoom; } | ||||
|     const render::Projection& projection() const { return m_proj; } | ||||
|     const render::Zoom& zoom() const { return m_proj.zoom(); } | ||||
|     const gfx::Point& padding() const { return m_padding; } | ||||
| 
 | ||||
|     void setZoom(const render::Zoom& zoom); | ||||
|  | @ -260,7 +261,7 @@ namespace app { | |||
|     // routine.
 | ||||
|     void drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& rc, int dx, int dy); | ||||
| 
 | ||||
|     gfx::Point calcExtraPadding(const render::Zoom& zoom); | ||||
|     gfx::Point calcExtraPadding(const render::Projection& proj); | ||||
| 
 | ||||
|     void invalidateIfActive(); | ||||
| 
 | ||||
|  | @ -278,7 +279,7 @@ namespace app { | |||
|     Sprite* m_sprite;             // Active sprite in the editor
 | ||||
|     Layer* m_layer;               // Active layer in the editor
 | ||||
|     frame_t m_frame;              // Active frame in the editor
 | ||||
|     render::Zoom m_zoom;          // Zoom in the editor
 | ||||
|     render::Projection m_proj;    // Zoom/pixel ratio in the editor
 | ||||
|     DocumentPreferences& m_docPref; | ||||
| 
 | ||||
|     // Brush preview
 | ||||
|  |  | |||
|  | @ -266,11 +266,11 @@ void SelectBoxState::preRenderDecorator(EditorPreRender* render) | |||
| void SelectBoxState::postRenderDecorator(EditorPostRender* render) | ||||
| { | ||||
|   Editor* editor = render->getEditor(); | ||||
|   render::Zoom zoom = editor->zoom(); | ||||
|   render::Projection proj = editor->projection(); | ||||
|   gfx::Rect sp = editor->sprite()->bounds(); | ||||
|   gfx::Rect vp = View::getView(editor)->viewportBounds(); | ||||
|   vp.w += zoom.apply(1); | ||||
|   vp.h += zoom.apply(1); | ||||
|   vp.w += proj.applyX(1); | ||||
|   vp.h += proj.applyY(1); | ||||
|   vp = editor->screenToEditor(vp); | ||||
| 
 | ||||
|   // Paint a grid generated by the box
 | ||||
|  |  | |||
|  | @ -312,8 +312,7 @@ public: | |||
|           m_floodfillSrcImage, | ||||
|           m_sprite, | ||||
|           m_frame, | ||||
|           gfx::Clip(m_sprite->bounds()), | ||||
|           render::Zoom(1, 1)); | ||||
|           gfx::Clip(m_sprite->bounds())); | ||||
|       } | ||||
|       else { | ||||
|         Cel* cel = m_layer->cel(m_frame); | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // Aseprite
 | ||||
| // Copyright (C) 2001-2015  David Capello
 | ||||
| // Copyright (C) 2001-2016  David Capello
 | ||||
| //
 | ||||
| // This program is free software; you can redistribute it and/or modify
 | ||||
| // it under the terms of the GNU General Public License version 2 as
 | ||||
|  | @ -179,8 +179,8 @@ gfx::Rect TransformHandles::getPivotHandleBounds(Editor* editor, | |||
|   gfx::Size partSize = theme->parts.pivotHandle()->size(); | ||||
|   gfx::Point screenPivotPos = editor->editorToScreen(transform.pivot()); | ||||
| 
 | ||||
|   screenPivotPos.x += editor->zoom().apply(1) / 2; | ||||
|   screenPivotPos.y += editor->zoom().apply(1) / 2; | ||||
|   screenPivotPos.x += editor->projection().applyX(1) / 2; | ||||
|   screenPivotPos.y += editor->projection().applyY(1) / 2; | ||||
| 
 | ||||
|   return gfx::Rect( | ||||
|     screenPivotPos.x-partSize.w/2, | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // Aseprite Document Library
 | ||||
| // Copyright (c) 2001-2015 David Capello
 | ||||
| // Copyright (c) 2001-2016 David Capello
 | ||||
| //
 | ||||
| // This file is released under the terms of the MIT license.
 | ||||
| // Read LICENSE.txt for more information.
 | ||||
|  | @ -28,6 +28,7 @@ | |||
| #include "doc/palette.h" | ||||
| #include "doc/palette_picks.h" | ||||
| #include "doc/pixel_format.h" | ||||
| #include "doc/pixel_ratio.h" | ||||
| #include "doc/primitives.h" | ||||
| #include "doc/primitives_fast.h" | ||||
| #include "doc/remap.h" | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // Aseprite Gfx Library
 | ||||
| // Copyright (C) 2001-2013, 2015 David Capello
 | ||||
| // Copyright (C) 2001-2016 David Capello
 | ||||
| //
 | ||||
| // This file is released under the terms of the MIT license.
 | ||||
| // Read LICENSE.txt for more information.
 | ||||
|  | @ -175,6 +175,18 @@ public: | |||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   RectT& enlargeXW(const T& unit) { | ||||
|     x -= unit; | ||||
|     w += unit<<1; | ||||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   RectT& enlargeYH(const T& unit) { | ||||
|     y -= unit; | ||||
|     h += unit<<1; | ||||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   RectT& shrink(const T& unit) { | ||||
|     x += unit; | ||||
|     y += unit; | ||||
|  | @ -259,6 +271,22 @@ public: | |||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   RectT& operator*=(const SizeT<T>& size) const { | ||||
|     x *= size.w; | ||||
|     y *= size.h; | ||||
|     w *= size.w; | ||||
|     h *= size.h; | ||||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   RectT& operator/=(const SizeT<T>& size) const { | ||||
|     x /= size.w; | ||||
|     y /= size.h; | ||||
|     w /= size.w; | ||||
|     h /= size.h; | ||||
|     return *this; | ||||
|   } | ||||
| 
 | ||||
|   const RectT& operator|=(const RectT& rc) { | ||||
|     return *this = createUnion(rc); | ||||
|   } | ||||
|  | @ -283,6 +311,16 @@ public: | |||
|     return createIntersection(other); | ||||
|   } | ||||
| 
 | ||||
|   RectT operator*(const SizeT<T>& size) const { | ||||
|     return RectT(x*size.w, y*size.h, | ||||
|                  w*size.w, h*size.h); | ||||
|   } | ||||
| 
 | ||||
|   RectT operator/(const SizeT<T>& size) const { | ||||
|     return RectT(x/size.w, y/size.h, | ||||
|                  w/size.w, h/size.h); | ||||
|   } | ||||
| 
 | ||||
|   bool operator==(const RectT& rc) const { | ||||
|     return | ||||
|       x == rc.x && w == rc.w && | ||||
|  |  | |||
|  | @ -0,0 +1,73 @@ | |||
| // Aseprite Render Library
 | ||||
| // Copyright (c) 2016 David Capello
 | ||||
| //
 | ||||
| // This file is released under the terms of the MIT license.
 | ||||
| // Read LICENSE.txt for more information.
 | ||||
| 
 | ||||
| #ifndef RENDER_PROJECTION_H_INCLUDED | ||||
| #define RENDER_PROJECTION_H_INCLUDED | ||||
| #pragma once | ||||
| 
 | ||||
| #include "doc/pixel_ratio.h" | ||||
| #include "render/zoom.h" | ||||
| 
 | ||||
| namespace render { | ||||
| 
 | ||||
|   class Projection { | ||||
|   public: | ||||
|     Projection() | ||||
|       : m_pixelRatio(1, 1), | ||||
|         m_zoom(1, 1) { | ||||
|     } | ||||
| 
 | ||||
|     Projection(const doc::PixelRatio& pixelRatio, | ||||
|                const Zoom& zoom) | ||||
|       : m_pixelRatio(pixelRatio), | ||||
|         m_zoom(zoom) { | ||||
|     } | ||||
| 
 | ||||
|     const doc::PixelRatio& pixelRatio() const { return m_pixelRatio; } | ||||
|     const Zoom& zoom() const { return m_zoom; } | ||||
| 
 | ||||
|     void setPixelRatio(const doc::PixelRatio& pixelRatio) { m_pixelRatio = pixelRatio; } | ||||
|     void setZoom(const Zoom& zoom) { m_zoom = zoom; } | ||||
| 
 | ||||
|     double scaleX() const { return m_zoom.scale() * m_pixelRatio.w; } | ||||
|     double scaleY() const { return m_zoom.scale() * m_pixelRatio.h; } | ||||
| 
 | ||||
|     template<typename T> | ||||
|     T applyX(T x) const { return m_zoom.apply(x * m_pixelRatio.w); } | ||||
| 
 | ||||
|     template<typename T> | ||||
|     T applyY(T y) const { return m_zoom.apply(y * m_pixelRatio.h); } | ||||
| 
 | ||||
|     template<typename T> | ||||
|     T removeX(T x) const { return m_zoom.remove(x / m_pixelRatio.w); } | ||||
| 
 | ||||
|     template<typename T> | ||||
|     T removeY(T y) const { return m_zoom.remove(y / m_pixelRatio.h); } | ||||
| 
 | ||||
|     gfx::Rect apply(const gfx::Rect& r) const { | ||||
|       int u = applyX(r.x); | ||||
|       int v = applyY(r.y); | ||||
|       return gfx::Rect(u, v, | ||||
|                        applyX(r.x+r.w) - u, | ||||
|                        applyY(r.y+r.h) - v); | ||||
|     } | ||||
| 
 | ||||
|     gfx::Rect remove(const gfx::Rect& r) const { | ||||
|       int u = removeX(r.x); | ||||
|       int v = removeY(r.y); | ||||
|       return gfx::Rect(u, v, | ||||
|                        removeX(r.x+r.w) - u, | ||||
|                        removeY(r.y+r.h) - v); | ||||
|     } | ||||
| 
 | ||||
|   private: | ||||
|     doc::PixelRatio m_pixelRatio; | ||||
|     Zoom m_zoom; | ||||
|   }; | ||||
| 
 | ||||
| } // namespace render
 | ||||
| 
 | ||||
| #endif | ||||
|  | @ -29,9 +29,9 @@ class BlenderHelper { | |||
|   BlendFunc m_blend_func; | ||||
|   color_t m_mask_color; | ||||
| public: | ||||
|   BlenderHelper(const Image* src, const Palette* pal, BlendMode blend_mode) | ||||
|   BlenderHelper(const Image* src, const Palette* pal, BlendMode blendMode) | ||||
|   { | ||||
|     m_blend_func = SrcTraits::get_blender(blend_mode); | ||||
|     m_blend_func = SrcTraits::get_blender(blendMode); | ||||
|     m_mask_color = src->maskColor(); | ||||
|   } | ||||
|   inline typename DstTraits::pixel_t | ||||
|  | @ -51,9 +51,9 @@ class BlenderHelper<RgbTraits, GrayscaleTraits> { | |||
|   BlendFunc m_blend_func; | ||||
|   color_t m_mask_color; | ||||
| public: | ||||
|   BlenderHelper(const Image* src, const Palette* pal, BlendMode blend_mode) | ||||
|   BlenderHelper(const Image* src, const Palette* pal, BlendMode blendMode) | ||||
|   { | ||||
|     m_blend_func = RgbTraits::get_blender(blend_mode); | ||||
|     m_blend_func = RgbTraits::get_blender(blendMode); | ||||
|     m_mask_color = src->maskColor(); | ||||
|   } | ||||
|   inline RgbTraits::pixel_t | ||||
|  | @ -73,14 +73,14 @@ public: | |||
| template<> | ||||
| class BlenderHelper<RgbTraits, IndexedTraits> { | ||||
|   const Palette* m_pal; | ||||
|   BlendMode m_blend_mode; | ||||
|   BlendMode m_blendMode; | ||||
|   BlendFunc m_blend_func; | ||||
|   color_t m_mask_color; | ||||
| public: | ||||
|   BlenderHelper(const Image* src, const Palette* pal, BlendMode blend_mode) | ||||
|   BlenderHelper(const Image* src, const Palette* pal, BlendMode blendMode) | ||||
|   { | ||||
|     m_blend_mode = blend_mode; | ||||
|     m_blend_func = RgbTraits::get_blender(blend_mode); | ||||
|     m_blendMode = blendMode; | ||||
|     m_blend_func = RgbTraits::get_blender(blendMode); | ||||
|     m_mask_color = src->maskColor(); | ||||
|     m_pal = pal; | ||||
|   } | ||||
|  | @ -89,7 +89,7 @@ public: | |||
|              const IndexedTraits::pixel_t& src, | ||||
|                          int opacity) | ||||
|   { | ||||
|     if (m_blend_mode == BlendMode::SRC) { | ||||
|     if (m_blendMode == BlendMode::SRC) { | ||||
|       return m_pal->getEntry(src); | ||||
|     } | ||||
|     else { | ||||
|  | @ -104,12 +104,12 @@ public: | |||
| 
 | ||||
| template<> | ||||
| class BlenderHelper<IndexedTraits, IndexedTraits> { | ||||
|   BlendMode m_blend_mode; | ||||
|   BlendMode m_blendMode; | ||||
|   color_t m_mask_color; | ||||
| public: | ||||
|   BlenderHelper(const Image* src, const Palette* pal, BlendMode blend_mode) | ||||
|   BlenderHelper(const Image* src, const Palette* pal, BlendMode blendMode) | ||||
|   { | ||||
|     m_blend_mode = blend_mode; | ||||
|     m_blendMode = blendMode; | ||||
|     m_mask_color = src->maskColor(); | ||||
|   } | ||||
|   inline IndexedTraits::pixel_t | ||||
|  | @ -117,7 +117,7 @@ public: | |||
|              const IndexedTraits::pixel_t& src, | ||||
|              int opacity) | ||||
|   { | ||||
|     if (m_blend_mode == BlendMode::SRC) { | ||||
|     if (m_blendMode == BlendMode::SRC) { | ||||
|       return src; | ||||
|     } | ||||
|     else { | ||||
|  | @ -130,39 +130,39 @@ public: | |||
| }; | ||||
| 
 | ||||
| template<class DstTraits, class SrcTraits> | ||||
| static void compose_scaled_image_scale_up( | ||||
| static void compose_scaled_image_zoom_in( | ||||
|   Image* dst, const Image* src, const Palette* pal, | ||||
|   gfx::Clip area, | ||||
|   int opacity, BlendMode blend_mode, Zoom zoom) | ||||
|   int opacity, BlendMode blendMode, | ||||
|   const Projection& proj) | ||||
| { | ||||
|   ASSERT(dst); | ||||
|   ASSERT(src); | ||||
|   ASSERT(DstTraits::pixel_format == dst->pixelFormat()); | ||||
|   ASSERT(SrcTraits::pixel_format == src->pixelFormat()); | ||||
| 
 | ||||
|   BlenderHelper<DstTraits, SrcTraits> blender(src, pal, blend_mode); | ||||
|   int px_x, px_y; | ||||
| 
 | ||||
|   if (!area.clip(dst->width(), dst->height(), | ||||
|       zoom.apply(src->width()), | ||||
|       zoom.apply(src->height()))) | ||||
|                  proj.applyX(src->width()), | ||||
|                  proj.applyY(src->height()))) | ||||
|     return; | ||||
| 
 | ||||
|   int px_w = zoom.apply(1); | ||||
|   int px_h = zoom.apply(1); | ||||
|   BlenderHelper<DstTraits, SrcTraits> blender(src, pal, blendMode); | ||||
|   int px_x, px_y; | ||||
|   int px_w = proj.applyX(1); | ||||
|   int px_h = proj.applyY(1); | ||||
|   int first_px_w = px_w - (area.src.x % px_w); | ||||
|   int first_px_h = px_h - (area.src.y % px_h); | ||||
|   gfx::Rect srcBounds = zoom.remove(area.srcBounds()); | ||||
| 
 | ||||
|   gfx::Rect srcBounds = proj.remove(area.srcBounds()); | ||||
|   if ((area.src.x+area.size.w) % px_w > 0) ++srcBounds.w; | ||||
|   if ((area.src.y+area.size.h) % px_h > 0) ++srcBounds.h; | ||||
|   if (srcBounds.isEmpty()) | ||||
|     return; | ||||
| 
 | ||||
|   gfx::Rect dstBounds = area.dstBounds(); | ||||
|   int bottom = area.dst.y+area.size.h-1; | ||||
|   int line_h; | ||||
| 
 | ||||
|   if ((area.src.x+area.size.w) % px_w > 0) ++srcBounds.w; | ||||
|   if ((area.src.y+area.size.h) % px_h > 0) ++srcBounds.h; | ||||
| 
 | ||||
|   if (srcBounds.isEmpty()) | ||||
|     return; | ||||
| 
 | ||||
|   // the scanline variable is used to blend src/dst pixels one time for each pixel
 | ||||
|   typedef std::vector<typename DstTraits::pixel_t> Scanline; | ||||
|   Scanline scanline(srcBounds.w); | ||||
|  | @ -262,32 +262,34 @@ done_with_blit:; | |||
| } | ||||
| 
 | ||||
| template<class DstTraits, class SrcTraits> | ||||
| static void compose_scaled_image_scale_down( | ||||
| static void compose_scaled_image_zoom_out( | ||||
|   Image* dst, const Image* src, const Palette* pal, | ||||
|   gfx::Clip area, | ||||
|   int opacity, BlendMode blend_mode, Zoom zoom) | ||||
|   gfx::Clip area, int opacity, BlendMode blendMode, | ||||
|   const Projection& proj) | ||||
| { | ||||
|   ASSERT(dst); | ||||
|   ASSERT(src); | ||||
|   ASSERT(DstTraits::pixel_format == dst->pixelFormat()); | ||||
|   ASSERT(SrcTraits::pixel_format == src->pixelFormat()); | ||||
| 
 | ||||
|   BlenderHelper<DstTraits, SrcTraits> blender(src, pal, blend_mode); | ||||
|   int unbox_w = zoom.remove(1); | ||||
|   int unbox_h = zoom.remove(1); | ||||
| 
 | ||||
|   if (!area.clip(dst->width(), dst->height(), | ||||
|       zoom.apply(src->width()), | ||||
|       zoom.apply(src->height()))) | ||||
|                  proj.applyX(src->width()), | ||||
|                  proj.applyY(src->height()))) | ||||
|     return; | ||||
| 
 | ||||
|   gfx::Rect srcBounds = zoom.remove(area.srcBounds()); | ||||
|   gfx::Rect dstBounds = area.dstBounds(); | ||||
|   int bottom = area.dst.y+area.size.h-1; | ||||
|   BlenderHelper<DstTraits, SrcTraits> blender(src, pal, blendMode); | ||||
|   int unbox_w = proj.removeX(1); | ||||
|   int unbox_h = proj.removeY(1); | ||||
|   if (unbox_w < 1 || unbox_h < 1) | ||||
|     return; | ||||
| 
 | ||||
|   gfx::Rect srcBounds = proj.remove(area.srcBounds()); | ||||
|   if (srcBounds.isEmpty()) | ||||
|     return; | ||||
| 
 | ||||
|   gfx::Rect dstBounds = area.dstBounds(); | ||||
|   int bottom = area.dst.y+area.size.h-1; | ||||
| 
 | ||||
|   // Lock all necessary bits
 | ||||
|   const LockImageBits<SrcTraits> srcBits(src, srcBounds); | ||||
|   LockImageBits<DstTraits> dstBits(dst, dstBounds); | ||||
|  | @ -327,12 +329,14 @@ template<class DstTraits, class SrcTraits> | |||
| static void compose_scaled_image( | ||||
|   Image* dst, const Image* src, const Palette* pal, | ||||
|   const gfx::Clip& area, | ||||
|   int opacity, BlendMode blend_mode, Zoom zoom) | ||||
|   int opacity, | ||||
|   BlendMode blendMode, | ||||
|   const Projection& proj) | ||||
| { | ||||
|   if (zoom.scale() >= 1.0) | ||||
|     compose_scaled_image_scale_up<DstTraits, SrcTraits>(dst, src, pal, area, opacity, blend_mode, zoom); | ||||
|   if (proj.zoom().scale() >= 1.0) | ||||
|     compose_scaled_image_zoom_in<DstTraits, SrcTraits>(dst, src, pal, area, opacity, blendMode, proj); | ||||
|   else | ||||
|     compose_scaled_image_scale_down<DstTraits, SrcTraits>(dst, src, pal, area, opacity, blend_mode, zoom); | ||||
|     compose_scaled_image_zoom_out<DstTraits, SrcTraits>(dst, src, pal, area, opacity, blendMode, proj); | ||||
| } | ||||
| 
 | ||||
| Render::Render() | ||||
|  | @ -353,6 +357,11 @@ Render::Render() | |||
| { | ||||
| } | ||||
| 
 | ||||
| void Render::setProjection(const Projection& projection) | ||||
| { | ||||
|   m_proj = projection; | ||||
| } | ||||
| 
 | ||||
| void Render::setBgType(BgType type) | ||||
| { | ||||
|   m_bgType = type; | ||||
|  | @ -427,17 +436,9 @@ void Render::renderSprite( | |||
|   const Sprite* sprite, | ||||
|   frame_t frame) | ||||
| { | ||||
|   renderSprite(dstImage, sprite, frame, | ||||
|     gfx::Clip(sprite->bounds()), Zoom(1, 1)); | ||||
| } | ||||
| 
 | ||||
| void Render::renderSprite( | ||||
|   Image* dstImage, | ||||
|   const Sprite* sprite, | ||||
|   frame_t frame, | ||||
|   const gfx::Clip& area) | ||||
| { | ||||
|   renderSprite(dstImage, sprite, frame, area, Zoom(1, 1)); | ||||
|   renderSprite( | ||||
|     dstImage, sprite, frame, | ||||
|     gfx::Clip(sprite->bounds())); | ||||
| } | ||||
| 
 | ||||
| void Render::renderLayer( | ||||
|  | @ -454,7 +455,7 @@ void Render::renderLayer( | |||
|   const Layer* layer, | ||||
|   frame_t frame, | ||||
|   const gfx::Clip& area, | ||||
|   BlendMode blend_mode) | ||||
|   BlendMode blendMode) | ||||
| { | ||||
|   m_sprite = layer->sprite(); | ||||
| 
 | ||||
|  | @ -467,17 +468,15 @@ void Render::renderLayer( | |||
| 
 | ||||
|   m_globalOpacity = 255; | ||||
|   renderLayer( | ||||
|     layer, dstImage, area, | ||||
|     frame, Zoom(1, 1), scaled_func, | ||||
|     true, true, blend_mode); | ||||
|     layer, dstImage, area, frame, | ||||
|     scaled_func, true, true, blendMode); | ||||
| } | ||||
| 
 | ||||
| void Render::renderSprite( | ||||
|   Image* dstImage, | ||||
|   const Sprite* sprite, | ||||
|   frame_t frame, | ||||
|   const gfx::Clip& area, | ||||
|   Zoom zoom) | ||||
|   const gfx::Clip& area) | ||||
| { | ||||
|   m_sprite = sprite; | ||||
| 
 | ||||
|  | @ -511,7 +510,7 @@ void Render::renderSprite( | |||
|         fill_rect(dstImage, area.dstBounds(), bg_color); | ||||
|       } | ||||
|       else { | ||||
|         renderBackground(dstImage, area, zoom); | ||||
|         renderBackground(dstImage, area); | ||||
|         if (bgLayer && bgLayer->isVisible() && rgba_geta(bg_color) > 0) { | ||||
|           blend_rect(dstImage, area.dst.x, area.dst.y, | ||||
|                      area.dst.x+area.size.w-1, | ||||
|  | @ -530,27 +529,27 @@ void Render::renderSprite( | |||
|   m_globalOpacity = 255; | ||||
|   renderLayer( | ||||
|     m_sprite->folder(), dstImage, | ||||
|     area, frame, zoom, scaled_func, | ||||
|     area, frame, scaled_func, | ||||
|     true, | ||||
|     false, | ||||
|     BlendMode::UNSPECIFIED); | ||||
| 
 | ||||
|   // Draw onion skin behind the sprite.
 | ||||
|   if (m_onionskin.position() == OnionskinPosition::BEHIND) | ||||
|     renderOnionskin(dstImage, area, frame, zoom, scaled_func); | ||||
|     renderOnionskin(dstImage, area, frame, scaled_func); | ||||
| 
 | ||||
|   // Draw the transparent layers.
 | ||||
|   m_globalOpacity = 255; | ||||
|   renderLayer( | ||||
|     m_sprite->folder(), dstImage, | ||||
|     area, frame, zoom, scaled_func, | ||||
|     area, frame, scaled_func, | ||||
|     false, | ||||
|     true, | ||||
|     BlendMode::UNSPECIFIED); | ||||
| 
 | ||||
|   // Draw onion skin in front of the sprite.
 | ||||
|   if (m_onionskin.position() == OnionskinPosition::INFRONT) | ||||
|     renderOnionskin(dstImage, area, frame, zoom, scaled_func); | ||||
|     renderOnionskin(dstImage, area, frame, scaled_func); | ||||
| 
 | ||||
|   // Overlay preview image
 | ||||
|   if (m_previewImage && | ||||
|  | @ -564,15 +563,14 @@ void Render::renderSprite( | |||
|       area, | ||||
|       scaled_func, | ||||
|       255, | ||||
|       m_previewBlendMode, | ||||
|       zoom); | ||||
|       m_previewBlendMode); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void Render::renderOnionskin( | ||||
|   Image* dstImage, | ||||
|   const gfx::Clip& area, | ||||
|   frame_t frame, Zoom zoom, | ||||
|   frame_t frame, | ||||
|   RenderScaledImage scaled_func) | ||||
| { | ||||
|   // Onion-skin feature: Draw previous/next frames with different
 | ||||
|  | @ -612,43 +610,42 @@ void Render::renderOnionskin( | |||
| 
 | ||||
|       m_globalOpacity = MID(0, m_globalOpacity, 255); | ||||
|       if (m_globalOpacity > 0) { | ||||
|         BlendMode blend_mode = BlendMode::UNSPECIFIED; | ||||
|         BlendMode blendMode = BlendMode::UNSPECIFIED; | ||||
|         if (m_onionskin.type() == OnionskinType::MERGE) | ||||
|           blend_mode = BlendMode::NORMAL; | ||||
|           blendMode = BlendMode::NORMAL; | ||||
|         else if (m_onionskin.type() == OnionskinType::RED_BLUE_TINT) | ||||
|           blend_mode = (frameOut < frame ? BlendMode::RED_TINT: BlendMode::BLUE_TINT); | ||||
|           blendMode = (frameOut < frame ? BlendMode::RED_TINT: BlendMode::BLUE_TINT); | ||||
| 
 | ||||
|         renderLayer( | ||||
|           onionLayer, dstImage, | ||||
|           area, frameIn, zoom, scaled_func, | ||||
|           area, frameIn, scaled_func, | ||||
|           // Render background only for "in-front" onion skinning and
 | ||||
|           // when opacity is < 255
 | ||||
|           (m_globalOpacity < 255 && | ||||
|            m_onionskin.position() == OnionskinPosition::INFRONT), | ||||
|           true, | ||||
|           blend_mode); | ||||
|           blendMode); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void Render::renderBackground(Image* image, | ||||
|   const gfx::Clip& area, | ||||
|   Zoom zoom) | ||||
| void Render::renderBackground( | ||||
|   Image* image, | ||||
|   const gfx::Clip& area) | ||||
| { | ||||
|   int x, y, u, v; | ||||
|   int tile_w = m_bgCheckedSize.w; | ||||
|   int tile_h = m_bgCheckedSize.h; | ||||
| 
 | ||||
|   if (m_bgZoom) { | ||||
|     tile_w = zoom.apply(tile_w); | ||||
|     tile_h = zoom.apply(tile_h); | ||||
|     tile_w = m_proj.zoom().apply(tile_w); | ||||
|     tile_h = m_proj.zoom().apply(tile_h); | ||||
|   } | ||||
| 
 | ||||
|   // Tile size
 | ||||
|   if (tile_w < zoom.apply(1)) tile_w = zoom.apply(1); | ||||
|   if (tile_h < zoom.apply(1)) tile_h = zoom.apply(1); | ||||
| 
 | ||||
|   if (tile_w < m_proj.applyX(1)) tile_w = m_proj.applyX(1); | ||||
|   if (tile_h < m_proj.applyY(1)) tile_h = m_proj.applyY(1); | ||||
|   if (tile_w < 1) tile_w = 1; | ||||
|   if (tile_h < 1) tile_h = 1; | ||||
| 
 | ||||
|  | @ -678,10 +675,11 @@ void Render::renderBackground(Image* image, | |||
|   } | ||||
| } | ||||
| 
 | ||||
| void Render::renderImage(Image* dst_image, const Image* src_image, | ||||
|                          const Palette* pal, | ||||
|                          int x, int y, | ||||
|                          Zoom zoom, int opacity, BlendMode blend_mode) | ||||
| void Render::renderImage( | ||||
|   Image* dst_image, const Image* src_image, | ||||
|   const Palette* pal, | ||||
|   int x, int y, | ||||
|   int opacity, BlendMode blendMode) | ||||
| { | ||||
|   RenderScaledImage scaled_func = getRenderScaledImageFunc( | ||||
|     dst_image->pixelFormat(), | ||||
|  | @ -689,22 +687,24 @@ void Render::renderImage(Image* dst_image, const Image* src_image, | |||
|   if (!scaled_func) | ||||
|     return; | ||||
| 
 | ||||
|   scaled_func(dst_image, src_image, pal, | ||||
|   scaled_func( | ||||
|     dst_image, src_image, pal, | ||||
|     gfx::Clip(x, y, 0, 0, | ||||
|       zoom.apply(src_image->width()), | ||||
|       zoom.apply(src_image->height())), | ||||
|     opacity, blend_mode, zoom); | ||||
|               m_proj.applyX(src_image->width()), | ||||
|               m_proj.applyY(src_image->height())), | ||||
|     opacity, blendMode, | ||||
|     m_proj); | ||||
| } | ||||
| 
 | ||||
| void Render::renderLayer( | ||||
|   const Layer* layer, | ||||
|   Image *image, | ||||
|   const gfx::Clip& area, | ||||
|   frame_t frame, Zoom zoom, | ||||
|   frame_t frame, | ||||
|   RenderScaledImage scaled_func, | ||||
|   bool render_background, | ||||
|   bool render_transparent, | ||||
|   BlendMode blend_mode) | ||||
|   BlendMode blendMode) | ||||
| { | ||||
|   // we can't read from this layer
 | ||||
|   if (!layer->isVisible()) | ||||
|  | @ -724,11 +724,9 @@ void Render::renderLayer( | |||
|       m_extraCel->y(), | ||||
|       m_extraImage->width(), | ||||
|       m_extraImage->height()); | ||||
|     extraArea = zoom.apply(extraArea); | ||||
|     if (zoom.scale() < 1.0) { | ||||
|       extraArea.w--; | ||||
|       extraArea.h--; | ||||
|     } | ||||
|     extraArea = m_proj.apply(extraArea); | ||||
|     if (m_proj.scaleX() < 1.0) extraArea.w--; | ||||
|     if (m_proj.scaleY() < 1.0) extraArea.h--; | ||||
|     if (extraArea.w < 1) extraArea.w = 1; | ||||
|     if (extraArea.h < 1) extraArea.h = 1; | ||||
|   } | ||||
|  | @ -761,9 +759,9 @@ void Render::renderLayer( | |||
|         if (src_image) { | ||||
|           const LayerImage* imgLayer = static_cast<const LayerImage*>(layer); | ||||
|           BlendMode layerBlendMode = | ||||
|             (blend_mode == BlendMode::UNSPECIFIED ? | ||||
|             (blendMode == BlendMode::UNSPECIFIED ? | ||||
|              imgLayer->blendMode(): | ||||
|              blend_mode); | ||||
|              blendMode); | ||||
| 
 | ||||
|           ASSERT(cel->opacity() >= 0); | ||||
|           ASSERT(cel->opacity() <= 255); | ||||
|  | @ -789,7 +787,7 @@ void Render::renderLayer( | |||
|                 image, src_image, pal, | ||||
|                 cel, gfx::Clip(area.dst.x+rc.x-area.src.x, | ||||
|                                area.dst.y+rc.y-area.src.y, rc), scaled_func, | ||||
|                 opacity, layerBlendMode, zoom); | ||||
|                 opacity, layerBlendMode); | ||||
|             } | ||||
|           } | ||||
|           // Draw the whole cel
 | ||||
|  | @ -797,7 +795,7 @@ void Render::renderLayer( | |||
|             renderCel( | ||||
|               image, src_image, pal, | ||||
|               cel, area, scaled_func, | ||||
|               opacity, layerBlendMode, zoom); | ||||
|               opacity, layerBlendMode); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | @ -809,11 +807,13 @@ void Render::renderLayer( | |||
|       LayerConstIterator end = static_cast<const LayerFolder*>(layer)->getLayerEnd(); | ||||
| 
 | ||||
|       for (; it != end; ++it) { | ||||
|         renderLayer(*it, image, | ||||
|           area, frame, zoom, scaled_func, | ||||
|         renderLayer( | ||||
|           *it, image, | ||||
|           area, frame, | ||||
|           scaled_func, | ||||
|           render_background, | ||||
|           render_transparent, | ||||
|           blend_mode); | ||||
|           blendMode); | ||||
|       } | ||||
|       break; | ||||
|     } | ||||
|  | @ -832,7 +832,7 @@ void Render::renderLayer( | |||
|                   extraArea), | ||||
|         scaled_func, | ||||
|         m_extraCel->opacity(), | ||||
|         m_extraBlendMode, zoom); | ||||
|         m_extraBlendMode); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -844,7 +844,7 @@ void Render::renderCel( | |||
|   const Cel* cel, | ||||
|   const gfx::Clip& area, | ||||
|   RenderScaledImage scaled_func, | ||||
|   int opacity, BlendMode blend_mode, Zoom zoom) | ||||
|   int opacity, BlendMode blendMode) | ||||
| { | ||||
|   renderImage(dst_image, | ||||
|               cel_image, | ||||
|  | @ -854,8 +854,7 @@ void Render::renderCel( | |||
|               area, | ||||
|               scaled_func, | ||||
|               opacity, | ||||
|               blend_mode, | ||||
|               zoom); | ||||
|               blendMode); | ||||
| } | ||||
| 
 | ||||
| void Render::renderImage( | ||||
|  | @ -866,30 +865,32 @@ void Render::renderImage( | |||
|   const int y, | ||||
|   const gfx::Clip& area, | ||||
|   RenderScaledImage scaled_func, | ||||
|   int opacity, BlendMode blend_mode, Zoom zoom) | ||||
|   int opacity, BlendMode blendMode) | ||||
| { | ||||
|   int cel_x = zoom.apply(x); | ||||
|   int cel_y = zoom.apply(y); | ||||
|   int cel_x = m_proj.applyX(x); | ||||
|   int cel_y = m_proj.applyY(y); | ||||
| 
 | ||||
|   gfx::Rect src_bounds = | ||||
|   gfx::Rect srcBounds = | ||||
|     area.srcBounds().createIntersection( | ||||
|       gfx::Rect( | ||||
|         cel_x, | ||||
|         cel_y, | ||||
|         zoom.apply(cel_image->width()), | ||||
|         zoom.apply(cel_image->height()))); | ||||
|   if (src_bounds.isEmpty()) | ||||
|         m_proj.applyX(cel_image->width()), | ||||
|         m_proj.applyY(cel_image->height()))); | ||||
|   if (srcBounds.isEmpty()) | ||||
|     return; | ||||
| 
 | ||||
|   (*scaled_func)(dst_image, cel_image, pal, | ||||
|   (*scaled_func)( | ||||
|     dst_image, cel_image, pal, | ||||
|     gfx::Clip( | ||||
|       area.dst.x + src_bounds.x - area.src.x, | ||||
|       area.dst.y + src_bounds.y - area.src.y, | ||||
|       src_bounds.x - cel_x, | ||||
|       src_bounds.y - cel_y, | ||||
|       src_bounds.w, | ||||
|       src_bounds.h), | ||||
|     opacity, blend_mode, zoom); | ||||
|       area.dst.x + srcBounds.x - area.src.x, | ||||
|       area.dst.y + srcBounds.y - area.src.y, | ||||
|       srcBounds.x - cel_x, | ||||
|       srcBounds.y - cel_y, | ||||
|       srcBounds.w, | ||||
|       srcBounds.h), | ||||
|     opacity, blendMode, | ||||
|     m_proj); | ||||
| } | ||||
| 
 | ||||
| // static
 | ||||
|  | @ -931,13 +932,13 @@ Render::RenderScaledImage Render::getRenderScaledImageFunc( | |||
| void composite_image(Image* dst, const Image* src, | ||||
|                      const Palette* pal, | ||||
|                      int x, int y, | ||||
|                      int opacity, BlendMode blend_mode) | ||||
|                      int opacity, BlendMode blendMode) | ||||
| { | ||||
|   // As the background is not rendered in renderImage(), we don't need
 | ||||
|   // to configure the Render instance's BgType.
 | ||||
|   Render().renderImage( | ||||
|     dst, src, pal, x, y, Zoom(1, 1), | ||||
|     opacity, blend_mode); | ||||
|     dst, src, pal, x, y, | ||||
|     opacity, blendMode); | ||||
| } | ||||
| 
 | ||||
| } // namespace render
 | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ | |||
| #include "gfx/size.h" | ||||
| #include "render/extra_type.h" | ||||
| #include "render/onionskin_position.h" | ||||
| #include "render/zoom.h" | ||||
| #include "render/projection.h" | ||||
| 
 | ||||
| namespace gfx { | ||||
|   class Clip; | ||||
|  | @ -93,6 +93,9 @@ namespace render { | |||
|   public: | ||||
|     Render(); | ||||
| 
 | ||||
|     // Viewport configuration
 | ||||
|     void setProjection(const Projection& projection); | ||||
| 
 | ||||
|     // Background configuration
 | ||||
|     void setBgType(BgType type); | ||||
|     void setBgZoom(bool state); | ||||
|  | @ -123,12 +126,6 @@ namespace render { | |||
|       const Sprite* sprite, | ||||
|       frame_t frame); | ||||
| 
 | ||||
|     void renderSprite( | ||||
|       Image* dstImage, | ||||
|       const Sprite* sprite, | ||||
|       frame_t frame, | ||||
|       const gfx::Clip& area); | ||||
| 
 | ||||
|     void renderLayer( | ||||
|       Image* dstImage, | ||||
|       const Layer* layer, | ||||
|  | @ -139,7 +136,7 @@ namespace render { | |||
|       const Layer* layer, | ||||
|       frame_t frame, | ||||
|       const gfx::Clip& area, | ||||
|       BlendMode blend_mode = BlendMode::UNSPECIFIED); | ||||
|       BlendMode blendMode = BlendMode::UNSPECIFIED); | ||||
| 
 | ||||
|     // Main function used to render the sprite. Draws the given sprite
 | ||||
|     // frame in a new image and return it. Note: zoomedRect must have
 | ||||
|  | @ -148,39 +145,41 @@ namespace render { | |||
|       Image* dstImage, | ||||
|       const Sprite* sprite, | ||||
|       frame_t frame, | ||||
|       const gfx::Clip& area, | ||||
|       Zoom zoom); | ||||
|       const gfx::Clip& area); | ||||
| 
 | ||||
|     // Extra functions
 | ||||
|     void renderBackground(Image* image, | ||||
|       const gfx::Clip& area, | ||||
|       Zoom zoom); | ||||
|     void renderBackground( | ||||
|       Image* image, | ||||
|       const gfx::Clip& area); | ||||
| 
 | ||||
|     void renderImage(Image* dst_image, const Image* src_image, | ||||
|       const Palette* pal, int x, int y, Zoom zoom, | ||||
|       int opacity, BlendMode blend_mode); | ||||
|     void renderImage( | ||||
|       Image* dst_image, const Image* src_image, | ||||
|       const Palette* pal, int x, int y, | ||||
|       int opacity, BlendMode blendMode); | ||||
| 
 | ||||
|   private: | ||||
|     typedef void (*RenderScaledImage)( | ||||
|       Image* dst, const Image* src, const Palette* pal, | ||||
|       const gfx::Clip& area, | ||||
|       int opacity, BlendMode blend_mode, Zoom zoom); | ||||
|       int opacity, | ||||
|       BlendMode blendMode, | ||||
|       const Projection& proj); | ||||
| 
 | ||||
|     void renderOnionskin( | ||||
|       Image* image, | ||||
|       const gfx::Clip& area, | ||||
|       frame_t frame, Zoom zoom, | ||||
|       frame_t frame, | ||||
|       RenderScaledImage scaled_func); | ||||
| 
 | ||||
|     void renderLayer( | ||||
|       const Layer* layer, | ||||
|       Image* image, | ||||
|       const gfx::Clip& area, | ||||
|       frame_t frame, Zoom zoom, | ||||
|       frame_t frame, | ||||
|       RenderScaledImage renderScaledImage, | ||||
|       bool render_background, | ||||
|       bool render_transparent, | ||||
|       BlendMode blend_mode); | ||||
|       BlendMode blendMode); | ||||
| 
 | ||||
|     void renderCel( | ||||
|       Image* dst_image, | ||||
|  | @ -189,7 +188,7 @@ namespace render { | |||
|       const Cel* cel, | ||||
|       const gfx::Clip& area, | ||||
|       RenderScaledImage scaled_func, | ||||
|       int opacity, BlendMode blend_mode, Zoom zoom); | ||||
|       int opacity, BlendMode blendMode); | ||||
| 
 | ||||
|     void renderImage( | ||||
|       Image* dst_image, | ||||
|  | @ -199,7 +198,7 @@ namespace render { | |||
|       const int y, | ||||
|       const gfx::Clip& area, | ||||
|       RenderScaledImage scaled_func, | ||||
|       int opacity, BlendMode blend_mode, Zoom zoom); | ||||
|       int opacity, BlendMode blendMode); | ||||
| 
 | ||||
|     static RenderScaledImage getRenderScaledImageFunc( | ||||
|       PixelFormat dstFormat, | ||||
|  | @ -208,11 +207,11 @@ namespace render { | |||
|     const Sprite* m_sprite; | ||||
|     const Layer* m_currentLayer; | ||||
|     frame_t m_currentFrame; | ||||
|     Projection m_proj; | ||||
|     ExtraType m_extraType; | ||||
|     const Cel* m_extraCel; | ||||
|     const Image* m_extraImage; | ||||
|     BlendMode m_extraBlendMode; | ||||
| 
 | ||||
|     BgType m_bgType; | ||||
|     bool m_bgZoom; | ||||
|     color_t m_bgColor1; | ||||
|  | @ -229,7 +228,7 @@ namespace render { | |||
|   void composite_image(Image* dst, const Image* src, | ||||
|                        const Palette* pal, | ||||
|                        int x, int y, | ||||
|                        int opacity, BlendMode blend_mode); | ||||
|                        int opacity, BlendMode blendMode); | ||||
| 
 | ||||
| } // namespace render
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // Aseprite Document Library
 | ||||
| // Copyright (c) 2001-2014 David Capello
 | ||||
| // Copyright (c) 2001-2016 David Capello
 | ||||
| //
 | ||||
| // This file is released under the terms of the MIT license.
 | ||||
| // Read LICENSE.txt for more information.
 | ||||
|  | @ -147,7 +147,7 @@ TEST(Render, CheckedBackground) | |||
| 
 | ||||
|   render.setBgCheckedSize(gfx::Size(1, 1)); | ||||
|   render.renderSprite(dst, doc->sprite(), frame_t(0)); | ||||
|   EXPECT_4X4_PIXELS(dst,  | ||||
|   EXPECT_4X4_PIXELS(dst, | ||||
|     1, 2, 1, 2, | ||||
|     2, 1, 2, 1, | ||||
|     1, 2, 1, 2, | ||||
|  | @ -155,7 +155,7 @@ TEST(Render, CheckedBackground) | |||
| 
 | ||||
|   render.setBgCheckedSize(gfx::Size(2, 2)); | ||||
|   render.renderSprite(dst, doc->sprite(), frame_t(0)); | ||||
|   EXPECT_4X4_PIXELS(dst,  | ||||
|   EXPECT_4X4_PIXELS(dst, | ||||
|     1, 1, 2, 2, | ||||
|     1, 1, 2, 2, | ||||
|     2, 2, 1, 1, | ||||
|  | @ -163,17 +163,15 @@ TEST(Render, CheckedBackground) | |||
| 
 | ||||
|   render.setBgCheckedSize(gfx::Size(3, 3)); | ||||
|   render.renderSprite(dst, doc->sprite(), frame_t(0)); | ||||
|   EXPECT_4X4_PIXELS(dst,  | ||||
|   EXPECT_4X4_PIXELS(dst, | ||||
|     1, 1, 1, 2, | ||||
|     1, 1, 1, 2, | ||||
|     1, 1, 1, 2, | ||||
|     2, 2, 2, 1); | ||||
| 
 | ||||
|   render.setProjection(Projection(PixelRatio(1, 1), Zoom(2, 1))); | ||||
|   render.setBgCheckedSize(gfx::Size(1, 1)); | ||||
|   render.renderSprite(dst, | ||||
|     doc->sprite(), frame_t(0), | ||||
|     gfx::Clip(dst->bounds()), | ||||
|     Zoom(2, 1)); | ||||
|   render.renderSprite(dst, doc->sprite(), frame_t(0)); | ||||
|   EXPECT_4X4_PIXELS(dst, | ||||
|     1, 1, 2, 2, | ||||
|     1, 1, 2, 2, | ||||
|  | @ -204,10 +202,10 @@ TEST(Render, ZoomAndDstBounds) | |||
|   render.setBgColor2(2); | ||||
|   render.setBgCheckedSize(gfx::Size(1, 1)); | ||||
| 
 | ||||
|   render.renderSprite(dst, doc->sprite(), frame_t(0), | ||||
|     gfx::Clip(1, 1, 0, 0, 2, 2), | ||||
|     Zoom(1, 1)); | ||||
|   EXPECT_4X4_PIXELS(dst,  | ||||
|   render.renderSprite( | ||||
|     dst, doc->sprite(), frame_t(0), | ||||
|     gfx::Clip(1, 1, 0, 0, 2, 2)); | ||||
|   EXPECT_4X4_PIXELS(dst, | ||||
|     0, 0, 0, 0, | ||||
|     0, 1, 2, 0, | ||||
|     0, 2, 4, 0, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue