mirror of https://github.com/aseprite/aseprite.git
				
				
				
			Draw mask boundaries with a gfx::Path
The path is also cached so on each re-paint we can re-use it while it's still valid.
This commit is contained in:
		
							parent
							
								
									9801010a2b
								
							
						
					
					
						commit
						3d2013b33c
					
				
							
								
								
									
										2
									
								
								laf
								
								
								
								
							
							
								
								
								
								
								
								
							
						
						
									
										2
									
								
								laf
								
								
								
								
							|  | @ -1 +1 @@ | ||||||
| Subproject commit 207de6662911e9471c01681fb16912b756646f07 | Subproject commit 8032d186a751326d0fc6436d69570ad4a3c4aaf1 | ||||||
|  | @ -304,8 +304,8 @@ void Doc::generateMaskBoundaries(const Mask* mask) | ||||||
|   ASSERT(mask); |   ASSERT(mask); | ||||||
| 
 | 
 | ||||||
|   if (!mask->isEmpty()) { |   if (!mask->isEmpty()) { | ||||||
|     m_maskBoundaries.reset(new MaskBoundaries(mask->bitmap())); |     m_maskBoundaries.regen(mask->bitmap()); | ||||||
|     m_maskBoundaries->offset(mask->bounds().x, |     m_maskBoundaries.offset(mask->bounds().x, | ||||||
|                             mask->bounds().y); |                             mask->bounds().y); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| // Aseprite
 | // Aseprite
 | ||||||
| // Copyright (C) 2018-2019  Igara Studio S.A.
 | // Copyright (C) 2018-2020  Igara Studio S.A.
 | ||||||
| // Copyright (C) 2001-2018  David Capello
 | // Copyright (C) 2001-2018  David Capello
 | ||||||
| //
 | //
 | ||||||
| // This program is distributed under the terms of
 | // This program is distributed under the terms of
 | ||||||
|  | @ -20,6 +20,7 @@ | ||||||
| #include "doc/color.h" | #include "doc/color.h" | ||||||
| #include "doc/document.h" | #include "doc/document.h" | ||||||
| #include "doc/frame.h" | #include "doc/frame.h" | ||||||
|  | #include "doc/mask_boundaries.h" | ||||||
| #include "doc/pixel_format.h" | #include "doc/pixel_format.h" | ||||||
| #include "gfx/rect.h" | #include "gfx/rect.h" | ||||||
| #include "obs/observable.h" | #include "obs/observable.h" | ||||||
|  | @ -32,7 +33,6 @@ namespace doc { | ||||||
|   class Cel; |   class Cel; | ||||||
|   class Layer; |   class Layer; | ||||||
|   class Mask; |   class Mask; | ||||||
|   class MaskBoundaries; |  | ||||||
|   class Sprite; |   class Sprite; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -143,8 +143,16 @@ namespace app { | ||||||
|     void destroyMaskBoundaries(); |     void destroyMaskBoundaries(); | ||||||
|     void generateMaskBoundaries(const Mask* mask = nullptr); |     void generateMaskBoundaries(const Mask* mask = nullptr); | ||||||
| 
 | 
 | ||||||
|     const MaskBoundaries* getMaskBoundaries() const { |     const MaskBoundaries& maskBoundaries() const { | ||||||
|      return m_maskBoundaries.get(); |       return m_maskBoundaries; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     MaskBoundaries& maskBoundaries() { | ||||||
|  |       return m_maskBoundaries; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     bool hasMaskBoundaries() const { | ||||||
|  |       return !m_maskBoundaries.isEmpty(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     //////////////////////////////////////////////////////////////////////
 |     //////////////////////////////////////////////////////////////////////
 | ||||||
|  | @ -217,7 +225,7 @@ namespace app { | ||||||
|     Transaction* m_transaction; |     Transaction* m_transaction; | ||||||
| 
 | 
 | ||||||
|     // Selected mask region boundaries
 |     // Selected mask region boundaries
 | ||||||
|     std::unique_ptr<doc::MaskBoundaries> m_maskBoundaries; |     doc::MaskBoundaries m_maskBoundaries; | ||||||
| 
 | 
 | ||||||
|     // Data to save the file in the same format that it was loaded
 |     // Data to save the file in the same format that it was loaded
 | ||||||
|     FormatOptionsPtr m_format_options; |     FormatOptionsPtr m_format_options; | ||||||
|  |  | ||||||
|  | @ -371,7 +371,7 @@ void BrushPreview::generateBoundaries() | ||||||
| { | { | ||||||
|   BrushRef brush = getCurrentBrush(); |   BrushRef brush = getCurrentBrush(); | ||||||
| 
 | 
 | ||||||
|   if (m_brushBoundaries && |   if (!m_brushBoundaries.isEmpty() && | ||||||
|       m_brushGen == brush->gen()) |       m_brushGen == brush->gen()) | ||||||
|     return; |     return; | ||||||
| 
 | 
 | ||||||
|  | @ -398,11 +398,9 @@ void BrushPreview::generateBoundaries() | ||||||
|     mask = brush->maskBitmap(); |     mask = brush->maskBitmap(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   m_brushBoundaries.reset( |   m_brushBoundaries.regen(mask ? mask: brushImage); | ||||||
|     new MaskBoundaries(mask ? mask: brushImage)); |  | ||||||
| 
 |  | ||||||
|   if (!isOnePixel) |   if (!isOnePixel) | ||||||
|     m_brushBoundaries->offset(-brush->center().x, |     m_brushBoundaries.offset(-brush->center().x, | ||||||
|                              -brush->center().y); |                              -brush->center().y); | ||||||
| 
 | 
 | ||||||
|   if (deleteMask) |   if (deleteMask) | ||||||
|  | @ -512,7 +510,7 @@ void BrushPreview::traceBrushBoundaries(ui::Graphics* g, | ||||||
|                                         gfx::Color color, |                                         gfx::Color color, | ||||||
|                                         PixelDelegate pixelDelegate) |                                         PixelDelegate pixelDelegate) | ||||||
| { | { | ||||||
|   for (const auto& seg : *m_brushBoundaries) { |   for (const auto& seg : m_brushBoundaries) { | ||||||
|     gfx::Rect bounds = seg.bounds(); |     gfx::Rect bounds = seg.bounds(); | ||||||
|     bounds.offset(pos); |     bounds.offset(pos); | ||||||
|     bounds = m_editor->editorToScreen(bounds); |     bounds = m_editor->editorToScreen(bounds); | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| // Aseprite
 | // Aseprite
 | ||||||
| // Copyright (C) 2019  Igara Studio S.A.
 | // Copyright (C) 2019-2020  Igara Studio S.A.
 | ||||||
| // Copyright (C) 2001-2016  David Capello
 | // Copyright (C) 2001-2016  David Capello
 | ||||||
| //
 | //
 | ||||||
| // This program is distributed under the terms of
 | // This program is distributed under the terms of
 | ||||||
|  | @ -93,7 +93,7 @@ namespace app { | ||||||
|     gfx::Point m_editorPosition; // Position in the editor (model)
 |     gfx::Point m_editorPosition; // Position in the editor (model)
 | ||||||
| 
 | 
 | ||||||
|     // Information about current brush
 |     // Information about current brush
 | ||||||
|     std::shared_ptr<doc::MaskBoundaries> m_brushBoundaries; |     doc::MaskBoundaries m_brushBoundaries; | ||||||
|     int m_brushGen; |     int m_brushGen; | ||||||
|     int m_brushWidth; |     int m_brushWidth; | ||||||
|     int m_brushHeight; |     int m_brushHeight; | ||||||
|  |  | ||||||
|  | @ -894,7 +894,7 @@ void Editor::drawSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& _rc) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // Draw the mask
 |   // Draw the mask
 | ||||||
|   if (m_document->getMaskBoundaries()) |   if (m_document->hasMaskBoundaries()) | ||||||
|     drawMask(g); |     drawMask(g); | ||||||
| 
 | 
 | ||||||
|   // Post-render decorator.
 |   // Post-render decorator.
 | ||||||
|  | @ -934,34 +934,26 @@ void Editor::drawMask(Graphics* g) | ||||||
|       !m_docPref.show.selectionEdges()) |       !m_docPref.show.selectionEdges()) | ||||||
|     return; |     return; | ||||||
| 
 | 
 | ||||||
|   ASSERT(m_document->getMaskBoundaries()); |   ASSERT(m_document->hasMaskBoundaries()); | ||||||
| 
 | 
 | ||||||
|   gfx::Point pt = mainTilePosition(); |   gfx::Point pt = mainTilePosition(); | ||||||
|   pt.x = m_padding.x + m_proj.applyX(pt.x); |   pt.x = m_padding.x + m_proj.applyX(pt.x); | ||||||
|   pt.y = m_padding.y + m_proj.applyY(pt.y); |   pt.y = m_padding.y + m_proj.applyY(pt.y); | ||||||
| 
 | 
 | ||||||
|   for (const auto& seg : *m_document->getMaskBoundaries()) { |   // Create the mask boundaries path
 | ||||||
|  |   auto& segs = m_document->maskBoundaries(); | ||||||
|  |   segs.createPathIfNeeeded(); | ||||||
|  | 
 | ||||||
|   CheckedDrawMode checked(g, m_antsOffset, |   CheckedDrawMode checked(g, m_antsOffset, | ||||||
|                           gfx::rgba(0, 0, 0, 255), |                           gfx::rgba(0, 0, 0, 255), | ||||||
|                           gfx::rgba(255, 255, 255, 255)); |                           gfx::rgba(255, 255, 255, 255)); | ||||||
|     gfx::Rect bounds = m_proj.apply(seg.bounds()); |   os::Paint paint; | ||||||
| 
 |   paint.style(os::Paint::Stroke); | ||||||
|     if (m_proj.scaleX() >= 1.0) { |   paint.color(gfx::rgba(0, 0, 0)); | ||||||
|       if (!seg.open() && seg.vertical()) |   g->setMatrix(Matrix::MakeTrans(pt.x, pt.y)); | ||||||
|         --bounds.x; |   g->concat(m_proj.scaleMatrix()); | ||||||
|     } |   g->drawPath(segs.path(), paint); | ||||||
| 
 |   g->resetMatrix(); | ||||||
|     if (m_proj.scaleY() >= 1.0) { |  | ||||||
|       if (!seg.open() && !seg.vertical()) |  | ||||||
|         --bounds.y; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // The color doesn't matter, we are using CheckedDrawMode
 |  | ||||||
|     if (seg.vertical()) |  | ||||||
|       g->drawVLine(gfx::rgba(0, 0, 0), pt.x+bounds.x, pt.y+bounds.y, bounds.h); |  | ||||||
|     else |  | ||||||
|       g->drawHLine(gfx::rgba(0, 0, 0), pt.x+bounds.x, pt.y+bounds.y, bounds.w); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Editor::drawMaskSafe() | void Editor::drawMaskSafe() | ||||||
|  | @ -971,7 +963,7 @@ void Editor::drawMaskSafe() | ||||||
| 
 | 
 | ||||||
|   if (isVisible() && |   if (isVisible() && | ||||||
|       m_document && |       m_document && | ||||||
|       m_document->getMaskBoundaries()) { |       m_document->hasMaskBoundaries()) { | ||||||
|     Region region; |     Region region; | ||||||
|     getDrawableRegion(region, kCutTopWindows); |     getDrawableRegion(region, kCutTopWindows); | ||||||
|     region.offset(-bounds().origin()); |     region.offset(-bounds().origin()); | ||||||
|  | @ -2047,7 +2039,7 @@ void Editor::onPaint(ui::PaintEvent& ev) | ||||||
| #endif // ENABLE_DEVMODE
 | #endif // ENABLE_DEVMODE
 | ||||||
| 
 | 
 | ||||||
|       // Draw the mask boundaries
 |       // Draw the mask boundaries
 | ||||||
|       if (m_document->getMaskBoundaries()) { |       if (m_document->hasMaskBoundaries()) { | ||||||
|         drawMask(g); |         drawMask(g); | ||||||
|         m_antsTimer.start(); |         m_antsTimer.start(); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  | @ -105,10 +105,10 @@ bool MovingSelectionState::onMouseMove(Editor* editor, MouseMessage* msg) | ||||||
|     editor->document()->mask()->setOrigin(newMaskOrigin.x, |     editor->document()->mask()->setOrigin(newMaskOrigin.x, | ||||||
|                                           newMaskOrigin.y); |                                           newMaskOrigin.y); | ||||||
| 
 | 
 | ||||||
|     if (MaskBoundaries* boundaries = |     if (editor->document()->hasMaskBoundaries()) { | ||||||
|           const_cast<MaskBoundaries*>(editor->document()->getMaskBoundaries())) { |       MaskBoundaries& boundaries = editor->document()->maskBoundaries(); | ||||||
|       const gfx::Point boundariesDelta = newMaskOrigin - oldMaskOrigin; |       const gfx::Point boundariesDelta = newMaskOrigin - oldMaskOrigin; | ||||||
|       boundaries->offset(boundariesDelta.x, |       boundaries.offset(boundariesDelta.x, | ||||||
|                         boundariesDelta.y); |                         boundariesDelta.y); | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|  |  | ||||||
|  | @ -832,13 +832,13 @@ bool StandbyState::overSelectionEdges(Editor* editor, | ||||||
|   if (Preferences::instance().selection.moveEdges() && |   if (Preferences::instance().selection.moveEdges() && | ||||||
|       editor->isActive() && |       editor->isActive() && | ||||||
|       editor->document()->isMaskVisible() && |       editor->document()->isMaskVisible() && | ||||||
|       editor->document()->getMaskBoundaries() && |       editor->document()->hasMaskBoundaries() && | ||||||
|       // TODO improve this check, how we can know that we aren't in the MovingPixelsState
 |       // TODO improve this check, how we can know that we aren't in the MovingPixelsState
 | ||||||
|       !dynamic_cast<MovingPixelsState*>(editor->getState().get())) { |       !dynamic_cast<MovingPixelsState*>(editor->getState().get())) { | ||||||
|     gfx::Point mainOffset(editor->mainTilePosition()); |     gfx::Point mainOffset(editor->mainTilePosition()); | ||||||
| 
 | 
 | ||||||
|     // For each selection edge
 |     // For each selection edge
 | ||||||
|     for (const auto& seg : *editor->document()->getMaskBoundaries()) { |     for (const auto& seg : editor->document()->maskBoundaries()) { | ||||||
|       gfx::Rect segBounds = seg.bounds(); |       gfx::Rect segBounds = seg.bounds(); | ||||||
|       segBounds.offset(mainOffset); |       segBounds.offset(mainOffset); | ||||||
|       segBounds = editor->editorToScreen(segBounds); |       segBounds = editor->editorToScreen(segBounds); | ||||||
|  |  | ||||||
|  | @ -14,8 +14,17 @@ | ||||||
| 
 | 
 | ||||||
| namespace doc { | namespace doc { | ||||||
| 
 | 
 | ||||||
| MaskBoundaries::MaskBoundaries(const Image* bitmap) | void MaskBoundaries::reset() | ||||||
| { | { | ||||||
|  |   m_segs.clear(); | ||||||
|  |   if (!m_path.isEmpty()) | ||||||
|  |     m_path.rewind(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MaskBoundaries::regen(const Image* bitmap) | ||||||
|  | { | ||||||
|  |   reset(); | ||||||
|  | 
 | ||||||
|   int x, y, w = bitmap->width(), h = bitmap->height(); |   int x, y, w = bitmap->width(), h = bitmap->height(); | ||||||
| 
 | 
 | ||||||
|   const LockImageBits<BitmapTraits> bits(bitmap); |   const LockImageBits<BitmapTraits> bits(bitmap); | ||||||
|  | @ -334,6 +343,24 @@ void MaskBoundaries::offset(int x, int y) | ||||||
| { | { | ||||||
|   for (Segment& seg : m_segs) |   for (Segment& seg : m_segs) | ||||||
|     seg.offset(x, y); |     seg.offset(x, y); | ||||||
|  | 
 | ||||||
|  |   m_path.offset(x, y); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MaskBoundaries::createPathIfNeeeded() | ||||||
|  | { | ||||||
|  |   if (!m_path.isEmpty()) | ||||||
|  |     return; | ||||||
|  | 
 | ||||||
|  |   for (const auto& seg : m_segs) { | ||||||
|  |     gfx::Rect rc = seg.bounds(); | ||||||
|  |     m_path.moveTo(rc.x, rc.y); | ||||||
|  | 
 | ||||||
|  |     if (seg.vertical()) | ||||||
|  |       m_path.lineTo(rc.x, rc.y2()); | ||||||
|  |     else | ||||||
|  |       m_path.lineTo(rc.x2(), rc.y); | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace doc
 | } // namespace doc
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Aseprite Document Library
 | // Aseprite Document Library
 | ||||||
|  | // Copyright (c) 2020 Igara Studio S.A.
 | ||||||
| // Copyright (c) 2001-2015 David Capello
 | // Copyright (c) 2001-2015 David Capello
 | ||||||
| //
 | //
 | ||||||
| // This file is released under the terms of the MIT license.
 | // This file is released under the terms of the MIT license.
 | ||||||
|  | @ -8,6 +9,7 @@ | ||||||
| #define DOC_MASK_BOUNDARIES_H_INCLUDED | #define DOC_MASK_BOUNDARIES_H_INCLUDED | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include "gfx/path.h" | ||||||
| #include "gfx/rect.h" | #include "gfx/rect.h" | ||||||
| 
 | 
 | ||||||
| #include <vector> | #include <vector> | ||||||
|  | @ -41,7 +43,9 @@ namespace doc { | ||||||
|     typedef list_type::iterator iterator; |     typedef list_type::iterator iterator; | ||||||
|     typedef list_type::const_iterator const_iterator; |     typedef list_type::const_iterator const_iterator; | ||||||
| 
 | 
 | ||||||
|     MaskBoundaries(const Image* bitmap); |     bool isEmpty() const { return m_segs.empty(); } | ||||||
|  |     void reset(); | ||||||
|  |     void regen(const Image* bitmap); | ||||||
| 
 | 
 | ||||||
|     const_iterator begin() const { return m_segs.begin(); } |     const_iterator begin() const { return m_segs.begin(); } | ||||||
|     const_iterator end() const { return m_segs.end(); } |     const_iterator end() const { return m_segs.end(); } | ||||||
|  | @ -49,9 +53,13 @@ namespace doc { | ||||||
|     iterator end() { return m_segs.end(); } |     iterator end() { return m_segs.end(); } | ||||||
| 
 | 
 | ||||||
|     void offset(int x, int y); |     void offset(int x, int y); | ||||||
|  |     gfx::Path& path() { return m_path; } | ||||||
|  | 
 | ||||||
|  |     void createPathIfNeeeded(); | ||||||
| 
 | 
 | ||||||
|   private: |   private: | ||||||
|     list_type m_segs; |     list_type m_segs; | ||||||
|  |     gfx::Path m_path; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
| } // namespace doc
 | } // namespace doc
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Aseprite Render Library
 | // Aseprite Render Library
 | ||||||
|  | // Copyright (c) 2020 Igara Studio S.A.
 | ||||||
| // Copyright (c) 2016 David Capello
 | // Copyright (c) 2016 David Capello
 | ||||||
| //
 | //
 | ||||||
| // This file is released under the terms of the MIT license.
 | // This file is released under the terms of the MIT license.
 | ||||||
|  | @ -9,6 +10,7 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "doc/pixel_ratio.h" | #include "doc/pixel_ratio.h" | ||||||
|  | #include "gfx/matrix.h" | ||||||
| #include "render/zoom.h" | #include "render/zoom.h" | ||||||
| 
 | 
 | ||||||
| namespace render { | namespace render { | ||||||
|  | @ -79,6 +81,10 @@ namespace render { | ||||||
|                         removeY(r.y+r.h) - v); |                         removeY(r.y+r.h) - v); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     gfx::Matrix scaleMatrix() const { | ||||||
|  |       return gfx::Matrix::MakeScale(scaleX(), scaleY()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|   private: |   private: | ||||||
|     doc::PixelRatio m_pixelRatio; |     doc::PixelRatio m_pixelRatio; | ||||||
|     Zoom m_zoom; |     Zoom m_zoom; | ||||||
|  |  | ||||||
|  | @ -13,6 +13,8 @@ | ||||||
| 
 | 
 | ||||||
| #include "base/string.h" | #include "base/string.h" | ||||||
| #include "gfx/clip.h" | #include "gfx/clip.h" | ||||||
|  | #include "gfx/matrix.h" | ||||||
|  | #include "gfx/path.h" | ||||||
| #include "gfx/point.h" | #include "gfx/point.h" | ||||||
| #include "gfx/rect.h" | #include "gfx/rect.h" | ||||||
| #include "gfx/region.h" | #include "gfx/region.h" | ||||||
|  | @ -81,6 +83,36 @@ bool Graphics::clipRect(const gfx::Rect& rc) | ||||||
|   return m_surface->clipRect(gfx::Rect(rc).offset(m_dx, m_dy)); |   return m_surface->clipRect(gfx::Rect(rc).offset(m_dx, m_dy)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void Graphics::save() | ||||||
|  | { | ||||||
|  |   m_surface->save(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Graphics::concat(const gfx::Matrix& matrix) | ||||||
|  | { | ||||||
|  |   m_surface->concat(matrix); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Graphics::setMatrix(const gfx::Matrix& matrix) | ||||||
|  | { | ||||||
|  |   m_surface->setMatrix(matrix); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Graphics::resetMatrix() | ||||||
|  | { | ||||||
|  |   m_surface->resetMatrix(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Graphics::restore() | ||||||
|  | { | ||||||
|  |   m_surface->restore(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | gfx::Matrix Graphics::matrix() const | ||||||
|  | { | ||||||
|  |   return m_surface->matrix(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void Graphics::setDrawMode(DrawMode mode, int param, | void Graphics::setDrawMode(DrawMode mode, int param, | ||||||
|                            const gfx::Color a, |                            const gfx::Color a, | ||||||
|                            const gfx::Color b) |                            const gfx::Color b) | ||||||
|  | @ -144,6 +176,21 @@ void Graphics::drawLine(gfx::Color color, const gfx::Point& _a, const gfx::Point | ||||||
|   m_surface->drawLine(a, b, paint); |   m_surface->drawLine(a, b, paint); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void Graphics::drawPath(gfx::Path& path, const Paint& paint) | ||||||
|  | { | ||||||
|  |   os::SurfaceLock lock(m_surface); | ||||||
|  | 
 | ||||||
|  |   auto m = matrix(); | ||||||
|  |   save(); | ||||||
|  |   setMatrix(gfx::Matrix::MakeTrans(m_dx, m_dy)); | ||||||
|  |   concat(m); | ||||||
|  | 
 | ||||||
|  |   m_surface->drawPath(path, paint); | ||||||
|  | 
 | ||||||
|  |   dirty(matrix().mapRect(path.bounds()).inflate(1, 1)); | ||||||
|  |   restore(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void Graphics::drawRect(gfx::Color color, const gfx::Rect& rcOrig) | void Graphics::drawRect(gfx::Color color, const gfx::Rect& rcOrig) | ||||||
| { | { | ||||||
|   gfx::Rect rc(rcOrig); |   gfx::Rect rc(rcOrig); | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| // Aseprite UI Library
 | // Aseprite UI Library
 | ||||||
| // Copyright (C) 2019  Igara Studio S.A.
 | // Copyright (C) 2019-2020  Igara Studio S.A.
 | ||||||
| // Copyright (C) 2001-2018  David Capello
 | // Copyright (C) 2001-2018  David Capello
 | ||||||
| //
 | //
 | ||||||
| // This file is released under the terms of the MIT license.
 | // This file is released under the terms of the MIT license.
 | ||||||
|  | @ -21,6 +21,8 @@ | ||||||
| #include <string> | #include <string> | ||||||
| 
 | 
 | ||||||
| namespace gfx { | namespace gfx { | ||||||
|  |   class Matrix; | ||||||
|  |   class Path; | ||||||
|   class Region; |   class Region; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -58,6 +60,13 @@ namespace ui { | ||||||
|     void restoreClip(); |     void restoreClip(); | ||||||
|     bool clipRect(const gfx::Rect& rc); |     bool clipRect(const gfx::Rect& rc); | ||||||
| 
 | 
 | ||||||
|  |     void save(); | ||||||
|  |     void concat(const gfx::Matrix& matrix); | ||||||
|  |     void setMatrix(const gfx::Matrix& matrix); | ||||||
|  |     void resetMatrix(); | ||||||
|  |     void restore(); | ||||||
|  |     gfx::Matrix matrix() const; | ||||||
|  | 
 | ||||||
|     void setDrawMode(DrawMode mode, int param = 0, |     void setDrawMode(DrawMode mode, int param = 0, | ||||||
|                      const gfx::Color a = gfx::ColorNone, |                      const gfx::Color a = gfx::ColorNone, | ||||||
|                      const gfx::Color b = gfx::ColorNone); |                      const gfx::Color b = gfx::ColorNone); | ||||||
|  | @ -68,6 +77,7 @@ namespace ui { | ||||||
|     void drawHLine(gfx::Color color, int x, int y, int w); |     void drawHLine(gfx::Color color, int x, int y, int w); | ||||||
|     void drawVLine(gfx::Color color, int x, int y, int h); |     void drawVLine(gfx::Color color, int x, int y, int h); | ||||||
|     void drawLine(gfx::Color color, const gfx::Point& a, const gfx::Point& b); |     void drawLine(gfx::Color color, const gfx::Point& a, const gfx::Point& b); | ||||||
|  |     void drawPath(gfx::Path& path, const Paint& paint); | ||||||
| 
 | 
 | ||||||
|     void drawRect(gfx::Color color, const gfx::Rect& rc); |     void drawRect(gfx::Color color, const gfx::Rect& rc); | ||||||
|     void fillRect(gfx::Color color, const gfx::Rect& rc); |     void fillRect(gfx::Color color, const gfx::Rect& rc); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue