mirror of
https://github.com/aseprite/aseprite.git
synced 2025-04-02 13:20:12 +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")
|
message(FATAL_ERROR "Your Aseprite repository is incomplete, initialize submodules using:\n git submodule update --init --recursive")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# This required for KDE/Qt destop integration, which sets BUILD_SHARED_LIBS to
|
# This is required for KDE/Qt destop integration, which sets
|
||||||
# TRUE by default
|
# BUILD_SHARED_LIBS to TRUE by default
|
||||||
set(BUILD_SHARED_LIBS off)
|
set(BUILD_SHARED_LIBS off)
|
||||||
|
|
||||||
enable_testing()
|
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
|
## C++11
|
||||||
|
|
||||||
We are using some modern C++ (C++11, C++14, etc.) features, mainly:
|
We are using some modern C++ (C++11, C++14, etc.) features, mainly:
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "app/doc.h"
|
#include "app/doc.h"
|
||||||
#include "app/doc_event.h"
|
#include "app/doc_event.h"
|
||||||
#include "app/doc_observer.h"
|
#include "app/doc_observer.h"
|
||||||
|
#include "app/pref/preferences.h"
|
||||||
#include "doc/sprite.h"
|
#include "doc/sprite.h"
|
||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
@ -29,15 +30,23 @@ SetGridBounds::SetGridBounds(Sprite* sprite, const gfx::Rect& bounds)
|
|||||||
|
|
||||||
void SetGridBounds::onExecute()
|
void SetGridBounds::onExecute()
|
||||||
{
|
{
|
||||||
Sprite* spr = sprite();
|
setGrid(m_newBounds);
|
||||||
spr->setGridBounds(m_newBounds);
|
|
||||||
spr->incrementVersion();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetGridBounds::onUndo()
|
void SetGridBounds::onUndo()
|
||||||
|
{
|
||||||
|
setGrid(m_oldBounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetGridBounds::setGrid(const gfx::Rect& grid)
|
||||||
{
|
{
|
||||||
Sprite* spr = sprite();
|
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();
|
spr->incrementVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,8 @@ namespace cmd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void setGrid(const gfx::Rect& grid);
|
||||||
|
|
||||||
gfx::Rect m_oldBounds;
|
gfx::Rect m_oldBounds;
|
||||||
gfx::Rect m_newBounds;
|
gfx::Rect m_newBounds;
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
// Copyright (C) 2019-2021 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2015 David Capello
|
// Copyright (C) 2001-2015 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// 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);
|
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()
|
void SetPalette::onExecute()
|
||||||
@ -64,6 +71,7 @@ void SetPalette::onExecute()
|
|||||||
for (size_t i=0; i<m_newColors.size(); ++i)
|
for (size_t i=0; i<m_newColors.size(); ++i)
|
||||||
palette->setEntry(m_from+i, m_newColors[i]);
|
palette->setEntry(m_from+i, m_newColors[i]);
|
||||||
|
|
||||||
|
sprite->setTransparentColor(m_newTransparentIndex);
|
||||||
palette->incrementVersion();
|
palette->incrementVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,6 +84,7 @@ void SetPalette::onUndo()
|
|||||||
for (size_t i=0; i<m_oldColors.size(); ++i)
|
for (size_t i=0; i<m_oldColors.size(); ++i)
|
||||||
palette->setEntry(m_from+i, m_oldColors[i]);
|
palette->setEntry(m_from+i, m_oldColors[i]);
|
||||||
|
|
||||||
|
sprite->setTransparentColor(m_oldTransparentIndex);
|
||||||
palette->incrementVersion();
|
palette->incrementVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2019 Igara Studio S.A.
|
// Copyright (C) 2019-2021 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2015 David Capello
|
// Copyright (C) 2001-2015 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -45,6 +45,8 @@ namespace cmd {
|
|||||||
int m_from, m_to;
|
int m_from, m_to;
|
||||||
int m_oldNColors;
|
int m_oldNColors;
|
||||||
int m_newNColors;
|
int m_newNColors;
|
||||||
|
int m_oldTransparentIndex;
|
||||||
|
int m_newTransparentIndex;
|
||||||
std::vector<color_t> m_oldColors;
|
std::vector<color_t> m_oldColors;
|
||||||
std::vector<color_t> m_newColors;
|
std::vector<color_t> m_newColors;
|
||||||
};
|
};
|
||||||
|
@ -131,7 +131,6 @@ void GridSettingsCommand::onExecute(Context* context)
|
|||||||
tx.commit();
|
tx.commit();
|
||||||
|
|
||||||
auto& docPref = Preferences::instance().document(site.document());
|
auto& docPref = Preferences::instance().document(site.document());
|
||||||
docPref.grid.bounds(bounds);
|
|
||||||
if (!docPref.show.grid()) // Make grid visible
|
if (!docPref.show.grid()) // Make grid visible
|
||||||
docPref.show.grid(true);
|
docPref.show.grid(true);
|
||||||
}
|
}
|
||||||
|
@ -856,7 +856,9 @@ void ColorBar::onRemapPalButtonClick()
|
|||||||
}
|
}
|
||||||
|
|
||||||
color_t oldTransparent = sprite->transparentColor();
|
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)
|
if (oldTransparent != newTransparent)
|
||||||
tx(new cmd::SetTransparentColor(sprite, newTransparent));
|
tx(new cmd::SetTransparentColor(sprite, newTransparent));
|
||||||
|
|
||||||
|
@ -112,8 +112,8 @@ void UIContext::setActiveView(DocView* docView)
|
|||||||
else
|
else
|
||||||
current_editor = nullptr;
|
current_editor = nullptr;
|
||||||
|
|
||||||
mainWin->getPreviewEditor()->updateUsingEditor(current_editor);
|
|
||||||
mainWin->getTimeline()->updateUsingEditor(current_editor);
|
mainWin->getTimeline()->updateUsingEditor(current_editor);
|
||||||
|
mainWin->getPreviewEditor()->updateUsingEditor(current_editor);
|
||||||
|
|
||||||
// Change the image-type of color bar.
|
// Change the image-type of color bar.
|
||||||
ColorBar::instance()->setPixelFormat(app_get_current_pixel_format());
|
ColorBar::instance()->setPixelFormat(app_get_current_pixel_format());
|
||||||
|
@ -59,10 +59,10 @@ Palette* load_pal_file(const char *filename)
|
|||||||
if (line.empty())
|
if (line.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int r, g, b;
|
int r, g, b, a=255;
|
||||||
std::istringstream lineIn(line);
|
std::istringstream lineIn(line);
|
||||||
lineIn >> r >> g >> b;
|
lineIn >> r >> g >> b >> a;
|
||||||
pal->addEntry(rgba(r, g, b, 255));
|
pal->addEntry(rgba(r, g, b, a));
|
||||||
}
|
}
|
||||||
|
|
||||||
return pal.release();
|
return pal.release();
|
||||||
@ -77,11 +77,16 @@ bool save_pal_file(const Palette *pal, const char *filename)
|
|||||||
<< "0100\n"
|
<< "0100\n"
|
||||||
<< pal->size() << "\n";
|
<< pal->size() << "\n";
|
||||||
|
|
||||||
|
const bool hasAlpha = pal->hasAlpha();
|
||||||
for (int i=0; i<pal->size(); ++i) {
|
for (int i=0; i<pal->size(); ++i) {
|
||||||
uint32_t col = pal->getEntry(i);
|
uint32_t col = pal->getEntry(i);
|
||||||
f << ((int)rgba_getr(col)) << " "
|
f << ((int)rgba_getr(col)) << " "
|
||||||
<< ((int)rgba_getg(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;
|
return true;
|
||||||
|
@ -40,82 +40,137 @@ struct PalEntryWithIndexPredicate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool operator()(const PalEntryWithIndex& a, const PalEntryWithIndex& b) {
|
bool operator()(const PalEntryWithIndex& a, const PalEntryWithIndex& b) {
|
||||||
color_t c1 = a.color;
|
const color_t c1 = a.color;
|
||||||
color_t c2 = b.color;
|
const color_t c2 = b.color;
|
||||||
int value1 = 0, value2 = 0;
|
|
||||||
|
// 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) {
|
switch (channel) {
|
||||||
|
|
||||||
case SortPaletteBy::RED:
|
case SortPaletteBy::RED:
|
||||||
value1 = rgba_getr(c1);
|
return (ascending ? r1 < r2: r2 < r1);
|
||||||
value2 = rgba_getr(c2);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SortPaletteBy::GREEN:
|
case SortPaletteBy::GREEN:
|
||||||
value1 = rgba_getg(c1);
|
return (ascending ? g1 < g2: g2 < g1);
|
||||||
value2 = rgba_getg(c2);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SortPaletteBy::BLUE:
|
case SortPaletteBy::BLUE:
|
||||||
value1 = rgba_getb(c1);
|
return (ascending ? b1 < b2: b2 < b1);
|
||||||
value2 = rgba_getb(c2);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SortPaletteBy::ALPHA:
|
case SortPaletteBy::ALPHA:
|
||||||
value1 = rgba_geta(c1);
|
return (ascending ? a1 < a2: a2 < a1);
|
||||||
value2 = rgba_geta(c2);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SortPaletteBy::HUE:
|
case SortPaletteBy::HUE: {
|
||||||
case SortPaletteBy::SATURATION:
|
const Hsv hsv1(Rgb(r1, g1, b1));
|
||||||
case SortPaletteBy::VALUE: {
|
const Hsv hsv2(Rgb(r2, g2, b2));
|
||||||
Hsv hsv1(Rgb(rgba_getr(c1),
|
|
||||||
rgba_getg(c1),
|
|
||||||
rgba_getb(c1)));
|
|
||||||
Hsv hsv2(Rgb(rgba_getr(c2),
|
|
||||||
rgba_getg(c2),
|
|
||||||
rgba_getb(c2)));
|
|
||||||
|
|
||||||
switch (channel) {
|
// When a color is desaturated, its hue
|
||||||
case SortPaletteBy::HUE:
|
// is the quotient of division by zero.
|
||||||
value1 = hsv1.hueInt();
|
// It is not zero, which is red.
|
||||||
value2 = hsv2.hueInt();
|
const int sat1 = hsv1.saturationInt();
|
||||||
break;
|
const int sat2 = hsv2.saturationInt();
|
||||||
case SortPaletteBy::SATURATION:
|
|
||||||
value1 = hsv1.saturationInt();
|
if (sat1 == 0 && sat2 == 0) {
|
||||||
value2 = hsv2.saturationInt();
|
const int val1 = hsv1.valueInt();
|
||||||
break;
|
const int val2 = hsv2.valueInt();
|
||||||
case SortPaletteBy::VALUE:
|
return (ascending ? val1 < val2: val2 < val1);
|
||||||
value1 = hsv1.valueInt();
|
|
||||||
value2 = hsv2.valueInt();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ASSERT(false);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
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: {
|
case SortPaletteBy::SATURATION: {
|
||||||
value1 = (std::max(rgba_getr(c1), std::max(rgba_getg(c1), rgba_getb(c1))) +
|
// This could be inlined with
|
||||||
std::min(rgba_getr(c1), std::min(rgba_getg(c1), rgba_getb(c1)))) / 2;
|
// (max(r, g, b) - min(r, g, b)) / max(r, g, b)
|
||||||
value2 = (std::max(rgba_getr(c2), std::max(rgba_getg(c2), rgba_getb(c2))) +
|
// but (1.) there is already opportunity for
|
||||||
std::min(rgba_getr(c2), std::min(rgba_getg(c2), rgba_getb(c2)))) / 2;
|
// confusion: HSV and HSL saturation share
|
||||||
break;
|
// 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: {
|
case SortPaletteBy::LUMA: {
|
||||||
value1 = rgb_luma(rgba_getr(c1), rgba_getg(c1), rgba_getb(c1));
|
// Perceptual, or relative, luminance.
|
||||||
value2 = rgb_luma(rgba_getr(c2), rgba_getg(c2), rgba_getb(c2));
|
// Finds the square for fast approximation
|
||||||
break;
|
// 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