mirror of https://github.com/aseprite/aseprite.git
				
				
				
			Merge branch 'master' into beta
This commit is contained in:
		
						commit
						e46d453356
					
				|  | @ -75,6 +75,7 @@ public: | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   Key* key() { return m_key; } |   Key* key() { return m_key; } | ||||||
|  |   AppMenuItem* menuitem() const { return m_menuitem; } | ||||||
| 
 | 
 | ||||||
|   void restoreKeys() { |   void restoreKeys() { | ||||||
|     if (m_key && m_keyOrig) |     if (m_key && m_keyOrig) | ||||||
|  | @ -502,7 +503,8 @@ private: | ||||||
| 
 | 
 | ||||||
|             KeyItem* copyItem = |             KeyItem* copyItem = | ||||||
|               new KeyItem(itemText, |               new KeyItem(itemText, | ||||||
|                           keyItem->key(), nullptr, 0); |                           keyItem->key(), | ||||||
|  |                           keyItem->menuitem(), 0); | ||||||
|             searchList()->addChild(copyItem); |             searchList()->addChild(copyItem); | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -1066,46 +1066,26 @@ void BrushInkProcessing<IndexedTraits>::processPixel(int x, int y) { | ||||||
| 
 | 
 | ||||||
| //////////////////////////////////////////////////////////////////////
 | //////////////////////////////////////////////////////////////////////
 | ||||||
| 
 | 
 | ||||||
| enum { | template<template<typename> class InkProcessing, | ||||||
|   INK_COPY, |          typename ImageTraits> | ||||||
|   INK_LOCKALPHA, | void ink_proc(int x1, int y, int x2, void* data) | ||||||
|   INK_TRANSPARENT, |  | ||||||
|   INK_MERGE, |  | ||||||
|   INK_BLUR, |  | ||||||
|   INK_REPLACE, |  | ||||||
|   INK_JUMBLE, |  | ||||||
|   INK_SHADING, |  | ||||||
|   INK_XOR, |  | ||||||
|   INK_BRUSH, |  | ||||||
|   MAX_INKS |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| template<typename InkProcessing> |  | ||||||
| void ink_processing_algo(int x1, int y, int x2, void* data) |  | ||||||
| { | { | ||||||
|   ToolLoop* loop = reinterpret_cast<ToolLoop*>(data); |   ToolLoop* loop = reinterpret_cast<ToolLoop*>(data); | ||||||
|   InkProcessing ink(loop); |   InkProcessing<ImageTraits> ink(loop); | ||||||
|   ink(x1, y, x2, loop); |   ink(x1, y, x2, loop); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| AlgoHLine ink_processing[][3] = | template<template<typename> class InkProcessing> | ||||||
|  | AlgoHLine get_ink_proc(PixelFormat pixelFormat) | ||||||
| { | { | ||||||
| #define DEFINE_INK(name)                         \ |   switch (pixelFormat) { | ||||||
|   { ink_processing_algo<name<RgbTraits> >,       \ |     case IMAGE_RGB:       return ink_proc<InkProcessing, RgbTraits>; | ||||||
|     ink_processing_algo<name<GrayscaleTraits> >, \ |     case IMAGE_GRAYSCALE: return ink_proc<InkProcessing, GrayscaleTraits>; | ||||||
|     ink_processing_algo<name<IndexedTraits> > } |     case IMAGE_INDEXED:   return ink_proc<InkProcessing, IndexedTraits>; | ||||||
| 
 |   } | ||||||
|   DEFINE_INK(CopyInkProcessing), |   ASSERT(false); | ||||||
|   DEFINE_INK(LockAlphaInkProcessing), |   return nullptr; | ||||||
|   DEFINE_INK(TransparentInkProcessing), | } | ||||||
|   DEFINE_INK(MergeInkProcessing), |  | ||||||
|   DEFINE_INK(BlurInkProcessing), |  | ||||||
|   DEFINE_INK(ReplaceInkProcessing), |  | ||||||
|   DEFINE_INK(JumbleInkProcessing), |  | ||||||
|   DEFINE_INK(ShadingInkProcessing), |  | ||||||
|   DEFINE_INK(XorInkProcessing), |  | ||||||
|   DEFINE_INK(BrushInkProcessing) |  | ||||||
| }; |  | ||||||
| 
 | 
 | ||||||
| } // anonymous namespace
 | } // anonymous namespace
 | ||||||
| } // namespace tools
 | } // namespace tools
 | ||||||
|  |  | ||||||
|  | @ -53,10 +53,10 @@ public: | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     int depth = MID(0, loop->sprite()->pixelFormat(), 2); |     auto pixelFormat = loop->sprite()->pixelFormat(); | ||||||
| 
 | 
 | ||||||
|     if (loop->getBrush()->type() == doc::kImageBrushType) |     if (loop->getBrush()->type() == doc::kImageBrushType) | ||||||
|       m_proc = ink_processing[INK_BRUSH][depth]; |       m_proc = get_ink_proc<BrushInkProcessing>(pixelFormat); | ||||||
|     else { |     else { | ||||||
|       switch (m_type) { |       switch (m_type) { | ||||||
|         case Simple: { |         case Simple: { | ||||||
|  | @ -81,19 +81,19 @@ public: | ||||||
| 
 | 
 | ||||||
|           // Use a faster ink, direct copy
 |           // Use a faster ink, direct copy
 | ||||||
|           if (opaque) |           if (opaque) | ||||||
|             m_proc = ink_processing[INK_COPY][depth]; |             m_proc = get_ink_proc<CopyInkProcessing>(pixelFormat); | ||||||
|           else |           else | ||||||
|             m_proc = ink_processing[INK_TRANSPARENT][depth]; |             m_proc = get_ink_proc<TransparentInkProcessing>(pixelFormat); | ||||||
|           break; |           break; | ||||||
|         } |         } | ||||||
|         case Copy: |         case Copy: | ||||||
|           m_proc = ink_processing[INK_COPY][depth]; |           m_proc = get_ink_proc<CopyInkProcessing>(pixelFormat); | ||||||
|           break; |           break; | ||||||
|         case LockAlpha: |         case LockAlpha: | ||||||
|           m_proc = ink_processing[INK_LOCKALPHA][depth]; |           m_proc = get_ink_proc<LockAlphaInkProcessing>(pixelFormat); | ||||||
|           break; |           break; | ||||||
|         default: |         default: | ||||||
|           m_proc = ink_processing[INK_TRANSPARENT][depth]; |           m_proc = get_ink_proc<TransparentInkProcessing>(pixelFormat); | ||||||
|           break; |           break; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  | @ -120,7 +120,7 @@ public: | ||||||
|   bool isShading() const override { return true; } |   bool isShading() const override { return true; } | ||||||
| 
 | 
 | ||||||
|   void prepareInk(ToolLoop* loop) override { |   void prepareInk(ToolLoop* loop) override { | ||||||
|     m_proc = ink_processing[INK_SHADING][MID(0, loop->sprite()->pixelFormat(), 2)]; |     m_proc = get_ink_proc<ShadingInkProcessing>(loop->sprite()->pixelFormat()); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   void inkHline(int x1, int y, int x2, ToolLoop* loop) override { |   void inkHline(int x1, int y, int x2, ToolLoop* loop) override { | ||||||
|  | @ -207,16 +207,16 @@ public: | ||||||
|         color_t secondary = app_get_color_to_clear_layer(loop->getLayer()); |         color_t secondary = app_get_color_to_clear_layer(loop->getLayer()); | ||||||
| 
 | 
 | ||||||
|         if (loop->getOpacity() == 255) { |         if (loop->getOpacity() == 255) { | ||||||
|           m_proc = ink_processing[INK_COPY][MID(0, loop->sprite()->pixelFormat(), 2)]; |           m_proc = get_ink_proc<CopyInkProcessing>(loop->sprite()->pixelFormat()); | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|           // For opaque layers
 |           // For opaque layers
 | ||||||
|           if (loop->getLayer()->isBackground()) { |           if (loop->getLayer()->isBackground()) { | ||||||
|             m_proc = ink_processing[INK_TRANSPARENT][MID(0, loop->sprite()->pixelFormat(), 2)]; |             m_proc = get_ink_proc<TransparentInkProcessing>(loop->sprite()->pixelFormat()); | ||||||
|           } |           } | ||||||
|           // For transparent layers
 |           // For transparent layers
 | ||||||
|           else { |           else { | ||||||
|             m_proc = ink_processing[INK_MERGE][MID(0, loop->sprite()->pixelFormat(), 2)]; |             m_proc = get_ink_proc<MergeInkProcessing>(loop->sprite()->pixelFormat()); | ||||||
| 
 | 
 | ||||||
|             if (loop->sprite()->pixelFormat() == IMAGE_INDEXED) { |             if (loop->sprite()->pixelFormat() == IMAGE_INDEXED) { | ||||||
|               primary = loop->sprite()->transparentColor(); |               primary = loop->sprite()->transparentColor(); | ||||||
|  | @ -231,14 +231,14 @@ public: | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       case ReplaceFgWithBg: |       case ReplaceFgWithBg: | ||||||
|         m_proc = ink_processing[INK_REPLACE][MID(0, loop->sprite()->pixelFormat(), 2)]; |         m_proc = get_ink_proc<ReplaceInkProcessing>(loop->sprite()->pixelFormat()); | ||||||
| 
 | 
 | ||||||
|         loop->setPrimaryColor(loop->getFgColor()); |         loop->setPrimaryColor(loop->getFgColor()); | ||||||
|         loop->setSecondaryColor(loop->getBgColor()); |         loop->setSecondaryColor(loop->getBgColor()); | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|       case ReplaceBgWithFg: |       case ReplaceBgWithFg: | ||||||
|         m_proc = ink_processing[INK_REPLACE][MID(0, loop->sprite()->pixelFormat(), 2)]; |         m_proc = get_ink_proc<ReplaceInkProcessing>(loop->sprite()->pixelFormat()); | ||||||
| 
 | 
 | ||||||
|         loop->setPrimaryColor(loop->getBgColor()); |         loop->setPrimaryColor(loop->getBgColor()); | ||||||
|         loop->setSecondaryColor(loop->getFgColor()); |         loop->setSecondaryColor(loop->getFgColor()); | ||||||
|  | @ -263,7 +263,7 @@ public: | ||||||
|   bool needsSpecialSourceArea() const override { return true; } |   bool needsSpecialSourceArea() const override { return true; } | ||||||
| 
 | 
 | ||||||
|   void prepareInk(ToolLoop* loop) override { |   void prepareInk(ToolLoop* loop) override { | ||||||
|     m_proc = ink_processing[INK_BLUR][MID(0, loop->sprite()->pixelFormat(), 2)]; |     m_proc = get_ink_proc<BlurInkProcessing>(loop->sprite()->pixelFormat()); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   void inkHline(int x1, int y, int x2, ToolLoop* loop) override { |   void inkHline(int x1, int y, int x2, ToolLoop* loop) override { | ||||||
|  | @ -291,7 +291,7 @@ public: | ||||||
|   bool needsSpecialSourceArea() const override { return true; } |   bool needsSpecialSourceArea() const override { return true; } | ||||||
| 
 | 
 | ||||||
|   void prepareInk(ToolLoop* loop) override { |   void prepareInk(ToolLoop* loop) override { | ||||||
|     m_proc = ink_processing[INK_JUMBLE][MID(0, loop->sprite()->pixelFormat(), 2)]; |     m_proc = get_ink_proc<JumbleInkProcessing>(loop->sprite()->pixelFormat()); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   void inkHline(int x1, int y, int x2, ToolLoop* loop) override { |   void inkHline(int x1, int y, int x2, ToolLoop* loop) override { | ||||||
|  | @ -313,12 +313,19 @@ class SelectionInk : public Ink { | ||||||
|   bool m_modify_selection; |   bool m_modify_selection; | ||||||
|   Mask m_mask; |   Mask m_mask; | ||||||
|   Rect m_maxBounds; |   Rect m_maxBounds; | ||||||
|  |   AlgoHLine m_proc; | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|   SelectionInk() { m_modify_selection = false; } |   SelectionInk() { | ||||||
|  |     m_modify_selection = false; | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   Ink* clone() override { return new SelectionInk(*this); } |   Ink* clone() override { return new SelectionInk(*this); } | ||||||
| 
 | 
 | ||||||
|  |   void prepareInk(ToolLoop* loop) override { | ||||||
|  |     m_proc = get_ink_proc<XorInkProcessing>(loop->sprite()->pixelFormat()); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   bool isSelection() const override { return true; } |   bool isSelection() const override { return true; } | ||||||
|   bool needsCelCoordinates() const override { |   bool needsCelCoordinates() const override { | ||||||
|     return (m_modify_selection ? false: true); |     return (m_modify_selection ? false: true); | ||||||
|  | @ -340,8 +347,7 @@ public: | ||||||
|     } |     } | ||||||
|     // TODO show the selection-preview with a XOR color or something like that
 |     // TODO show the selection-preview with a XOR color or something like that
 | ||||||
|     else { |     else { | ||||||
|       ink_processing[INK_XOR][MID(0, loop->sprite()->pixelFormat(), 2)] |       (*m_proc)(x1, y, x2, loop); | ||||||
|         (x1, y, x2, loop); |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -52,10 +52,6 @@ DrawingState::~DrawingState() | ||||||
| 
 | 
 | ||||||
| void DrawingState::initToolLoop(Editor* editor, MouseMessage* msg) | void DrawingState::initToolLoop(Editor* editor, MouseMessage* msg) | ||||||
| { | { | ||||||
|   // It's needed to clear and redraw the brush boundaries after the
 |  | ||||||
|   // first mouse pressed/point shape if drawn.
 |  | ||||||
|   HideBrushPreview hide(editor->brushPreview()); |  | ||||||
| 
 |  | ||||||
|   // Prepare preview image (the destination image will be our preview
 |   // Prepare preview image (the destination image will be our preview
 | ||||||
|   // in the tool-loop time, so we can see what we are drawing)
 |   // in the tool-loop time, so we can see what we are drawing)
 | ||||||
|   editor->renderEngine().setPreviewImage( |   editor->renderEngine().setPreviewImage( | ||||||
|  |  | ||||||
|  | @ -305,6 +305,12 @@ bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg) | ||||||
|     if (layerEdges) |     if (layerEdges) | ||||||
|       layerEdgesOption(false); |       layerEdgesOption(false); | ||||||
| 
 | 
 | ||||||
|  |     // We need to clear and redraw the brush boundaries after the
 | ||||||
|  |     // first mouse pressed/point shape if drawn. This is to avoid
 | ||||||
|  |     // graphical glitches (invalid areas in the ToolLoop's src/dst
 | ||||||
|  |     // images).
 | ||||||
|  |     HideBrushPreview hide(editor->brushPreview()); | ||||||
|  | 
 | ||||||
|     tools::ToolLoop* toolLoop = create_tool_loop(editor, context); |     tools::ToolLoop* toolLoop = create_tool_loop(editor, context); | ||||||
|     if (toolLoop) { |     if (toolLoop) { | ||||||
|       EditorStatePtr newState(new DrawingState(toolLoop)); |       EditorStatePtr newState(new DrawingState(toolLoop)); | ||||||
|  |  | ||||||
|  | @ -241,10 +241,15 @@ public: | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   void updateDirtyArea() override { |   void updateDirtyArea() override { | ||||||
|     // TODO find a way to avoid calling hide/show brush preview here
 |     // This is necessary here so the "on sprite crosshair" is hidden,
 | ||||||
|  |     // we update screen pixels with the new sprite, and then we show
 | ||||||
|  |     // the crosshair saving the updated pixels. It fixes problems with
 | ||||||
|  |     // filled shape tools when we release the button, or paint-bucket
 | ||||||
|  |     // when we press the button.
 | ||||||
|     HideBrushPreview hide(m_editor->brushPreview()); |     HideBrushPreview hide(m_editor->brushPreview()); | ||||||
|     m_document->notifySpritePixelsModified(m_sprite, m_dirtyArea, | 
 | ||||||
|                                            m_frame); |     m_document->notifySpritePixelsModified( | ||||||
|  |       m_sprite, m_dirtyArea, m_frame); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   void updateStatusBar(const char* text) override { |   void updateStatusBar(const char* text) override { | ||||||
|  |  | ||||||
|  | @ -42,20 +42,21 @@ CompressedImage::CompressedImage(const Image* image, | ||||||
|       scanline.x = x; |       scanline.x = x; | ||||||
| 
 | 
 | ||||||
|       for (++x; x<image->width(); ++x) { |       for (++x; x<image->width(); ++x) { | ||||||
|  |         if (maskBitmap && !get_pixel_fast<BitmapTraits>(maskBitmap, x, y)) | ||||||
|  |           break; | ||||||
|  | 
 | ||||||
|         c2 = get_pixel(image, x, y); |         c2 = get_pixel(image, x, y); | ||||||
| 
 | 
 | ||||||
|         if (diffColors && c1 != c2) |         if (diffColors && c1 != c2) | ||||||
|           break; |           break; | ||||||
| 
 | 
 | ||||||
|         if (maskBitmap && !get_pixel_fast<BitmapTraits>(maskBitmap, x, y)) |  | ||||||
|           break; |  | ||||||
| 
 |  | ||||||
|         if (!diffColors && !maskBitmap && c2 == mask) |         if (!diffColors && !maskBitmap && c2 == mask) | ||||||
|           break; |           break; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       scanline.w = x - scanline.x; |       scanline.w = x - scanline.x; | ||||||
|       m_scanlines.push_back(scanline); |       if (scanline.w > 0) | ||||||
|  |         m_scanlines.push_back(scanline); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue