--User changes

-Add a palette editor.
 -Add support for reading .ugr/.gradient/.gradients palette files.
 -Allow toggling on spinners whose minimum value is not zero.
 -Allow toggling display of image, affines and grid.
 -Add new variations: cylinder2, circlesplit, tile_log, truchet_fill, waves2_radial.

--Bug fixes
 -cpow2 was wrong.
 -Palettes with rapid changes in color would produce slightly different outputs from Apo/Chaotica. This was due to a long standing bug from flam3.
 -Use exec() on Apple and show() on all other OSes for dialog boxes.
 -Trying to render a sequence with no frames would crash.
 -Selecting multiple xforms and rotating them would produce the wrong rotation.
 -Better handling when parsing flames using different encoding, such as unicode and UTF-8.
 -Switching between SP/DP didn't reselect the selected flame in the Library tab.

--Code changes
 -Make all types concerning palettes be floats, including PaletteTableWidgetItem.
 -PaletteTableWidgetItem is no longer templated because all palettes are float.
 -Include the source colors for user created gradients.
 -Change parallel_for() calls to work with very old versions of TBB which are lingering on some systems.
 -Split conditional out of accumulation loop on the CPU for better performance.
 -Vectorize summing when doing density filter for better performance.
 -Make all usage of palettes be of type float, double is pointless.
 -Allow palettes to reside in multiple folders, while ensuring only one of each name is added.
 -Refactor some palette path searching code.
 -Make ReadFile() throw and catch an exception if the file operation fails.
 -A little extra safety in foci and foci3D with a call to Zeps().
 -Cast to (real_t) in the OpenCL string for the w variation, which was having trouble compiling on Mac.
 -Fixing missing comma between paths in InitPaletteList().
 -Move Xml and PaletteList classes into cpp to shorten build times when working on them.
 -Remove default param values for IterOpenCLKernelCreator<T>::SharedDataIndexDefines in cpp file.
 -Change more NULL to nullptr.
This commit is contained in:
Person
2017-02-26 00:02:21 -08:00
parent 8a75d5d227
commit 8a4127d5d7
102 changed files with 242668 additions and 3713 deletions

View File

@ -53,6 +53,18 @@ static inline bool Contains(c& container, const T& val)
return std::find_if(container.begin(), container.end(), [&](const T & t) -> bool { return t == val; }) != container.end();
}
/// <summary>
/// Thin specialization for string because the compiler can't figure out the container template type
/// when passing string to the function above.
/// </summary>
/// <param name="str1">The string to call find() on</param>
/// <param name="str2">The string to search for</param>
/// <returns>True if str2 was present at least once, else false.</returns>
static bool Find(const string& str1, const string& str2)
{
return str1.find(str2) != string::npos;
}
/// <summary>
/// Thin wrapper around computing the total size of a vector.
/// </summary>
@ -284,16 +296,21 @@ static bool ReadFile(const char* filename, string& buf, bool nullTerminate = tru
{
try
{
ifstream ifs(filename, ios::binary | ios::ate);
auto pos = ifs.tellg();
buf.resize(pos + streampos(nullTerminate ? 1 : 0));
ifs.seekg(0, ios::beg);
ifs.read(&buf[0], pos);
ifstream ifs;
ifs.exceptions(ifstream::failbit);
ifs.open(filename, ios::binary | ios::ate);
if (nullTerminate)//Optionally NULL terminate if they want to treat it as a string.
buf[buf.size() - 1] = 0;
if (auto pos = ifs.tellg())//Ensure it exists and wasn't empty.
{
buf.resize(pos + streampos(nullTerminate ? 1 : 0));
ifs.seekg(0, ios::beg);
ifs.read(&buf[0], pos);
return true;
if (nullTerminate)//Optionally NULL terminate if they want to treat it as a string.
buf[buf.size() - 1] = 0;
return true;
}
}
catch (const std::exception& e)
{
@ -812,6 +829,18 @@ static inline T NormalizeDeg180(T angle)
return a;
}
/// <summary>
/// Determine whether the passed in string ends with the passed in suffix, case sensitive.
/// </summary>
/// <param name="str">The string to test</param>
/// <param name="suffix">The string to test for</param>
/// <returns>True if str ends with suffix, else false.</returns>
static bool EndsWith(const std::string& str, const std::string& suffix)
{
return str.size() >= suffix.size() &&
str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
}
/// <summary>
/// Return a lower case copy of a string.
/// </summary>
@ -867,21 +896,61 @@ static string Trim(const string& str, char ch = ' ')
}
/// <summary>
/// Return a copy of a file path string with the path portion removed.
/// Split a string into tokens and place them in a vector.
/// </summary>
/// <param name="str">The string to split</param>
/// <param name="del">The delimiter to split the string on. Note that only one character has to match, so this is a good way to use multiple delimiters</param>
/// <param name="removeEmpty">True to omit empty strings, else false to keep them.</param>
/// <returns>The vector containing the split tokens</returns>
static vector<std::string> Split(const string& str, const string& del, bool removeEmpty = false)
{
int current = 0;
int next = -1;
vector<string> vec;
do
{
current = next + 1;
next = int(str.find_first_of(del, current));
string ent(Trim(str.substr(current, next - current)));
if (!removeEmpty || ent.length() > 0)
vec.push_back(ent);
}
while (next != int(string::npos));
return vec;
}
/// <summary>
/// Return a copy of a file path string with the file portion removed.
/// </summary>
/// <param name="filename">The string to retrieve the path from</param>
/// <returns>The path portion of the string</returns>
static string GetPath(const string& filename)
{
const size_t lastSlash = filename.find_last_of("\\/");
if (std::string::npos != lastSlash)
return filename.substr(0, lastSlash + 1);
else
return filename;
}
/// <summary>
/// Return a copy of a file path string with the path portion removed.
/// </summary>
/// <param name="filename">The string to retrieve the filename from</param>
/// <returns>The filename portion of the string</returns>
static string GetFilename(const string& filename)
{
string s;
const size_t lastSlash = filename.find_last_of("\\/");
if (std::string::npos != lastSlash)
s = filename.substr(0, lastSlash + 1);
return filename.substr(lastSlash + 1, filename.size() - lastSlash);
else
s = "";
return s;
return filename;
}
/// <summary>