mirror of
https://github.com/aseprite/aseprite.git
synced 2025-04-01 01:20:25 +00:00
Merge branch 'main' into beta
This commit is contained in:
commit
adc9c109da
125
.clang-format
Normal file
125
.clang-format
Normal 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
|
||||
...
|
@ -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()
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,8 @@ namespace cmd {
|
||||
}
|
||||
|
||||
private:
|
||||
void setGrid(const gfx::Rect& grid);
|
||||
|
||||
gfx::Rect m_oldBounds;
|
||||
gfx::Rect m_newBounds;
|
||||
};
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user