Merge branch 'main' into beta

This commit is contained in:
David Capello 2021-08-31 09:06:09 -03:00
commit adc9c109da
12 changed files with 282 additions and 70 deletions

125
.clang-format Normal file
View File

@ -0,0 +1,125 @@
---
Language: Cpp
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: AcrossEmptyLines
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortEnumsOnASingleLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: InlineOnly
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: true
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeComma
BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeComma
BreakStringLiterals: false
ColumnLimit: 80
CompactNamespaces: true
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 2
Cpp11BracedListStyle: false
DeriveLineEnding: false
DerivePointerAlignment: false
DisableFormat: false
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
IncludeBlocks: Preserve
IndentCaseLabels: true
IndentCaseBlocks: false
IndentGotoLabels: true
IndentPPDirectives: BeforeHash
IndentExternBlock: AfterExternBlock
IndentRequires: false
IndentWidth: 2
IndentWrappedFunctionNames: false
InsertTrailingCommas: None
KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 1000
PenaltyIndentedWhitespace: 0
PointerAlignment: Left
ReflowComments: false
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceAroundPointerQualifiers: Default
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
BitFieldColonSpacing: Both
Standard: Latest
TabWidth: 8
UseCRLF: false
UseTab: Never
...

View File

@ -41,8 +41,8 @@ if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/laf/CMakeLists.txt)
message(FATAL_ERROR "Your Aseprite repository is incomplete, initialize submodules using:\n git submodule update --init --recursive")
endif()
# This required for KDE/Qt destop integration, which sets BUILD_SHARED_LIBS to
# TRUE by default
# This is required for KDE/Qt destop integration, which sets
# BUILD_SHARED_LIBS to TRUE by default
set(BUILD_SHARED_LIBS off)
enable_testing()

View File

@ -126,6 +126,10 @@ protected:
};
```
## Const
* [NL.26: Use conventional const notation](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#nl26-use-conventional-const-notation)
## C++11
We are using some modern C++ (C++11, C++14, etc.) features, mainly:

View File

@ -13,6 +13,7 @@
#include "app/doc.h"
#include "app/doc_event.h"
#include "app/doc_observer.h"
#include "app/pref/preferences.h"
#include "doc/sprite.h"
namespace app {
@ -29,15 +30,23 @@ SetGridBounds::SetGridBounds(Sprite* sprite, const gfx::Rect& bounds)
void SetGridBounds::onExecute()
{
Sprite* spr = sprite();
spr->setGridBounds(m_newBounds);
spr->incrementVersion();
setGrid(m_newBounds);
}
void SetGridBounds::onUndo()
{
setGrid(m_oldBounds);
}
void SetGridBounds::setGrid(const gfx::Rect& grid)
{
Sprite* spr = sprite();
spr->setGridBounds(m_oldBounds);
spr->setGridBounds(grid);
Doc* doc = static_cast<Doc*>(spr->document());
auto& docPref = Preferences::instance().document(doc);
docPref.grid.bounds(grid);
spr->incrementVersion();
}

View File

@ -33,6 +33,8 @@ namespace cmd {
}
private:
void setGrid(const gfx::Rect& grid);
gfx::Rect m_oldBounds;
gfx::Rect m_newBounds;
};

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-2015 David Capello
//
// This program is distributed under the terms of
@ -53,6 +53,13 @@ SetPalette::SetPalette(Sprite* sprite, frame_t frame, const Palette* newPalette)
m_newColors[i] = newPalette->getEntry(m_from+i);
}
}
if (sprite->pixelFormat() == IMAGE_INDEXED) {
m_oldTransparentIndex = sprite->transparentColor();
if (m_oldTransparentIndex >= newPalette->size())
m_newTransparentIndex = newPalette->size() -1;
else
m_newTransparentIndex = m_oldTransparentIndex;
}
}
void SetPalette::onExecute()
@ -64,6 +71,7 @@ void SetPalette::onExecute()
for (size_t i=0; i<m_newColors.size(); ++i)
palette->setEntry(m_from+i, m_newColors[i]);
sprite->setTransparentColor(m_newTransparentIndex);
palette->incrementVersion();
}
@ -76,6 +84,7 @@ void SetPalette::onUndo()
for (size_t i=0; i<m_oldColors.size(); ++i)
palette->setEntry(m_from+i, m_oldColors[i]);
sprite->setTransparentColor(m_oldTransparentIndex);
palette->incrementVersion();
}

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019 Igara Studio S.A.
// Copyright (C) 2019-2021 Igara Studio S.A.
// Copyright (C) 2001-2015 David Capello
//
// This program is distributed under the terms of
@ -45,6 +45,8 @@ namespace cmd {
int m_from, m_to;
int m_oldNColors;
int m_newNColors;
int m_oldTransparentIndex;
int m_newTransparentIndex;
std::vector<color_t> m_oldColors;
std::vector<color_t> m_newColors;
};

View File

@ -131,7 +131,6 @@ void GridSettingsCommand::onExecute(Context* context)
tx.commit();
auto& docPref = Preferences::instance().document(site.document());
docPref.grid.bounds(bounds);
if (!docPref.show.grid()) // Make grid visible
docPref.show.grid(true);
}

View File

@ -856,7 +856,9 @@ void ColorBar::onRemapPalButtonClick()
}
color_t oldTransparent = sprite->transparentColor();
color_t newTransparent = remap[oldTransparent];
color_t newTransparent = (remap[oldTransparent] >= 0) ? remap[oldTransparent] : oldTransparent;
if (newTransparent >= get_current_palette()->size())
newTransparent = get_current_palette()->size() - 1;
if (oldTransparent != newTransparent)
tx(new cmd::SetTransparentColor(sprite, newTransparent));

View File

@ -112,8 +112,8 @@ void UIContext::setActiveView(DocView* docView)
else
current_editor = nullptr;
mainWin->getPreviewEditor()->updateUsingEditor(current_editor);
mainWin->getTimeline()->updateUsingEditor(current_editor);
mainWin->getPreviewEditor()->updateUsingEditor(current_editor);
// Change the image-type of color bar.
ColorBar::instance()->setPixelFormat(app_get_current_pixel_format());

View File

@ -59,10 +59,10 @@ Palette* load_pal_file(const char *filename)
if (line.empty())
continue;
int r, g, b;
int r, g, b, a=255;
std::istringstream lineIn(line);
lineIn >> r >> g >> b;
pal->addEntry(rgba(r, g, b, 255));
lineIn >> r >> g >> b >> a;
pal->addEntry(rgba(r, g, b, a));
}
return pal.release();
@ -77,11 +77,16 @@ bool save_pal_file(const Palette *pal, const char *filename)
<< "0100\n"
<< pal->size() << "\n";
const bool hasAlpha = pal->hasAlpha();
for (int i=0; i<pal->size(); ++i) {
uint32_t col = pal->getEntry(i);
f << ((int)rgba_getr(col)) << " "
<< ((int)rgba_getg(col)) << " "
<< ((int)rgba_getb(col)) << "\n";
<< ((int)rgba_getb(col));
if (hasAlpha) {
f << " " << ((int)rgba_geta(col));
}
f << "\n";
}
return true;

View File

@ -40,82 +40,137 @@ struct PalEntryWithIndexPredicate {
}
bool operator()(const PalEntryWithIndex& a, const PalEntryWithIndex& b) {
color_t c1 = a.color;
color_t c2 = b.color;
int value1 = 0, value2 = 0;
const color_t c1 = a.color;
const color_t c2 = b.color;
// Handle cases where, e.g., transparent yellow
// is visually indistinguishable from transparent
// black. Push 0 alpha toward index 0, regardless
// of sort order being ascending or descending.
const uint8_t a1 = rgba_geta(c1);
const uint8_t a2 = rgba_geta(c2);
if (a1 == 0 && a2 == 0) {
return true;
}
else if (a1 == 0) {
return true;
}
else if (a2 == 0) {
return false;
}
const uint8_t r1 = rgba_getr(c1);
const uint8_t g1 = rgba_getg(c1);
const uint8_t b1 = rgba_getb(c1);
const uint8_t r2 = rgba_getr(c2);
const uint8_t g2 = rgba_getg(c2);
const uint8_t b2 = rgba_getb(c2);
switch (channel) {
case SortPaletteBy::RED:
value1 = rgba_getr(c1);
value2 = rgba_getr(c2);
break;
return (ascending ? r1 < r2: r2 < r1);
case SortPaletteBy::GREEN:
value1 = rgba_getg(c1);
value2 = rgba_getg(c2);
break;
return (ascending ? g1 < g2: g2 < g1);
case SortPaletteBy::BLUE:
value1 = rgba_getb(c1);
value2 = rgba_getb(c2);
break;
return (ascending ? b1 < b2: b2 < b1);
case SortPaletteBy::ALPHA:
value1 = rgba_geta(c1);
value2 = rgba_geta(c2);
break;
return (ascending ? a1 < a2: a2 < a1);
case SortPaletteBy::HUE:
case SortPaletteBy::SATURATION:
case SortPaletteBy::VALUE: {
Hsv hsv1(Rgb(rgba_getr(c1),
rgba_getg(c1),
rgba_getb(c1)));
Hsv hsv2(Rgb(rgba_getr(c2),
rgba_getg(c2),
rgba_getb(c2)));
case SortPaletteBy::HUE: {
const Hsv hsv1(Rgb(r1, g1, b1));
const Hsv hsv2(Rgb(r2, g2, b2));
switch (channel) {
case SortPaletteBy::HUE:
value1 = hsv1.hueInt();
value2 = hsv2.hueInt();
break;
case SortPaletteBy::SATURATION:
value1 = hsv1.saturationInt();
value2 = hsv2.saturationInt();
break;
case SortPaletteBy::VALUE:
value1 = hsv1.valueInt();
value2 = hsv2.valueInt();
break;
default:
ASSERT(false);
break;
// When a color is desaturated, its hue
// is the quotient of division by zero.
// It is not zero, which is red.
const int sat1 = hsv1.saturationInt();
const int sat2 = hsv2.saturationInt();
if (sat1 == 0 && sat2 == 0) {
const int val1 = hsv1.valueInt();
const int val2 = hsv2.valueInt();
return (ascending ? val1 < val2: val2 < val1);
}
break;
else if (sat1 == 0) {
return ascending;
}
else if (sat2 == 0) {
return !ascending;
}
const int hue1 = hsv1.hueInt();
const int hue2 = hsv2.hueInt();
return (ascending ? hue1 < hue2: hue2 < hue1);
}
case SortPaletteBy::LIGHTNESS: {
value1 = (std::max(rgba_getr(c1), std::max(rgba_getg(c1), rgba_getb(c1))) +
std::min(rgba_getr(c1), std::min(rgba_getg(c1), rgba_getb(c1)))) / 2;
value2 = (std::max(rgba_getr(c2), std::max(rgba_getg(c2), rgba_getb(c2))) +
std::min(rgba_getr(c2), std::min(rgba_getg(c2), rgba_getb(c2)))) / 2;
break;
case SortPaletteBy::SATURATION: {
// This could be inlined with
// (max(r, g, b) - min(r, g, b)) / max(r, g, b)
// but (1.) there is already opportunity for
// confusion: HSV and HSL saturation share
// the same name but arise from different
// calculations; (2.) HSV components can
// almost never be compared in isolation.
const Hsv hsv1(Rgb(r1, g1, b1));
const Hsv hsv2(Rgb(r2, g2, b2));
const int sat1 = hsv1.saturationInt();
const int sat2 = hsv2.saturationInt();
if (sat1 == sat2) {
const int val1 = hsv1.valueInt();
const int val2 = hsv2.valueInt();
return (ascending ? val1 < val2: val2 < val1);
}
return (ascending ? sat1 < sat2: sat2 < sat1);
}
case SortPaletteBy::VALUE: {
const Hsv hsv1(Rgb(r1, g1, b1));
const Hsv hsv2(Rgb(r2, g2, b2));
const int val1 = hsv1.valueInt();
const int val2 = hsv2.valueInt();
if (val1 == val2) {
const int sat1 = hsv1.saturationInt();
const int sat2 = hsv2.saturationInt();
return (ascending ? sat1 < sat2: sat2 < sat1);
}
return (ascending ? val1 < val2: val2 < val1);
}
case SortPaletteBy::LUMA: {
value1 = rgb_luma(rgba_getr(c1), rgba_getg(c1), rgba_getb(c1));
value2 = rgb_luma(rgba_getr(c2), rgba_getg(c2), rgba_getb(c2));
break;
// Perceptual, or relative, luminance.
// Finds the square for fast approximation
// of 2.4 or 2.2 exponent needed to convert
// from gamma to linear. Assumes that the
// source for palette colors is sRGB.
const int lum1 = rgb_luma(r1 * r1, g1 * g1, b1 * b1);
const int lum2 = rgb_luma(r2 * r2, g2 * g2, b2 * b2);
return (ascending ? lum1 < lum2: lum2 < lum1);
}
case SortPaletteBy::LIGHTNESS: {
// HSL Lightness
const int mn1 = std::min(r1, std::min(g1, b1));
const int mx1 = std::max(r1, std::max(g1, b1));
const int light1 = (mn1 + mx1) / 2;
const int mn2 = std::min(r2, std::min(g2, b2));
const int mx2 = std::max(r2, std::max(g2, b2));
const int light2 = (mn2 + mx2) / 2;
return (ascending ? light1 < light2: light2 < light1);
}
default: {
ASSERT(false);
return false;
}
}
if (!ascending)
std::swap(value1, value2);
return (value1 < value2);
}
};