Merge branch 'master' into beta

This commit is contained in:
David Capello 2021-02-25 17:12:53 -03:00
commit 49d5787737
4 changed files with 185 additions and 45 deletions

2
laf

@ -1 +1 @@
Subproject commit 0b2e8b7a401aa34c245afe5e0114a498d4e341cd
Subproject commit 6cff5d558e88c6726339fe977d2630db367f9f58

View File

@ -31,6 +31,7 @@
#include "app/ui_context.h"
#include "app/util/wrap_value.h"
#include "base/debug.h"
#include "base/scoped_value.h"
#include "doc/algo.h"
#include "doc/blend_internals.h"
#include "doc/brush.h"
@ -38,7 +39,9 @@
#include "doc/image_impl.h"
#include "doc/layer.h"
#include "doc/primitives.h"
#include "gfx/rect_io.h"
#include "os/surface.h"
#include "os/system.h"
#include "os/window.h"
#include "render/render.h"
#include "ui/manager.h"
#include "ui/system.h"
@ -49,17 +52,12 @@ using namespace doc;
BrushPreview::BrushPreview(Editor* editor)
: m_editor(editor)
, m_type(CROSSHAIR)
, m_onScreen(false)
, m_withModifiedPixels(false)
, m_withRealPreview(false)
, m_screenPosition(0, 0)
, m_editorPosition(0, 0)
{
}
BrushPreview::~BrushPreview()
{
m_cursor.reset();
}
BrushRef BrushPreview::getCurrentBrush()
@ -352,8 +350,13 @@ void BrushPreview::show(const gfx::Point& screenPos)
ui::ScreenGraphics g(m_editor->display());
ui::SetClip clip(&g);
gfx::Color uiCursorColor = color_utils::color_for_ui(appCursorColor);
forEachBrushPixel(&g, m_screenPosition, spritePos, uiCursorColor, &BrushPreview::savePixelDelegate);
forEachBrushPixel(&g, m_screenPosition, spritePos, uiCursorColor, &BrushPreview::drawPixelDelegate);
createNativeCursor();
if (m_cursor)
forEachLittleCrossPixel(&g, m_screenPosition, uiCursorColor, &BrushPreview::putPixelInCursorDelegate);
forEachBrushPixel(&g, spritePos, uiCursorColor, &BrushPreview::savePixelDelegate);
forEachBrushPixel(&g, spritePos, uiCursorColor, &BrushPreview::drawPixelDelegate);
m_withModifiedPixels = true;
}
@ -378,6 +381,12 @@ void BrushPreview::hide()
if (!m_onScreen)
return;
// Don't hide the cursor to avoid flickering, the native mouse
// cursor will be changed anyway after the hide() by the caller.
//
//if (m_cursor)
// m_editor->m_editor->display()->nativeWindow()->setNativeMouseCursor(os::NativeCursor::Hidden);
// Get drawable region
m_editor->getDrawableRegion(m_clippingRegion, ui::Widget::kCutTopWindows);
@ -389,7 +398,7 @@ void BrushPreview::hide()
// Restore pixels
ui::ScreenGraphics g(m_editor->display());
ui::SetClip clip(&g);
forEachBrushPixel(&g, m_screenPosition, m_editorPosition, gfx::ColorNone,
forEachBrushPixel(&g, m_editorPosition, gfx::ColorNone,
&BrushPreview::clearPixelDelegate);
}
@ -411,6 +420,7 @@ void BrushPreview::hide()
}
m_onScreen = false;
m_clippingRegion.clear();
m_oldClippingRegion.clear();
}
@ -451,12 +461,7 @@ void BrushPreview::generateBoundaries()
(m_editor->getCurrentEditorTool()->getPointShape(0)->isPixel() ||
m_editor->getCurrentEditorTool()->getPointShape(0)->isFloodFill());
Image* brushImage = brush->image();
int w = (isOnePixel ? 1: brushImage->width());
int h = (isOnePixel ? 1: brushImage->height());
m_brushGen = brush->gen();
m_brushWidth = w;
m_brushHeight = h;
Image* mask = nullptr;
bool deleteMask = true;
@ -479,30 +484,89 @@ void BrushPreview::generateBoundaries()
delete mask;
}
void BrushPreview::forEachBrushPixel(
void BrushPreview::createNativeCursor()
{
gfx::Rect cursorBounds;
if (m_type & CROSSHAIR) {
cursorBounds |= gfx::Rect(-3, -3, 7, 7);
m_cursorCenter = -cursorBounds.origin();
}
// Special case of a cursor for one pixel
else if (!(m_type & NATIVE_CROSSHAIR) &&
m_editor->zoom().scale() >= 4.0) {
cursorBounds = gfx::Rect(0, 0, 1, 1);
m_cursorCenter = gfx::Point(0, 0);
}
if (m_cursor) {
if (m_cursor->width() != cursorBounds.w ||
m_cursor->height() != cursorBounds.h) {
m_cursor.reset();
}
}
if (cursorBounds.isEmpty()) {
ASSERT(!m_cursor);
m_editor->display()->nativeWindow()->setNativeMouseCursor(os::NativeCursor::Hidden);
return;
}
if (!m_cursor) {
m_cursor = os::instance()->makeRgbaSurface(cursorBounds.w, cursorBounds.h);
// Cannot clear the cursor on each iteration because it can
// generate a flicker effect when zooming in the same mouse
// position. That's strange.
m_cursor->clear();
}
}
void BrushPreview::forEachLittleCrossPixel(
ui::Graphics* g,
const gfx::Point& screenPos,
const gfx::Point& spritePos,
gfx::Color color,
PixelDelegate pixelDelegate)
{
m_savedPixelsIterator = 0;
if (m_type & CROSSHAIR)
traceCrossPixels(g, screenPos, color, pixelDelegate);
if (m_type & SELECTION_CROSSHAIR)
traceSelectionCrossPixels(g, spritePos, color, 1, pixelDelegate);
if (m_type & BRUSH_BOUNDARIES)
traceBrushBoundaries(g, spritePos, color, pixelDelegate);
// Depending on the editor zoom, maybe we need subpixel movement (a
// little dot inside the active pixel)
if (!(m_type & NATIVE_CROSSHAIR) &&
m_editor->zoom().scale() >= 4.0) {
(this->*pixelDelegate)(g, screenPos, color);
}
else {
// We'll remove the pixel (as we didn't called Surface::clear() to
// avoid a flickering issue when zooming in the same mouse
// position).
base::ScopedValue<bool> restore(m_blackAndWhiteNegative, false,
m_blackAndWhiteNegative);
(this->*pixelDelegate)(g, screenPos, gfx::ColorNone);
}
if (m_cursor) {
m_editor->display()->nativeWindow()->setNativeMouseCursor(
m_cursor.get(),
m_cursorCenter,
m_editor->display()->nativeWindow()->scale());
}
}
void BrushPreview::forEachBrushPixel(
ui::Graphics* g,
const gfx::Point& spritePos,
gfx::Color color,
PixelDelegate pixelDelegate)
{
m_savedPixelsIterator = 0;
if (m_type & SELECTION_CROSSHAIR)
traceSelectionCrossPixels(g, spritePos, color, 1, pixelDelegate);
if (m_type & BRUSH_BOUNDARIES)
traceBrushBoundaries(g, spritePos, color, pixelDelegate);
m_savedPixelsLimit = m_savedPixelsIterator;
}
@ -535,9 +599,7 @@ void BrushPreview::traceCrossPixels(
}
}
//////////////////////////////////////////////////////////////////////
// Old Thick Cross
// Old thick cross (used for selection tools)
void BrushPreview::traceSelectionCrossPixels(
ui::Graphics* g,
const gfx::Point& pt, gfx::Color color,
@ -574,9 +636,7 @@ void BrushPreview::traceSelectionCrossPixels(
}
}
//////////////////////////////////////////////////////////////////////
// Current Brush Bounds
// Current brush edges
void BrushPreview::traceBrushBoundaries(ui::Graphics* g,
gfx::Point pos,
gfx::Color color,
@ -604,6 +664,33 @@ void BrushPreview::traceBrushBoundaries(ui::Graphics* g,
}
}
//////////////////////////////////////////////////////////////////////
// Pixel delegates
void BrushPreview::putPixelInCursorDelegate(ui::Graphics* g, const gfx::Point& pt, gfx::Color color)
{
ASSERT(m_cursor);
if (!m_clippingRegion.contains(pt))
return;
if (m_blackAndWhiteNegative) {
color_t c = g->getPixel(pt.x, pt.y);
int r = gfx::getr(c);
int g = gfx::getg(c);
int b = gfx::getb(c);
m_cursor->putPixel(color_utils::blackandwhite_neg(gfx::rgba(r, g, b)),
pt.x - m_screenPosition.x + m_cursorCenter.x,
pt.y - m_screenPosition.y + m_cursorCenter.y);
}
else {
m_cursor->putPixel(color,
pt.x - m_screenPosition.x + m_cursorCenter.x,
pt.y - m_screenPosition.y + m_cursorCenter.y);
}
}
void BrushPreview::savePixelDelegate(ui::Graphics* g, const gfx::Point& pt, gfx::Color color)
{
if (m_clippingRegion.contains(pt)) {

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A.
// Copyright (C) 2019-2021 Igara Studio S.A.
// Copyright (C) 2001-2016 David Capello
//
// This program is distributed under the terms of
@ -18,6 +18,7 @@
#include "gfx/point.h"
#include "gfx/rect.h"
#include "gfx/region.h"
#include "os/surface.h"
#include <vector>
@ -37,9 +38,33 @@ namespace app {
public:
// Brush type
enum {
// A simple cursor in the mouse position for drawing tools. The
// crosshair is painted in real-time with black and white
// depending on the pixel of the screen.
//
// |
// |
// --- * ---
// |
// |
CROSSHAIR = 1,
// Crosshair used in the selection tools in the sprite position.
//
// | |
// -- --
// *
// -- --
// | |
SELECTION_CROSSHAIR = 2,
// The boundaries of the brush used in the sprite position
// (depends on the shape of the brush generated with
// doc::MaskBoundaries).
BRUSH_BOUNDARIES = 4,
// Use a pre-defined native cursor that is a crosshair in the
// mouse position.
NATIVE_CROSSHAIR = 8,
};
@ -63,9 +88,16 @@ namespace app {
static doc::color_t getBrushColor(doc::Sprite* sprite, doc::Layer* layer);
void generateBoundaries();
void forEachBrushPixel(
// Creates a little native cursor to draw the CROSSHAIR
void createNativeCursor();
void forEachLittleCrossPixel(
ui::Graphics* g,
const gfx::Point& screenPos,
gfx::Color color,
PixelDelegate pixelDelegate);
void forEachBrushPixel(
ui::Graphics* g,
const gfx::Point& spritePos,
gfx::Color color,
PixelDelegate pixelDelegate);
@ -74,30 +106,36 @@ namespace app {
void traceSelectionCrossPixels(ui::Graphics* g, const gfx::Point& pt, gfx::Color color, int thickness, PixelDelegate pixel);
void traceBrushBoundaries(ui::Graphics* g, gfx::Point pos, gfx::Color color, PixelDelegate pixel);
void putPixelInCursorDelegate(ui::Graphics* g, const gfx::Point& pt, gfx::Color color);
void savePixelDelegate(ui::Graphics* g, const gfx::Point& pt, gfx::Color color);
void drawPixelDelegate(ui::Graphics* g, const gfx::Point& pt, gfx::Color color);
void clearPixelDelegate(ui::Graphics* g, const gfx::Point& pt, gfx::Color color);
Editor* m_editor;
int m_type;
int m_type = CROSSHAIR;
// The brush preview shows the cross or brush boundaries as black
// & white negative.
bool m_blackAndWhiteNegative;
// The brush preview is on the screen.
bool m_onScreen;
bool m_withModifiedPixels;
bool m_withRealPreview;
bool m_onScreen = false;
bool m_withRealPreview = false;
gfx::Point m_screenPosition; // Position in the screen (view)
gfx::Point m_editorPosition; // Position in the editor (model)
// Native mouse cursor to draw crosshair
os::SurfaceRef m_cursor;
gfx::Point m_cursorCenter;
// Information about current brush
doc::MaskBoundaries m_brushBoundaries;
int m_brushGen;
int m_brushWidth;
int m_brushHeight;
// True if we've modified pixels in the display surface
// (e.g. drawing the selection crosshair or the brush edges).
bool m_withModifiedPixels = false;
std::vector<gfx::Color> m_savedPixels;
int m_savedPixelsIterator;
int m_savedPixelsLimit;

View File

@ -45,6 +45,13 @@
#include <utility>
#include <vector>
#if defined(_WIN32) && defined(DEBUG_PAINT_EVENTS)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef min
#undef max
#endif
namespace ui {
namespace {
@ -1568,15 +1575,23 @@ bool Manager::sendMessageToWidget(Message* msg, Widget* widget)
#ifdef DEBUG_PAINT_EVENTS
{
os::SurfaceLock lock(surface);
surface->fillRect(gfx::rgba(0, 0, 255), paintMsg->rect());
os::Paint p;
p.color(gfx::rgba(0, 0, 255));
surface->drawRect(paintMsg->rect(), p);
}
if (m_window) {
m_window->invalidateRegion(gfx::Region(m_window->bounds()));
// TODO m_window->update() ??
#ifdef _WIN32 // TODO add a m_display->updateNow() method ??
HWND hwnd = (HWND)m_display->nativeHandle();
UpdateWindow(hwnd);
#endif
}
#ifndef _WIN32
base::this_thread::sleep_for(0.002);
#endif
#endif
if (surface) {