mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-30 06:32:42 +00:00
Merge branch 'master' into tilemap-editor
This commit is contained in:
commit
7319309630
@ -1,4 +1,5 @@
|
||||
# Aseprite
|
||||
# Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
# Copyright (C) 2001-2018 David Capello
|
||||
|
||||
cmake_minimum_required(VERSION 3.4)
|
||||
@ -23,12 +24,8 @@ if(NOT CMAKE_BUILD_TYPE)
|
||||
FORCE)
|
||||
endif()
|
||||
|
||||
# Restrict configuration types to the selected build type.
|
||||
# Note: This needs to be done before the project command
|
||||
set(CMAKE_CONFIGURATION_TYPES "${CMAKE_BUILD_TYPE}" CACHE INTERNAL "internal")
|
||||
|
||||
set(CMAKE_USER_MAKE_RULES_OVERRIDE ${CMAKE_CURRENT_SOURCE_DIR}/cmake/c_flag_overrides.cmake)
|
||||
set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cxx_flag_overrides.cmake)
|
||||
set(CMAKE_USER_MAKE_RULES_OVERRIDE ${CMAKE_CURRENT_SOURCE_DIR}/laf/cmake/c_flag_overrides.cmake)
|
||||
set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX ${CMAKE_CURRENT_SOURCE_DIR}/laf/cmake/cxx_flag_overrides.cmake)
|
||||
|
||||
# Aseprite project
|
||||
project(aseprite C CXX)
|
||||
|
184
INSTALL.md
184
INSTALL.md
@ -12,19 +12,15 @@
|
||||
* [Issues with Retina displays](#issues-with-retina-displays)
|
||||
* [Linux details](#linux-details)
|
||||
* [Using shared third party libraries](#using-shared-third-party-libraries)
|
||||
* [Building Skia dependency](#building-skia-dependency)
|
||||
* [Skia on Windows](#skia-on-windows)
|
||||
* [Skia on macOS](#skia-on-macos)
|
||||
* [Skia on Linux](#skia-on-linux)
|
||||
|
||||
# Platforms
|
||||
|
||||
You should be able to compile Aseprite successfully on the following
|
||||
platforms:
|
||||
|
||||
* Windows 10 + [Visual Studio Community 2019 + Windows 10.0.17763.0 SDK](https://imgur.com/4Pq2Cbv)
|
||||
* macOS 10.14.4 Mojave + Xcode 10.2.1 + macOS 10.14 SDK
|
||||
* Linux + gcc 4.8 or clang 7.0
|
||||
* Windows 10 + [Visual Studio Community 2019 + Windows 10.0.18362.0 SDK](https://imgur.com/a/7zs51IT)
|
||||
* macOS 10.15.3 Mojave + Xcode 11.2.1 + macOS 10.15 SDK (older version might work)
|
||||
* Linux + gcc 9.2 or clang 9.0
|
||||
|
||||
# Get the source code
|
||||
|
||||
@ -54,32 +50,24 @@ To compile Aseprite you will need:
|
||||
|
||||
* The latest version of [CMake](https://cmake.org) (3.14 or greater)
|
||||
* [Ninja](https://ninja-build.org) build system
|
||||
* You will need a compiled version of the Skia library.
|
||||
Please check the details about [how to build Skia](#building-skia-dependency)
|
||||
on your platform.
|
||||
* And a compiled version of the `aseprite-m81` branch of
|
||||
the [Skia library](https://github.com/aseprite/skia#readme).
|
||||
There are [pre-built packages available](https://github.com/aseprite/skia/releases).
|
||||
You can get some extra information in
|
||||
the [*laf* dependencies](https://github.com/aseprite/laf#dependencies) page.
|
||||
|
||||
## Windows dependencies
|
||||
|
||||
First of all, you will need:
|
||||
|
||||
* Windows 10 (**we don't support cross-compiling and don't know if this would be possible**)
|
||||
* [Visual Studio Community 2019](https://visualstudio.microsoft.com/downloads/)
|
||||
* The [Desktop development with C++ item + Windows 10.0.17763.0 SDK](https://imgur.com/4Pq2Cbv)
|
||||
* The [Desktop development with C++ item + Windows 10.0.18362.0 SDK](https://imgur.com/a/7zs51IT)
|
||||
from the Visual Studio installer
|
||||
|
||||
You will need to [compile Skia](#skia-on-windows) before and then
|
||||
continue in the [Compiling](#compiling) section. Remember to check the
|
||||
[Windows details](#windows-details) section to know how to call
|
||||
`cmake` correctly.
|
||||
|
||||
## macOS dependencies
|
||||
|
||||
On macOS you will need macOS 10.14 SDK and Xcode 10.2.1 (older
|
||||
On macOS you will need macOS 10.15 SDK and Xcode 11.2.1 (older
|
||||
versions might work).
|
||||
|
||||
You must also compile [Skia](#skia-on-macos) before starting with the
|
||||
[compilation](#compiling).
|
||||
|
||||
## Linux dependencies
|
||||
|
||||
You will need the following dependencies on Ubuntu/Debian:
|
||||
@ -88,10 +76,7 @@ You will need the following dependencies on Ubuntu/Debian:
|
||||
|
||||
On Fedora:
|
||||
|
||||
sudo yum install -y gcc-c++ cmake ninja-build libX11-devel libXcursor-devel mesa-libGL-devel fontconfig-devel
|
||||
|
||||
You must also compile [Skia](#skia-on-linux) before starting with the
|
||||
[compilation](#compiling).
|
||||
sudo dnf install -y gcc-c++ cmake ninja-build libX11-devel libXcursor-devel mesa-libGL-devel fontconfig-devel
|
||||
|
||||
# Compiling
|
||||
|
||||
@ -109,7 +94,7 @@ You must also compile [Skia](#skia-on-linux) before starting with the
|
||||
2. Enter in the new directory and execute `cmake`:
|
||||
|
||||
cd C:\aseprite\build
|
||||
cmake -G Ninja ..
|
||||
cmake -G Ninja -DLAF_BACKEND=skia ..
|
||||
|
||||
Here `cmake` needs different options depending on your
|
||||
platform. You must check the details for
|
||||
@ -129,8 +114,7 @@ You must also compile [Skia](#skia-on-linux) before starting with the
|
||||
|
||||
## Windows details
|
||||
|
||||
After you've [compiled Skia](#skia-on-windows),
|
||||
open a [developer command prompt](https://docs.microsoft.com/en-us/dotnet/framework/tools/developer-command-prompt-for-vs)
|
||||
Open a [developer command prompt](https://docs.microsoft.com/en-us/dotnet/framework/tools/developer-command-prompt-for-vs)
|
||||
or in the command line (`cmd.exe`) call:
|
||||
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\VsDevCmd.bat" -arch=x64
|
||||
@ -140,16 +124,15 @@ And then
|
||||
cd aseprite
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DLAF_OS_BACKEND=skia -DSKIA_DIR=C:\deps\skia -DSKIA_OUT_DIR=C:\deps\skia\out\Release -G Ninja ..
|
||||
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DLAF_BACKEND=skia -DSKIA_DIR=C:\deps\skia -DSKIA_LIBRARY_DIR=C:\deps\skia\out\Release-x64 -G Ninja ..
|
||||
ninja aseprite
|
||||
|
||||
In this case, `C:\deps\skia` is the directory where Skia was compiled
|
||||
as described in [Skia on Windows](#skia-on-windows) section.
|
||||
or uncompressed.
|
||||
|
||||
## macOS details
|
||||
|
||||
After [compiling Skia](#skia-on-macos), you should run `cmake` with
|
||||
the following parameters and then `ninja`:
|
||||
Run `cmake` with the following parameters and then `ninja`:
|
||||
|
||||
cd aseprite
|
||||
mkdir build
|
||||
@ -158,19 +141,18 @@ the following parameters and then `ninja`:
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DCMAKE_OSX_ARCHITECTURES=x86_64 \
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.9 \
|
||||
-DCMAKE_OSX_SYSROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk \
|
||||
-DLAF_OS_BACKEND=skia \
|
||||
-DCMAKE_OSX_SYSROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk \
|
||||
-DLAF_BACKEND=skia \
|
||||
-DSKIA_DIR=$HOME/deps/skia \
|
||||
-DSKIA_OUT_DIR=$HOME/deps/skia/out/Release \
|
||||
-DSKIA_LIBRARY_DIR=$HOME/deps/skia/out/Release-x64 \
|
||||
-G Ninja \
|
||||
..
|
||||
ninja aseprite
|
||||
|
||||
In this case, `$HOME/deps/skia` is the directory where Skia was
|
||||
compiled as described in [Skia on macOS](#skia-on-macos) section.
|
||||
Make sure that `CMAKE_OSX_SYSROOT` is pointing to the correct SDK
|
||||
directory (in this case
|
||||
`/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk`),
|
||||
compiled or downloaded. Make sure that `CMAKE_OSX_SYSROOT` is
|
||||
pointing to the correct SDK directory (in this case
|
||||
`/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk`),
|
||||
but it could be different in your Mac.
|
||||
|
||||
### Issues with Retina displays
|
||||
@ -181,23 +163,22 @@ If you have a Retina display, check the following issue:
|
||||
|
||||
## Linux details
|
||||
|
||||
First you have to [compile Skia](#skia-on-linux), then you should run
|
||||
`cmake` with the following parameters and then `ninja`:
|
||||
Run `cmake` with the following parameters and then `ninja`:
|
||||
|
||||
cd aseprite
|
||||
mkdir build
|
||||
cd build
|
||||
cmake \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DLAF_OS_BACKEND=skia \
|
||||
-DLAF_BACKEND=skia \
|
||||
-DSKIA_DIR=$HOME/deps/skia \
|
||||
-DSKIA_OUT_DIR=$HOME/deps/skia/out/Release \
|
||||
-DSKIA_LIBRARY_DIR=$HOME/deps/skia/out/Release-x64 \
|
||||
-G Ninja \
|
||||
..
|
||||
ninja aseprite
|
||||
|
||||
In this case, `$HOME/deps/skia` is the directory where Skia was
|
||||
compiled as described in [Skia on Linux](#skia-on-linux) section.
|
||||
compiled or uncompressed.
|
||||
|
||||
# Using shared third party libraries
|
||||
|
||||
@ -208,116 +189,3 @@ configuring each `USE_SHARED_` option.
|
||||
After running `cmake -G`, you can edit `build/CMakeCache.txt` file,
|
||||
and enable the `USE_SHARED_` flag (set its value to `ON`) of the
|
||||
library that you want to be linked dynamically.
|
||||
|
||||
# Building Skia dependency
|
||||
|
||||
When you compile Aseprite with [Skia](https://skia.org) as back-end on
|
||||
Windows or macOS, you need to compile a specific version of Skia. In
|
||||
the following sections you will find straightforward steps to compile
|
||||
Skia.
|
||||
|
||||
You can always check the
|
||||
[official Skia instructions](https://skia.org/user/build) and select
|
||||
the OS you are building for. Aseprite uses the `aseprite-m71` Skia
|
||||
branch from `https://github.com/aseprite/skia`.
|
||||
|
||||
## Skia on Windows
|
||||
|
||||
Download
|
||||
[Google depot tools](https://storage.googleapis.com/chrome-infra/depot_tools.zip)
|
||||
and uncompress it in some place like `C:\deps\depot_tools`.
|
||||
|
||||
[It's recommended to compile Skia with Clang](https://github.com/google/skia/blob/master/site/user/build.md#a-note-on-software-backend-performance)
|
||||
to get better performance. So you will need to [download Clang](http://releases.llvm.org/8.0.0/LLVM-8.0.0-win64.exe),
|
||||
and install it on a folder like `C:\deps\llvm` (a folder without whitespaces).
|
||||
|
||||
Open a [developer command prompt](https://docs.microsoft.com/en-us/dotnet/framework/tools/developer-command-prompt-for-vs)
|
||||
or command line (`cmd.exe`) and call:
|
||||
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\VsDevCmd.bat" -arch=x64
|
||||
|
||||
Then:
|
||||
|
||||
set PATH=C:\deps\depot_tools;%PATH%
|
||||
cd C:\deps\depot_tools
|
||||
gclient sync
|
||||
|
||||
(The `gclient` command might print an error like
|
||||
`Error: client not configured; see 'gclient config'`.
|
||||
Just ignore it.)
|
||||
|
||||
cd C:\deps
|
||||
git clone -b aseprite-m71 https://github.com/aseprite/skia.git
|
||||
cd skia
|
||||
set GIT_EXECUTABLE=git.bat
|
||||
python tools/git-sync-deps
|
||||
|
||||
(The `tools/git-sync-deps` will take some minutes because it downloads
|
||||
a lot of packages, please wait and re-run the same command in case it
|
||||
fails.)
|
||||
|
||||
Finally, if you've downloaded Clang, use this command:
|
||||
|
||||
set PATH=C:\deps\llvm\bin;%PATH%
|
||||
gn gen out/Release --args="is_official_build=true skia_use_system_expat=false skia_use_system_libjpeg_turbo=false skia_use_system_libpng=false skia_use_system_libwebp=false skia_use_system_zlib=false target_cpu=""x64"" cc=""clang"" cxx=""clang++"" clang_win=""c:\deps\llvm"" win_vc=""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC"""
|
||||
ninja -C out/Release skia
|
||||
|
||||
If you haven't installed Clang, and want to compile Skia with MSVC
|
||||
(anyway it's not recommended because the performance penalty is too
|
||||
big), you can use the following commands instead:
|
||||
|
||||
gn gen out/Release --args="is_official_build=true skia_use_system_expat=false skia_use_system_libjpeg_turbo=false skia_use_system_libpng=false skia_use_system_libwebp=false skia_use_system_zlib=false target_cpu=""x64"" win_vc=""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC"""
|
||||
ninja -C out/Release skia
|
||||
|
||||
More information about these steps in the
|
||||
[official Skia documentation](https://skia.org/user/build).
|
||||
|
||||
## Skia on macOS
|
||||
|
||||
These steps will create a `deps` folder in your home directory with a
|
||||
couple of subdirectories needed to build Skia (you can change the
|
||||
`$HOME/deps` with other directory). Some of these commands will take
|
||||
several minutes to finish:
|
||||
|
||||
mkdir $HOME/deps
|
||||
cd $HOME/deps
|
||||
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
git clone -b aseprite-m71 https://github.com/aseprite/skia.git
|
||||
export PATH="${PWD}/depot_tools:${PATH}"
|
||||
cd skia
|
||||
python tools/git-sync-deps
|
||||
gn gen out/Release --args="is_official_build=true skia_use_system_expat=false skia_use_system_icu=false skia_use_libjpeg_turbo=false skia_use_system_libpng=false skia_use_system_libwebp=false skia_use_system_zlib=false extra_cflags_cc=[\"-frtti\"]"
|
||||
ninja -C out/Release skia
|
||||
|
||||
After this you should have all Skia libraries compiled. When you
|
||||
[compile Aseprite](#compiling), remember to add
|
||||
`-DSKIA_DIR=$HOME/deps/skia` parameter to your `cmake` call as
|
||||
described in the [macOS details](#macos-details) section.
|
||||
|
||||
More information about these steps in the
|
||||
[official Skia documentation](https://skia.org/user/build).
|
||||
|
||||
## Skia on Linux
|
||||
|
||||
These steps will create a `deps` folder in your home directory with a
|
||||
couple of subdirectories needed to build Skia (you can change the
|
||||
`$HOME/deps` with other directory). Some of these commands will take
|
||||
several minutes to finish:
|
||||
|
||||
mkdir $HOME/deps
|
||||
cd $HOME/deps
|
||||
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
git clone -b aseprite-m71 https://github.com/aseprite/skia.git
|
||||
export PATH="${PWD}/depot_tools:${PATH}"
|
||||
cd skia
|
||||
python tools/git-sync-deps
|
||||
gn gen out/Release --args="is_debug=false is_official_build=true skia_use_system_expat=false skia_use_system_icu=false skia_use_system_libjpeg_turbo=false skia_use_system_libpng=false skia_use_system_libwebp=false skia_use_system_zlib=false"
|
||||
ninja -C out/Release skia
|
||||
|
||||
After this you should have all Skia libraries compiled. When you
|
||||
[compile Aseprite](#compiling), remember to add
|
||||
`-DSKIA_DIR=$HOME/deps/skia` parameter to your `cmake` call as
|
||||
described in the [Linux details](#linux-details) section.
|
||||
|
||||
More information about these steps in the
|
||||
[official Skia documentation](https://skia.org/user/build).
|
||||
|
@ -10,10 +10,10 @@
|
||||
**Aseprite** is a program to create animated sprites. Its main
|
||||
features are:
|
||||
|
||||
* Sprites are composed by [**layers** & **frames**](http://www.aseprite.org/docs/timeline/) (as separated concepts).
|
||||
* Sprites are composed of [**layers** & **frames**](http://www.aseprite.org/docs/timeline/) (as separated concepts).
|
||||
* Supported [color modes](http://www.aseprite.org/docs/color/): **RGBA**, **Indexed** (palettes up to 256
|
||||
colors), and Grayscale.
|
||||
* Load/save sequence of **PNG** files and **GIF** animations (and
|
||||
* Load/save a sequence of **PNG** files and **GIF** animations (and
|
||||
FLC, FLI, JPG, BMP, PCX, TGA).
|
||||
* Export/import animations to/from **Sprite Sheets**.
|
||||
* **Tiled** drawing mode, useful to draw **patterns** and textures.
|
||||
@ -64,12 +64,12 @@ Aseprite includes color palettes created by:
|
||||
|
||||
* [Richard "DawnBringer" Fhager](http://pixeljoint.com/p/23821.htm), [16 colors](http://pixeljoint.com/forum/forum_posts.asp?TID=12795), [32 colors](http://pixeljoint.com/forum/forum_posts.asp?TID=16247).
|
||||
* [Arne Niklas Jansson](http://androidarts.com/), [16 colors](http://androidarts.com/palette/16pal.htm), [32 colors](http://wayofthepixel.net/index.php?topic=15824.msg144494).
|
||||
* [ENDESGA Studios](https://twitter.com/ENDESGA), [EDG16 and EDG32](https://forums.tigsource.com/index.php?topic=46126.msg1279124#msg1279124), and [other palettes](https://twitter.com/ENDESGA/status/865812366931353600)
|
||||
* [ENDESGA Studios](https://twitter.com/ENDESGA), [EDG16 and EDG32](https://forums.tigsource.com/index.php?topic=46126.msg1279124#msg1279124), and [other palettes](https://twitter.com/ENDESGA/status/865812366931353600).
|
||||
* [Hyohnoo Games](https://twitter.com/Hyohnoo), [mail24](https://twitter.com/Hyohnoo/status/797472587974639616) palette.
|
||||
* [Davit Masia](https://twitter.com/DavitMasia), [matriax8c](https://twitter.com/DavitMasia/status/834862452164612096) palette.
|
||||
* [Javier Guerrero](https://twitter.com/Xavier_Gd), [nyx8](https://twitter.com/Xavier_Gd/status/868519467864686594) palette.
|
||||
* [Adigun A. Polack](https://twitter.com/adigunpolack), [AAP-64](http://pixeljoint.com/pixelart/119466.htm), [AAP-Splendor128](http://pixeljoint.com/pixelart/120714.htm), [SimpleJPC-16](http://pixeljoint.com/pixelart/119844.htm), and [AAP-Micro12](http://pixeljoint.com/pixelart/121151.htm) palette.
|
||||
* [PineTreePizza](https://twitter.com/PineTreePizza), [Rosy-42](https://twitter.com/PineTreePizza/status/1006536191955623938) palette
|
||||
* [PineTreePizza](https://twitter.com/PineTreePizza), [Rosy-42](https://twitter.com/PineTreePizza/status/1006536191955623938) palette.
|
||||
|
||||
It tries to replicate some pixel-art algorithms:
|
||||
|
||||
|
@ -35,38 +35,15 @@ include(FindPkgConfig)
|
||||
pkg_check_modules(PC_HARFBUZZ harfbuzz>=0.9.7)
|
||||
|
||||
find_path(HARFBUZZ_INCLUDE_DIRS NAMES hb.h
|
||||
HINTS ${PC_HARFBUZZ_INCLUDE_DIRS} ${PC_HARFBUZZ_INCLUDEDIR}
|
||||
)
|
||||
HINTS ${PC_HARFBUZZ_INCLUDE_DIRS} ${PC_HARFBUZZ_INCLUDEDIR})
|
||||
|
||||
find_library(HARFBUZZ_LIBRARIES NAMES harfbuzz
|
||||
HINTS ${PC_HARFBUZZ_LIBRARY_DIRS} ${PC_HARFBUZZ_LIBDIR}
|
||||
)
|
||||
|
||||
# HarfBuzz 0.9.18 split ICU support into a separate harfbuzz-icu library.
|
||||
if ("${PC_HARFBUZZ_VERSION}" VERSION_GREATER "0.9.17")
|
||||
if (HarfBuzz_FIND_REQUIRED)
|
||||
set(_HARFBUZZ_REQUIRED REQUIRED)
|
||||
else ()
|
||||
set(_HARFBUZZ_REQUIRED "")
|
||||
endif ()
|
||||
pkg_check_modules(PC_HARFBUZZ_ICU harfbuzz-icu>=0.9.18 ${_HARFBUZZ_REQUIRED})
|
||||
find_library(HARFBUZZ_ICU_LIBRARIES NAMES harfbuzz-icu
|
||||
HINTS ${PC_HARFBUZZ_ICU_LIBRARY_DIRS} ${PC_HARFBUZZ_ICU_LIBDIR}
|
||||
)
|
||||
if (HARFBUZZ_ICU_LIBRARIES)
|
||||
list(APPEND HARFBUZZ_LIBRARIES "${HARFBUZZ_ICU_LIBRARIES}")
|
||||
endif ()
|
||||
set(_HARFBUZZ_EXTRA_REQUIRED_VAR "HARFBUZZ_ICU_LIBRARIES")
|
||||
else ()
|
||||
set(_HARFBUZZ_EXTRA_REQUIRED_VAR "")
|
||||
endif ()
|
||||
HINTS ${PC_HARFBUZZ_LIBRARY_DIRS} ${PC_HARFBUZZ_LIBDIR})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(HarfBuzz DEFAULT_MSG HARFBUZZ_INCLUDE_DIRS
|
||||
HARFBUZZ_LIBRARIES ${_HARFBUZZ_EXTRA_REQUIRED_VAR})
|
||||
HARFBUZZ_LIBRARIES)
|
||||
|
||||
mark_as_advanced(
|
||||
HARFBUZZ_ICU_LIBRARIES
|
||||
HARFBUZZ_INCLUDE_DIRS
|
||||
HARFBUZZ_LIBRARIES
|
||||
)
|
||||
HARFBUZZ_LIBRARIES)
|
||||
|
@ -1,6 +0,0 @@
|
||||
if(MSVC)
|
||||
set(CMAKE_C_FLAGS_DEBUG_INIT "/D_DEBUG /MTd /Zi /Ob0 /Od /RTC1")
|
||||
set(CMAKE_C_FLAGS_MINSIZEREL_INIT "/MT /O1 /Ob1 /D NDEBUG")
|
||||
set(CMAKE_C_FLAGS_RELEASE_INIT "/MT /O2 /Ob2 /D NDEBUG")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "/MT /Zi /O2 /Ob1 /D NDEBUG")
|
||||
endif()
|
@ -1,6 +0,0 @@
|
||||
if(MSVC)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG_INIT "/D_DEBUG /MTd /Zi /Ob0 /Od /RTC1")
|
||||
set(CMAKE_CXX_FLAGS_MINSIZEREL_INIT "/MT /O1 /Ob1 /D NDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE_INIT "/MT /O2 /Ob2 /D NDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "/MT /Zi /O2 /Ob1 /D NDEBUG")
|
||||
endif()
|
@ -2,7 +2,7 @@
|
||||
<!-- Aseprite -->
|
||||
<!-- Copyright (C) 2018-2020 Igara Studio S.A. -->
|
||||
<!-- Copyright (C) 2001-2018 David Capello -->
|
||||
<gui version="1.3-dev">
|
||||
<gui>
|
||||
<!-- Keyboard shortcuts -->
|
||||
<keyboard version="1">
|
||||
|
||||
|
2
laf
2
laf
@ -1 +1 @@
|
||||
Subproject commit 60b2e83ce159a79368141c5386a764e16ede0c27
|
||||
Subproject commit 98506341d68a318f4916a891ab12351a5db05f98
|
@ -1,5 +1,5 @@
|
||||
# Aseprite
|
||||
# Copyright (C) 2019 Igara Studio S.A.
|
||||
# Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
# Copyright (C) 2001-2018 David Capello
|
||||
|
||||
######################################################################
|
||||
@ -37,13 +37,6 @@ if(WIN32)
|
||||
include_directories(..)
|
||||
endif()
|
||||
|
||||
######################################################################
|
||||
# Custom Aseprite website (for testing server-side)
|
||||
|
||||
if(NOT "${CUSTOM_WEBSITE_URL}" STREQUAL "")
|
||||
add_definitions(-DCUSTOM_WEBSITE_URL="${CUSTOM_WEBSITE_URL}")
|
||||
endif()
|
||||
|
||||
######################################################################
|
||||
# With static libcurl
|
||||
|
||||
@ -106,6 +99,7 @@ add_subdirectory(flic)
|
||||
add_subdirectory(render)
|
||||
add_subdirectory(dio)
|
||||
add_subdirectory(ui)
|
||||
add_subdirectory(ver)
|
||||
|
||||
if(REQUIRE_CURL)
|
||||
add_subdirectory(net)
|
||||
@ -182,6 +176,7 @@ if(ENABLE_ASEPRITE_EXE)
|
||||
if(WIN32 AND ENABLE_UI)
|
||||
set_target_properties(aseprite PROPERTIES WIN32_EXECUTABLE true)
|
||||
endif()
|
||||
set_target_properties(aseprite PROPERTIES LINK_FLAGS "${LAF_BACKEND_LINK_FLAGS}")
|
||||
target_link_libraries(aseprite app-lib)
|
||||
add_dependencies(aseprite copy_data)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Aseprite
|
||||
# Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
# Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
# Copyright (C) 2001-2018 David Capello
|
||||
|
||||
# Generate a ui::Widget for each widget in a XML file
|
||||
@ -305,7 +305,6 @@ if(ENABLE_UI)
|
||||
modules/editors.cpp
|
||||
modules/gfx.cpp
|
||||
modules/gui.cpp
|
||||
send_crash.cpp
|
||||
ui/app_menuitem.cpp
|
||||
ui/backup_indicator.cpp
|
||||
ui/browser_view.cpp
|
||||
@ -585,6 +584,7 @@ add_library(app-lib
|
||||
res/resources_loader.cpp
|
||||
resource_finder.cpp
|
||||
restore_visible_layers.cpp
|
||||
send_crash.cpp
|
||||
shade.cpp
|
||||
site.cpp
|
||||
snap_to_grid.cpp
|
||||
@ -629,6 +629,10 @@ add_library(app-lib
|
||||
${scripting_files}
|
||||
${generated_files})
|
||||
|
||||
if(TARGET generated_version)
|
||||
add_dependencies(app-lib generated_version)
|
||||
endif()
|
||||
|
||||
target_link_libraries(app-lib
|
||||
laf-base
|
||||
cfg-lib
|
||||
@ -643,6 +647,7 @@ target_link_libraries(app-lib
|
||||
laf-ft
|
||||
laf-os
|
||||
ui-lib
|
||||
ver-lib
|
||||
undo
|
||||
${CMARK_LIBRARIES}
|
||||
${TINYXML_LIBRARY}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -67,6 +67,7 @@
|
||||
#include "render/render.h"
|
||||
#include "ui/intern.h"
|
||||
#include "ui/ui.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
@ -514,7 +515,7 @@ App::~App()
|
||||
// no re-throw
|
||||
}
|
||||
catch (...) {
|
||||
os::error_message("Error closing " PACKAGE ".\n(uncaught exception)");
|
||||
os::error_message("Error closing the program.\n(uncaught exception)");
|
||||
|
||||
// no re-throw
|
||||
}
|
||||
@ -606,7 +607,8 @@ crash::DataRecovery* App::dataRecovery() const
|
||||
#ifdef ENABLE_UI
|
||||
void App::showNotification(INotificationDelegate* del)
|
||||
{
|
||||
m_mainWindow->showNotification(del);
|
||||
if (m_mainWindow)
|
||||
m_mainWindow->showNotification(del);
|
||||
}
|
||||
|
||||
void App::showBackupNotification(bool state)
|
||||
@ -625,7 +627,7 @@ void App::showBackupNotification(bool state)
|
||||
|
||||
void App::updateDisplayTitleBar()
|
||||
{
|
||||
std::string defaultTitle = PACKAGE " v" VERSION;
|
||||
std::string defaultTitle = fmt::format("{} v{}", get_app_name(), get_app_version());
|
||||
std::string title;
|
||||
|
||||
DocView* docView = UIContext::instance()->activeView();
|
||||
@ -636,7 +638,7 @@ void App::updateDisplayTitleBar()
|
||||
}
|
||||
|
||||
title += defaultTitle;
|
||||
os::instance()->defaultDisplay()->setTitleBar(title);
|
||||
os::instance()->defaultDisplay()->setTitle(title);
|
||||
}
|
||||
|
||||
InputChain& App::inputChain()
|
||||
@ -709,18 +711,4 @@ int app_get_color_to_clear_layer(Layer* layer)
|
||||
return color_utils::color_for_layer(color, layer);
|
||||
}
|
||||
|
||||
std::string memory_dump_filename()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
static const char* kDefaultCrashName = PACKAGE "-crash-" VERSION ".dmp";
|
||||
|
||||
app::ResourceFinder rf;
|
||||
rf.includeUserDir(kDefaultCrashName);
|
||||
return rf.getFirstOrCreateDefault();
|
||||
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -117,6 +117,9 @@ namespace app {
|
||||
script::Engine* scriptEngine() { return m_engine.get(); }
|
||||
#endif
|
||||
|
||||
const std::string& memoryDumpFilename() const { return m_memoryDumpFilename; }
|
||||
void memoryDumpFilename(const std::string& fn) { m_memoryDumpFilename = fn; }
|
||||
|
||||
// App Signals
|
||||
obs::signal<void()> Exit;
|
||||
obs::signal<void()> PaletteChange;
|
||||
@ -145,13 +148,16 @@ namespace app {
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
std::unique_ptr<script::Engine> m_engine;
|
||||
#endif
|
||||
|
||||
// Set the memory dump filename to show in the Preferences dialog
|
||||
// or the "send crash" dialog. It's set by the SendCrash class.
|
||||
std::string m_memoryDumpFilename;
|
||||
};
|
||||
|
||||
void app_refresh_screen();
|
||||
void app_rebuild_documents_tabs();
|
||||
PixelFormat app_get_current_pixel_format();
|
||||
int app_get_color_to_clear_layer(doc::Layer* layer);
|
||||
std::string memory_dump_filename();
|
||||
|
||||
} // namespace app
|
||||
|
||||
|
@ -29,9 +29,11 @@
|
||||
#include "base/bind.h"
|
||||
#include "base/fs.h"
|
||||
#include "base/string.h"
|
||||
#include "fmt/format.h"
|
||||
#include "os/menus.h"
|
||||
#include "os/system.h"
|
||||
#include "ui/ui.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
#include "tinyxml.h"
|
||||
|
||||
@ -337,12 +339,6 @@ void AppMenus::reload()
|
||||
|
||||
m_rootMenu.reset(loadMenuById(handle, "main_menu"));
|
||||
|
||||
#if _DEBUG
|
||||
// Add a warning element because the user is not using the last well-known gui.xml file.
|
||||
if (GuiXml::instance()->version() != VERSION)
|
||||
m_rootMenu->insertChild(0, createInvalidVersionMenuitem());
|
||||
#endif
|
||||
|
||||
LOG("MENU: Main menu loaded.\n");
|
||||
|
||||
m_tabPopupMenu.reset(loadMenuById(handle, "tab_popup_menu"));
|
||||
@ -633,20 +629,6 @@ Widget* AppMenus::convertXmlelemToMenuitem(TiXmlElement* elem)
|
||||
return menuitem;
|
||||
}
|
||||
|
||||
Widget* AppMenus::createInvalidVersionMenuitem()
|
||||
{
|
||||
AppMenuItem* menuitem = new AppMenuItem("WARNING!");
|
||||
Menu* subMenu = new Menu();
|
||||
subMenu->addChild(new AppMenuItem(PACKAGE " is using a customized gui.xml (maybe from your HOME directory)."));
|
||||
subMenu->addChild(new AppMenuItem("You should update your customized gui.xml file to the new version to get"));
|
||||
subMenu->addChild(new AppMenuItem("the latest commands available."));
|
||||
subMenu->addChild(new MenuSeparator);
|
||||
subMenu->addChild(new AppMenuItem("You can bypass this validation adding the correct version"));
|
||||
subMenu->addChild(new AppMenuItem("number in <gui version=\"" VERSION "\"> element."));
|
||||
menuitem->setSubmenu(subMenu);
|
||||
return menuitem;
|
||||
}
|
||||
|
||||
void AppMenus::applyShortcutToMenuitemsWithCommand(Command* command,
|
||||
const Params& params,
|
||||
const KeyPtr& key)
|
||||
@ -732,7 +714,7 @@ void AppMenus::createNativeMenus()
|
||||
|
||||
#ifdef __APPLE__ // Create default macOS app menus (App ... Window)
|
||||
{
|
||||
os::MenuItemInfo about("About " PACKAGE);
|
||||
os::MenuItemInfo about(fmt::format("About {}", get_app_name()));
|
||||
auto native = get_native_shortcut_for_command(CommandId::About());
|
||||
about.shortcut = native.shortcut;
|
||||
about.execute = [native]{
|
||||
@ -758,10 +740,10 @@ void AppMenus::createNativeMenus()
|
||||
item->setEnabled(can_call_global_shortcut(&native));
|
||||
};
|
||||
|
||||
os::MenuItemInfo hide("Hide " PACKAGE, os::MenuItemInfo::Hide);
|
||||
os::MenuItemInfo hide(fmt::format("Hide {}", get_app_name()), os::MenuItemInfo::Hide);
|
||||
hide.shortcut = os::Shortcut('h', os::kKeyCmdModifier);
|
||||
|
||||
os::MenuItemInfo quit("Quit " PACKAGE, os::MenuItemInfo::Quit);
|
||||
os::MenuItemInfo quit(fmt::format("Quit {}", get_app_name()), os::MenuItemInfo::Quit);
|
||||
quit.shortcut = os::Shortcut('q', os::kKeyCmdModifier);
|
||||
|
||||
os::Menu* appMenu = menus->createMenu();
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -69,7 +69,6 @@ namespace app {
|
||||
Menu* loadMenuById(TiXmlHandle& handle, const char *id);
|
||||
Menu* convertXmlelemToMenu(TiXmlElement* elem);
|
||||
Widget* convertXmlelemToMenuitem(TiXmlElement* elem);
|
||||
Widget* createInvalidVersionMenuitem();
|
||||
void applyShortcutToMenuitemsWithCommand(Menu* menu, Command* command, const Params& params,
|
||||
const KeyPtr& key);
|
||||
void syncNativeMenuItemKeyShortcuts(Menu* menu);
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -19,6 +20,7 @@
|
||||
#include "base/launcher.h"
|
||||
#include "base/replace_string.h"
|
||||
#include "base/version.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
#include <ctime>
|
||||
#include <sstream>
|
||||
@ -202,7 +204,7 @@ void CheckUpdateThreadLauncher::checkForUpdates()
|
||||
|
||||
void CheckUpdateThreadLauncher::showUI()
|
||||
{
|
||||
std::string localVersionStr = VERSION;
|
||||
std::string localVersionStr = get_app_version();
|
||||
base::replace_string(localVersionStr, "-x64", "");
|
||||
bool newVer = false;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2016-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -26,6 +26,7 @@
|
||||
#include "doc/slice.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/tag.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
#include "app/app.h"
|
||||
@ -40,18 +41,20 @@ namespace app {
|
||||
void DefaultCliDelegate::showHelp(const AppOptions& options)
|
||||
{
|
||||
std::cout
|
||||
<< PACKAGE << " v" << VERSION << " | A pixel art program\n" << COPYRIGHT
|
||||
<< get_app_name() << " v" << get_app_version()
|
||||
<< " | A pixel art program\n"
|
||||
<< get_app_copyright()
|
||||
<< "\n\nUsage:\n"
|
||||
<< " " << options.exeName() << " [OPTIONS] [FILES]...\n\n"
|
||||
<< "Options:\n"
|
||||
<< options.programOptions()
|
||||
<< "\nFind more information in " << PACKAGE
|
||||
<< " web site: " << WEBSITE << "\n\n";
|
||||
<< "\nFind more information in " << get_app_name()
|
||||
<< " web site: " << get_app_url() << "\n\n";
|
||||
}
|
||||
|
||||
void DefaultCliDelegate::showVersion()
|
||||
{
|
||||
std::cout << PACKAGE << ' ' << VERSION << '\n';
|
||||
std::cout << get_app_name() << ' ' << get_app_version() << '\n';
|
||||
}
|
||||
|
||||
void DefaultCliDelegate::afterOpenFile(const CliOpenFile& cof)
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2016-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -19,6 +19,8 @@
|
||||
#include "base/fs.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "fmt/format.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
@ -27,12 +29,12 @@ namespace app {
|
||||
|
||||
void PreviewCliDelegate::showHelp(const AppOptions& options)
|
||||
{
|
||||
std::cout << "- Show " PACKAGE " CLI usage\n";
|
||||
std::cout << fmt::format("- Show {} CLI usage\n", get_app_name());
|
||||
}
|
||||
|
||||
void PreviewCliDelegate::showVersion()
|
||||
{
|
||||
std::cout << "- Show " PACKAGE " version\n";
|
||||
std::cout << fmt::format("- Show {} version\n", get_app_name());
|
||||
}
|
||||
|
||||
void PreviewCliDelegate::uiMode()
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -22,8 +22,6 @@ namespace app {
|
||||
ClosedDocs::ClosedDocs(const Preferences& pref)
|
||||
: m_done(false)
|
||||
{
|
||||
CLOSEDOC_TRACE("CLOSEDOC: Init");
|
||||
|
||||
if (pref.general.dataRecovery())
|
||||
m_dataRecoveryPeriodMSecs = int(1000.0*60.0*pref.general.dataRecoveryPeriod());
|
||||
else
|
||||
@ -33,6 +31,10 @@ ClosedDocs::ClosedDocs(const Preferences& pref)
|
||||
m_keepClosedDocAliveForMSecs = int(1000.0*60.0*pref.general.keepClosedSpriteOnMemoryFor());
|
||||
else
|
||||
m_keepClosedDocAliveForMSecs = 0;
|
||||
|
||||
CLOSEDOC_TRACE("CLOSEDOC: Init",
|
||||
"dataRecoveryPeriod", m_dataRecoveryPeriodMSecs,
|
||||
"keepClosedDocs", m_keepClosedDocAliveForMSecs);
|
||||
}
|
||||
|
||||
ClosedDocs::~ClosedDocs()
|
||||
@ -123,15 +125,20 @@ void ClosedDocs::backgroundThread()
|
||||
|
||||
for (auto it=m_docs.begin(); it != m_docs.end(); ) {
|
||||
const ClosedDoc& closedDoc = *it;
|
||||
auto doc = closedDoc.doc;
|
||||
|
||||
base::tick_t diff = now - closedDoc.timestamp;
|
||||
if (diff >= m_keepClosedDocAliveForMSecs) {
|
||||
if (m_dataRecoveryPeriodMSecs == 0 ||
|
||||
closedDoc.doc->isFullyBackedUp()) {
|
||||
if (// If we backup process is disabled
|
||||
m_dataRecoveryPeriodMSecs == 0 ||
|
||||
// Or this document doesn't need a backup (e.g. an unmodified document)
|
||||
!doc->needsBackup() ||
|
||||
// Or the document already has the backup done
|
||||
doc->isFullyBackedUp()) {
|
||||
// Finally delete the document (this is the place where we
|
||||
// delete all documents created/loaded by the user)
|
||||
CLOSEDOC_TRACE("CLOSEDOC: [BG] Delete doc", closedDoc.doc);
|
||||
delete closedDoc.doc;
|
||||
CLOSEDOC_TRACE("CLOSEDOC: [BG] Delete doc", doc);
|
||||
delete doc;
|
||||
it = m_docs.erase(it);
|
||||
}
|
||||
else {
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -13,6 +14,8 @@
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/ui/main_window.h"
|
||||
#include "base/bind.h"
|
||||
#include "fmt/format.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
#include "about.xml.h"
|
||||
|
||||
@ -36,7 +39,7 @@ AboutCommand::AboutCommand()
|
||||
void AboutCommand::onExecute(Context* context)
|
||||
{
|
||||
gen::About window;
|
||||
window.title()->setText(PACKAGE " v" VERSION);
|
||||
window.title()->setText(fmt::format("{} v{}", get_app_name(), get_app_version()));
|
||||
window.licenses()->Click.connect(
|
||||
[&window]{
|
||||
window.closeWindow(nullptr);
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -12,6 +13,7 @@
|
||||
#include "app/commands/params.h"
|
||||
#include "app/launcher.h"
|
||||
#include "base/fs.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
@ -42,7 +44,7 @@ void LaunchCommand::onLoadParams(const Params& params)
|
||||
m_path = params.get("path");
|
||||
|
||||
if (m_type == Url && !m_path.empty() && m_path[0] == '/') {
|
||||
m_path = WEBSITE + m_path.substr(1);
|
||||
m_path = std::string(get_app_url()) + m_path.substr(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "base/bind.h"
|
||||
#include "base/chrono.h"
|
||||
#include "base/convert_to.h"
|
||||
#include "base/scoped_value.h"
|
||||
#include "doc/image.h"
|
||||
#include "doc/mask.h"
|
||||
#include "doc/sprite.h"
|
||||
@ -70,11 +71,11 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
Window* m_window; // TODO we cannot use a std::unique_ptr because clone() needs a copy ctor
|
||||
ColorButton* m_buttonColor;
|
||||
CheckBox* m_checkPreview;
|
||||
Slider* m_sliderTolerance;
|
||||
SelModeField* m_selMode;
|
||||
Window* m_window = nullptr;
|
||||
ColorButton* m_buttonColor = nullptr;
|
||||
CheckBox* m_checkPreview = nullptr;
|
||||
Slider* m_sliderTolerance = nullptr;
|
||||
SelModeField* m_selMode = nullptr;
|
||||
};
|
||||
|
||||
MaskByColorCommand::MaskByColorCommand()
|
||||
@ -91,6 +92,8 @@ bool MaskByColorCommand::onEnabled(Context* context)
|
||||
|
||||
void MaskByColorCommand::onExecute(Context* context)
|
||||
{
|
||||
ASSERT(!m_window);
|
||||
|
||||
const ContextReader reader(context);
|
||||
const Sprite* sprite = reader.sprite();
|
||||
|
||||
@ -102,7 +105,8 @@ void MaskByColorCommand::onExecute(Context* context)
|
||||
if (!image)
|
||||
return;
|
||||
|
||||
m_window = new Window(Window::WithTitleBar, "Mask by Color");
|
||||
std::unique_ptr<Window> win(new Window(Window::WithTitleBar, "Mask by Color"));
|
||||
base::ScopedValue<Window*> setWindow(m_window, win.get(), nullptr);
|
||||
TooltipManager* tooltipManager = new TooltipManager();
|
||||
m_window->addChild(tooltipManager);
|
||||
auto box1 = new Box(VERTICAL);
|
||||
@ -135,7 +139,6 @@ void MaskByColorCommand::onExecute(Context* context)
|
||||
button_ok->Click.connect(base::Bind<void>(&Window::closeWindow, m_window, button_ok));
|
||||
button_cancel->Click.connect(base::Bind<void>(&Window::closeWindow, m_window, button_cancel));
|
||||
|
||||
|
||||
m_buttonColor->Change.connect(base::Bind<void>(&MaskByColorCommand::maskPreview, this, base::Ref(reader)));
|
||||
m_sliderTolerance->Change.connect(base::Bind<void>(&MaskByColorCommand::maskPreview, this, base::Ref(reader)));
|
||||
m_checkPreview->Click.connect(base::Bind<void>(&MaskByColorCommand::maskPreview, this, base::Ref(reader)));
|
||||
@ -198,7 +201,6 @@ void MaskByColorCommand::onExecute(Context* context)
|
||||
|
||||
// Save window configuration.
|
||||
save_window_pos(m_window, "MaskColor");
|
||||
delete m_window;
|
||||
}
|
||||
|
||||
Mask* MaskByColorCommand::generateMask(const Mask& origMask,
|
||||
@ -245,7 +247,8 @@ Mask* MaskByColorCommand::generateMask(const Mask& origMask,
|
||||
|
||||
void MaskByColorCommand::maskPreview(const ContextReader& reader)
|
||||
{
|
||||
if (m_checkPreview->isSelected()) {
|
||||
ASSERT(m_window);
|
||||
if (m_window && m_checkPreview->isSelected()) {
|
||||
int xpos, ypos;
|
||||
const Image* image = reader.image(&xpos, &ypos);
|
||||
std::unique_ptr<Mask> mask(generateMask(*reader.document()->mask(),
|
||||
|
@ -421,11 +421,10 @@ public:
|
||||
|
||||
// Links
|
||||
locateFile()->Click.connect(base::Bind<void>(&OptionsWindow::onLocateConfigFile, this));
|
||||
#if _WIN32
|
||||
locateCrashFolder()->Click.connect(base::Bind<void>(&OptionsWindow::onLocateCrashFolder, this));
|
||||
#else
|
||||
locateCrashFolder()->setVisible(false);
|
||||
#endif
|
||||
if (!App::instance()->memoryDumpFilename().empty())
|
||||
locateCrashFolder()->Click.connect(base::Bind<void>(&OptionsWindow::onLocateCrashFolder, this));
|
||||
else
|
||||
locateCrashFolder()->setVisible(false);
|
||||
|
||||
// Undo preferences
|
||||
limitUndo()->Click.connect(base::Bind<void>(&OptionsWindow::onLimitUndoCheck, this));
|
||||
@ -1017,7 +1016,8 @@ private:
|
||||
}
|
||||
|
||||
void onLocateCrashFolder() {
|
||||
app::launcher::open_folder(base::get_file_path(app::memory_dump_filename()));
|
||||
app::launcher::open_folder(
|
||||
base::get_file_path(App::instance()->memoryDumpFilename()));
|
||||
}
|
||||
|
||||
void onLocateConfigFile() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -97,15 +97,23 @@ void BackupObserver::onRemoveDocument(Doc* doc)
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
base::remove_from_container(m_documents, doc);
|
||||
}
|
||||
if (m_config->keepEditedSpriteDataFor > 0 &&
|
||||
doc->needsBackup() &&
|
||||
if (doc->needsBackup() &&
|
||||
// If the document is already fully backed up, we don't need to
|
||||
// add it to the background thread to create its backup
|
||||
!doc->isFullyBackedUp() &&
|
||||
// If the backup is disabled, we don't need it (e.g. when the
|
||||
// document is destroyed from a script with Sprite:close(), the
|
||||
// backup is disabled)
|
||||
!doc->inhibitBackup()) {
|
||||
// If m_config->keepEditedSpriteDataFor == 0 we add the document
|
||||
// in m_closedDocs list anyway so we call markAsBackedUp(), and
|
||||
// then it's deleted from ClosedDocs::backgroundThread()
|
||||
|
||||
TRACE("RECO: Adding to CLOSEDOC %p\n", doc);
|
||||
m_closedDocs.push_back(doc);
|
||||
}
|
||||
else {
|
||||
TRACE("RECO: Removing doc %p from session\n", doc);
|
||||
m_session->removeDocument(doc);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -31,6 +31,7 @@
|
||||
#include "base/time.h"
|
||||
#include "doc/cancel_io.h"
|
||||
#include "fmt/format.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
namespace app {
|
||||
namespace crash {
|
||||
@ -170,7 +171,7 @@ void Session::create(base::pid pid)
|
||||
std::ofstream verf(FSTREAM_PATH(verFilename()));
|
||||
|
||||
pidf << m_pid;
|
||||
verf << VERSION;
|
||||
verf << get_app_version();
|
||||
}
|
||||
|
||||
void Session::close()
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -39,6 +39,8 @@
|
||||
#include <limits>
|
||||
#include <map>
|
||||
|
||||
#define DOC_TRACE(...) // TRACEARGS
|
||||
|
||||
namespace app {
|
||||
|
||||
using namespace base;
|
||||
@ -61,10 +63,12 @@ Doc::Doc(Sprite* sprite)
|
||||
sprites().add(sprite);
|
||||
|
||||
updateOSColorSpace(false);
|
||||
DOC_TRACE("DOC: New", this);
|
||||
}
|
||||
|
||||
Doc::~Doc()
|
||||
{
|
||||
DOC_TRACE("DOC: Deleting", this);
|
||||
removeFromContext();
|
||||
}
|
||||
|
||||
@ -77,6 +81,8 @@ void Doc::setContext(Context* ctx)
|
||||
|
||||
m_ctx = ctx;
|
||||
if (ctx) {
|
||||
DOC_TRACE("DOC: Removing as fully backed up", this);
|
||||
|
||||
// Remove the flag that indicates that this doc is fully backed
|
||||
// up, because now we are inside a context, so the user can change
|
||||
// it again and the backup will be outdated.
|
||||
@ -263,6 +269,8 @@ void Doc::setInhibitBackup(const bool inhibitBackup)
|
||||
|
||||
void Doc::markAsBackedUp()
|
||||
{
|
||||
DOC_TRACE("DOC: Mark as fully backed up", this);
|
||||
|
||||
m_flags |= kFullyBackedUp;
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "render/dithering.h"
|
||||
#include "render/ordered_dither.h"
|
||||
#include "render/render.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
@ -1303,8 +1304,8 @@ void DocExporter::createDataFile(const Samples& samples,
|
||||
// "meta" property
|
||||
os << ",\n"
|
||||
<< " \"meta\": {\n"
|
||||
<< " \"app\": \"" << WEBSITE << "\",\n"
|
||||
<< " \"version\": \"" << VERSION << "\",\n";
|
||||
<< " \"app\": \"" << get_app_url() << "\",\n"
|
||||
<< " \"version\": \"" << get_app_version() << "\",\n";
|
||||
|
||||
if (!m_textureFilename.empty())
|
||||
os << " \"image\": \""
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -27,6 +27,7 @@
|
||||
#include "fixmath/fixmath.h"
|
||||
#include "fmt/format.h"
|
||||
#include "ui/alert.h"
|
||||
#include "ver/info.h"
|
||||
#include "zlib.h"
|
||||
|
||||
#include <cstdio>
|
||||
@ -288,7 +289,7 @@ bool AseFormat::onPostLoad(FileOp* fop)
|
||||
|
||||
// Forward Compatibility: In 1.1 we convert a file with layer groups
|
||||
// (saved with 1.2) as top level layers
|
||||
std::string ver = VERSION;
|
||||
std::string ver = get_app_version();
|
||||
bool flat = (ver[0] == '1' &&
|
||||
ver[1] == '.' &&
|
||||
ver[2] == '1');
|
||||
@ -305,7 +306,7 @@ bool AseFormat::onPostLoad(FileOp* fop)
|
||||
"<<Note: Layers inside groups will be converted to top level layers."
|
||||
"||&Yes||&No",
|
||||
base::get_file_name(fop->filename()),
|
||||
PACKAGE, ver)) != 1) {
|
||||
get_app_name(), ver)) != 1) {
|
||||
return false;
|
||||
}
|
||||
ase_ungroup_all(group);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -41,6 +41,7 @@
|
||||
#include "ui/alert.h"
|
||||
#include "ui/listitem.h"
|
||||
#include "ui/system.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
#include "ask_for_color_profile.xml.h"
|
||||
#include "open_sequence.xml.h"
|
||||
@ -200,7 +201,7 @@ FileOp* FileOp::createLoadDocumentOperation(Context* context,
|
||||
dio::detect_format(filename));
|
||||
if (!fop->m_format ||
|
||||
!fop->m_format->support(FILE_SUPPORT_LOAD)) {
|
||||
fop->setError("%s can't load \"%s\" file (\"%s\")\n", PACKAGE,
|
||||
fop->setError("%s can't load \"%s\" file (\"%s\")\n", get_app_name(),
|
||||
filename.c_str(), base::get_file_extension(filename).c_str());
|
||||
goto done;
|
||||
}
|
||||
@ -354,7 +355,7 @@ FileOp* FileOp::createSaveDocumentOperation(const Context* context,
|
||||
dio::detect_format_by_file_extension(filename));
|
||||
if (!fop->m_format ||
|
||||
!fop->m_format->support(FILE_SUPPORT_SAVE)) {
|
||||
fop->setError("%s can't save \"%s\" file (\"%s\")\n", PACKAGE,
|
||||
fop->setError("%s can't save \"%s\" file (\"%s\")\n", get_app_name(),
|
||||
filename.c_str(), base::get_file_extension(filename).c_str());
|
||||
return fop.release();
|
||||
}
|
||||
@ -835,8 +836,9 @@ void FileOp::operate(IFileOpProgress* progress)
|
||||
}
|
||||
#else
|
||||
setError(
|
||||
"Save operation is not supported in trial version.\n"
|
||||
"Go to " WEBSITE_DOWNLOAD " and get the full-version.");
|
||||
fmt::format("Save operation is not supported in trial version.\n"
|
||||
"Go to {} and get the full-version.",
|
||||
get_app_download_url()));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -154,6 +154,7 @@ public:
|
||||
|
||||
// A more easy PIDLs interface (without using the SH* & IL* routines of W2K)
|
||||
#ifdef _WIN32
|
||||
static SFGAOF get_pidl_attrib(FileItem* fileitem, SFGAOF attrib);
|
||||
static void update_by_pidl(FileItem* fileitem, SFGAOF attrib);
|
||||
static LPITEMIDLIST concat_pidl(LPITEMIDLIST pidlHead, LPITEMIDLIST pidlTail);
|
||||
static UINT get_pidl_size(LPITEMIDLIST pidl);
|
||||
@ -453,7 +454,7 @@ const FileItemList& FileItem::children()
|
||||
IEnumIDList *pEnum = NULL;
|
||||
ULONG c, fetched;
|
||||
|
||||
/* get the interface to enumerate subitems */
|
||||
// Get the interface to enumerate subitems
|
||||
hr = pFolder->EnumObjects(reinterpret_cast<HWND>(os::instance()->defaultDisplay()->nativeHandle()),
|
||||
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &pEnum);
|
||||
|
||||
@ -461,16 +462,16 @@ const FileItemList& FileItem::children()
|
||||
LPITEMIDLIST itempidl[256];
|
||||
SFGAOF attribs[256];
|
||||
|
||||
/* enumerate the items in the folder */
|
||||
// Enumerate the items in the folder
|
||||
while (pEnum->Next(256, itempidl, &fetched) == S_OK && fetched > 0) {
|
||||
/* request the SFGAO_FOLDER attribute to know what of the
|
||||
item is a folder */
|
||||
// Request the SFGAO_FOLDER attribute to know what of the
|
||||
// item is file or a folder
|
||||
for (c=0; c<fetched; ++c) {
|
||||
attribs[c] = SFGAO_FOLDER;
|
||||
pFolder->GetAttributesOf(1, (LPCITEMIDLIST *)itempidl, attribs+c);
|
||||
}
|
||||
|
||||
/* generate the FileItems */
|
||||
// Generate the FileItems
|
||||
for (c=0; c<fetched; ++c) {
|
||||
LPITEMIDLIST fullpidl = concat_pidl(m_fullpidl,
|
||||
itempidl[c]);
|
||||
@ -680,6 +681,34 @@ static bool calc_is_folder(std::string filename, SFGAOF attrib)
|
||||
&& ((!filename.empty() && (*filename.begin()) != ':') || (filename == MYPC_CSLID));
|
||||
}
|
||||
|
||||
static SFGAOF get_pidl_attrib(FileItem* fileitem, SFGAOF attrib)
|
||||
{
|
||||
ASSERT(fileitem->m_pidl);
|
||||
ASSERT(fileitem->m_parent);
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
IShellFolder* pFolder = nullptr;
|
||||
if (fileitem->m_parent == rootitem)
|
||||
pFolder = shl_idesktop;
|
||||
else {
|
||||
hr = shl_idesktop->BindToObject(fileitem->m_parent->m_fullpidl,
|
||||
nullptr, IID_IShellFolder, (LPVOID*)&pFolder);
|
||||
if (hr != S_OK)
|
||||
pFolder = nullptr;
|
||||
}
|
||||
|
||||
if (pFolder) {
|
||||
SFGAOF attrib2 = SFGAO_FOLDER;
|
||||
hr = pFolder->GetAttributesOf(1, (LPCITEMIDLIST*)&fileitem->m_pidl, &attrib2);
|
||||
if (hr == S_OK)
|
||||
attrib = attrib2;
|
||||
if (pFolder && pFolder != shl_idesktop)
|
||||
pFolder->Release();
|
||||
}
|
||||
return attrib;
|
||||
}
|
||||
|
||||
// Updates the names of the file-item through its PIDL
|
||||
static void update_by_pidl(FileItem* fileitem, SFGAOF attrib)
|
||||
{
|
||||
@ -693,7 +722,7 @@ static void update_by_pidl(FileItem* fileitem, SFGAOF attrib)
|
||||
else {
|
||||
ASSERT(fileitem->m_parent);
|
||||
hr = shl_idesktop->BindToObject(fileitem->m_parent->m_fullpidl,
|
||||
NULL, IID_IShellFolder, (LPVOID *)&pFolder);
|
||||
nullptr, IID_IShellFolder, (LPVOID*)&pFolder);
|
||||
if (hr != S_OK)
|
||||
pFolder = NULL;
|
||||
}
|
||||
@ -921,7 +950,7 @@ static FileItem* get_fileitem_by_fullpidl(LPITEMIDLIST fullpidl, bool create_if_
|
||||
if (!create_if_not)
|
||||
return nullptr;
|
||||
|
||||
// Check if the pidl exists
|
||||
// Validate if the fullpidl exists.
|
||||
SFGAOF attrib = SFGAO_FOLDER | SFGAO_VALIDATE;
|
||||
HRESULT hr = shl_idesktop->GetAttributesOf(1, (LPCITEMIDLIST*)&fullpidl, &attrib);
|
||||
if (hr != S_OK)
|
||||
@ -939,6 +968,12 @@ static FileItem* get_fileitem_by_fullpidl(LPITEMIDLIST fullpidl, bool create_if_
|
||||
fileitem->m_parent = get_fileitem_by_fullpidl(parent_fullpidl, true);
|
||||
|
||||
free_pidl(parent_fullpidl);
|
||||
|
||||
// Get specific pidl attributes
|
||||
if (fileitem->m_pidl &&
|
||||
fileitem->m_parent) {
|
||||
attrib = get_pidl_attrib(fileitem, attrib);
|
||||
}
|
||||
}
|
||||
|
||||
update_by_pidl(fileitem, attrib);
|
||||
@ -949,9 +984,7 @@ static FileItem* get_fileitem_by_fullpidl(LPITEMIDLIST fullpidl, bool create_if_
|
||||
return fileitem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the @a fileitem in the hash map of items.
|
||||
*/
|
||||
// Inserts the fileitem in the hash map of items.
|
||||
static void put_fileitem(FileItem* fileitem)
|
||||
{
|
||||
ASSERT(fileitem->m_filename != NOTINITIALIZED);
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -40,17 +41,4 @@ GuiXml::GuiXml()
|
||||
m_doc = app::open_xml(rf.filename());
|
||||
}
|
||||
|
||||
std::string GuiXml::version()
|
||||
{
|
||||
TiXmlHandle handle(m_doc.get());
|
||||
TiXmlElement* xmlKey = handle.FirstChild("gui").ToElement();
|
||||
|
||||
if (xmlKey && xmlKey->Attribute("version")) {
|
||||
const char* guixml_version = xmlKey->Attribute("version");
|
||||
return guixml_version;
|
||||
}
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -32,8 +33,6 @@ namespace app {
|
||||
return m_doc->Value();
|
||||
}
|
||||
|
||||
std::string version();
|
||||
|
||||
private:
|
||||
GuiXml();
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -13,6 +14,8 @@
|
||||
#include "app/app.h"
|
||||
#include "app/resource_finder.h"
|
||||
#include "base/log.h"
|
||||
#include "fmt/format.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
@ -20,10 +23,14 @@ LoggerModule::LoggerModule(bool createLogInDesktop)
|
||||
{
|
||||
app::ResourceFinder rf(false);
|
||||
|
||||
if (createLogInDesktop)
|
||||
rf.includeDesktopDir(PACKAGE "-v" VERSION "-DebugOutput.txt");
|
||||
else
|
||||
rf.includeUserDir("aseprite.log");
|
||||
if (createLogInDesktop) {
|
||||
rf.includeDesktopDir(fmt::format("{}-v{}-DebugOutput.txt",
|
||||
get_app_name(),
|
||||
get_app_version()).c_str());
|
||||
}
|
||||
else {
|
||||
rf.includeUserDir(fmt::format("{}.log", get_app_name()).c_str());
|
||||
}
|
||||
|
||||
auto filename = rf.defaultFilename();
|
||||
base::set_log_filename(filename.c_str());
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -217,18 +217,19 @@ void draw_alpha_slider(os::Surface* s,
|
||||
color.getGreen(),
|
||||
color.getBlue(), 255): 0);
|
||||
|
||||
os::Paint paint;
|
||||
for (int x=0; x<rc.w; ++x) {
|
||||
const int a = (255 * x / xmax);
|
||||
const doc::color_t c1 = doc::rgba_blender_normal(gridColor1, c, a);
|
||||
const doc::color_t c2 = doc::rgba_blender_normal(gridColor2, c, a);
|
||||
const int mid = rc.h/2;
|
||||
const int odd = (x / rc.h) & 1;
|
||||
s->drawVLine(
|
||||
app::color_utils::color_for_ui(app::Color::fromImage(IMAGE_RGB, odd ? c2: c1)),
|
||||
rc.x+x, rc.y, mid);
|
||||
s->drawVLine(
|
||||
app::color_utils::color_for_ui(app::Color::fromImage(IMAGE_RGB, odd ? c1: c2)),
|
||||
rc.x+x, rc.y+mid, rc.h-mid);
|
||||
|
||||
paint.color(app::color_utils::color_for_ui(app::Color::fromImage(IMAGE_RGB, odd ? c2: c1)));
|
||||
s->drawRect(gfx::Rect(rc.x+x, rc.y, 1, mid), paint);
|
||||
|
||||
paint.color(app::color_utils::color_for_ui(app::Color::fromImage(IMAGE_RGB, odd ? c1: c2)));
|
||||
s->drawRect(gfx::Rect(rc.x+x, rc.y+mid, 1, rc.h-mid), paint);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -18,6 +19,7 @@
|
||||
#include "base/string.h"
|
||||
#include "net/http_request.h"
|
||||
#include "net/http_response.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
@ -49,7 +51,7 @@ void HttpLoader::threadHttpRequest()
|
||||
|
||||
LOG("HTTP: Sending http request to %s\n", m_url.c_str());
|
||||
|
||||
std::string dir = base::join_path(base::get_temp_path(), PACKAGE);
|
||||
std::string dir = base::join_path(base::get_temp_path(), get_app_name());
|
||||
base::make_all_directories(dir);
|
||||
|
||||
std::string fn = m_url;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -14,6 +14,7 @@
|
||||
#include "app/app.h"
|
||||
#include "base/fs.h"
|
||||
#include "base/string.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
@ -178,7 +179,7 @@ void ResourceFinder::includeUserDir(const char* filename)
|
||||
// $HOME/Library/Application Support/Aseprite/filename
|
||||
addPath(
|
||||
base::join_path(
|
||||
base::join_path(base::get_lib_app_support_path(), PACKAGE),
|
||||
base::join_path(base::get_lib_app_support_path(), get_app_name()),
|
||||
filename).c_str());
|
||||
|
||||
#else // !__APPLE__
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "doc/tag.h"
|
||||
#include "render/render.h"
|
||||
#include "ui/alert.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@ -490,7 +491,7 @@ int App_get_isUIAvailable(lua_State* L)
|
||||
|
||||
int App_get_version(lua_State* L)
|
||||
{
|
||||
std::string ver = VERSION;
|
||||
std::string ver = get_app_version();
|
||||
base::replace_string(ver, "-x64", ""); // Remove "-x64" suffix
|
||||
push_version(L, base::Version(ver));
|
||||
return 1;
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -14,26 +15,105 @@
|
||||
#include "app/console.h"
|
||||
#include "app/i18n/strings.h"
|
||||
#include "app/resource_finder.h"
|
||||
#include "app/task.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/fs.h"
|
||||
#include "base/launcher.h"
|
||||
#include "fmt/format.h"
|
||||
#include "ui/alert.h"
|
||||
#include "ui/system.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
#include "send_crash.xml.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
// static
|
||||
std::string SendCrash::DefaultMemoryDumpFilename()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
std::string kDefaultCrashName = fmt::format("{}-crash-{}.dmp",
|
||||
get_app_name(),
|
||||
get_app_version());
|
||||
ResourceFinder rf;
|
||||
rf.includeUserDir(kDefaultCrashName.c_str());
|
||||
return rf.getFirstOrCreateDefault();
|
||||
#else
|
||||
return std::string();
|
||||
#endif
|
||||
}
|
||||
|
||||
SendCrash::~SendCrash()
|
||||
{
|
||||
if (m_task.running()) {
|
||||
m_task.cancel();
|
||||
m_task.wait();
|
||||
}
|
||||
}
|
||||
|
||||
void SendCrash::search()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
m_dumpFilename = memory_dump_filename();
|
||||
// On Windows we use one mini-dump to report bugs, then we can open
|
||||
// this .dmp file locally along with the .exe + .pdb to check the
|
||||
// stack trace and detect the cause of the bug.
|
||||
|
||||
if (base::is_file(m_dumpFilename)) {
|
||||
App::instance()->showNotification(this);
|
||||
m_dumpFilename = SendCrash::DefaultMemoryDumpFilename();
|
||||
if (!m_dumpFilename.empty() &&
|
||||
base::is_file(m_dumpFilename)) {
|
||||
auto app = App::instance();
|
||||
app->memoryDumpFilename(m_dumpFilename);
|
||||
#ifdef ENABLE_UI
|
||||
app->showNotification(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
// On macOS we can show the possibility to send the latest crash
|
||||
// report from ~/Library/Logs/DiagnosticReports which is the
|
||||
// location where crash reports (.crash files) are located.
|
||||
|
||||
m_task.run(
|
||||
[this](base::task_token&){
|
||||
ResourceFinder rf;
|
||||
rf.includeHomeDir("Library/Logs/DiagnosticReports");
|
||||
std::string dir = rf.defaultFilename();
|
||||
if (base::is_directory(dir)) {
|
||||
std::vector<std::string> candidates;
|
||||
int n = std::strlen(get_app_name());
|
||||
for (const auto& fn : base::list_files(dir)) {
|
||||
// Cancel everything
|
||||
if (m_task.canceled())
|
||||
return;
|
||||
|
||||
if (base::utf8_icmp(get_app_name(), fn, n) == 0) {
|
||||
candidates.push_back(fn);
|
||||
}
|
||||
}
|
||||
std::sort(candidates.begin(), candidates.end());
|
||||
if (!candidates.empty()) {
|
||||
std::string fn = base::join_path(dir, candidates.back());
|
||||
if (base::is_file(fn)) {
|
||||
ui::execute_from_ui_thread(
|
||||
[this, fn]{
|
||||
m_dumpFilename = fn;
|
||||
if (auto app = App::instance()) {
|
||||
app->memoryDumpFilename(fn);
|
||||
#ifdef ENABLE_UI
|
||||
app->showNotification(this);
|
||||
#endif
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ENABLE_UI
|
||||
|
||||
std::string SendCrash::notificationText()
|
||||
{
|
||||
return "Report last crash";
|
||||
@ -48,15 +128,24 @@ void SendCrash::notificationClick()
|
||||
|
||||
app::gen::SendCrash dlg;
|
||||
|
||||
// The current version is a "development" version if the VERSION
|
||||
// macro contains the "dev" word.
|
||||
bool isDev = (std::string(VERSION).find("dev") != std::string::npos);
|
||||
#if _WIN32
|
||||
// Only on Windows, if the current version is a development version
|
||||
// (i.e. the get_app_version() contains "-dev"), the .dmp
|
||||
// file is useless for us. This is because we need the .exe + .pdb +
|
||||
// source code used in the compilation process to make some sense of
|
||||
// the .dmp file.
|
||||
|
||||
bool isDev = (std::string(get_app_version()).find("-dev") != std::string::npos);
|
||||
if (isDev) {
|
||||
dlg.official()->setVisible(false);
|
||||
dlg.devFilename()->setText(m_dumpFilename);
|
||||
dlg.devFilename()->Click.connect(base::Bind(&SendCrash::onClickDevFilename, this));
|
||||
}
|
||||
else {
|
||||
else
|
||||
#endif // On other platforms the crash file might be useful even in
|
||||
// the "-dev" version (e.g. on macOS it's a text file with
|
||||
// stack traces).
|
||||
{
|
||||
dlg.dev()->setVisible(false);
|
||||
dlg.filename()->setText(m_dumpFilename);
|
||||
dlg.filename()->Click.connect(base::Bind(&SendCrash::onClickFilename, this));
|
||||
@ -84,4 +173,6 @@ void SendCrash::onClickDevFilename()
|
||||
base::launcher::open_file(m_dumpFilename);
|
||||
}
|
||||
|
||||
#endif // ENABLE_UI
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -9,22 +10,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "app/notification_delegate.h"
|
||||
#include "app/task.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace app {
|
||||
|
||||
class SendCrash : public INotificationDelegate {
|
||||
class SendCrash
|
||||
#ifdef ENABLE_UI
|
||||
: public INotificationDelegate
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
static std::string DefaultMemoryDumpFilename();
|
||||
|
||||
~SendCrash();
|
||||
|
||||
void search();
|
||||
|
||||
#ifdef ENABLE_UI
|
||||
public: // INotificationDelegate impl
|
||||
virtual std::string notificationText() override;
|
||||
virtual void notificationClick() override;
|
||||
|
||||
private:
|
||||
void onClickFilename();
|
||||
void onClickDevFilename();
|
||||
#endif // ENABLE_UI
|
||||
|
||||
private:
|
||||
Task m_task;
|
||||
std::string m_dumpFilename;
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -14,7 +15,9 @@
|
||||
|
||||
#include "app/shell.h"
|
||||
|
||||
#include "fmt/format.h"
|
||||
#include "script/engine.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
@ -31,7 +34,8 @@ Shell::~Shell()
|
||||
|
||||
void Shell::run(script::Engine& engine)
|
||||
{
|
||||
std::cout << "Welcome to " PACKAGE " v" VERSION " Interactive Console" << std::endl;
|
||||
std::cout << fmt::format("Welcome to {} v{} Interactive Console",
|
||||
get_app_name(), get_app_version()) << std::endl;
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
engine.evalCode(line);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -11,6 +11,7 @@
|
||||
#include "app/task.h"
|
||||
|
||||
#include "base/task.h"
|
||||
#include "base/thread.h"
|
||||
#include "base/thread_pool.h"
|
||||
|
||||
namespace app {
|
||||
@ -32,4 +33,12 @@ void Task::run(base::task::func_t&& func)
|
||||
m_token = &m_task.start(tasks_pool);
|
||||
}
|
||||
|
||||
void Task::wait()
|
||||
{
|
||||
// TODO wait a condition variable
|
||||
while (!m_task.completed()) {
|
||||
base::this_thread::sleep_for(0.1);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -20,6 +20,7 @@ namespace app {
|
||||
~Task();
|
||||
|
||||
void run(base::task::func_t&& func);
|
||||
void wait();
|
||||
|
||||
// Returns true when the task is completed (whether it was
|
||||
// canceled or not)
|
||||
@ -27,6 +28,10 @@ namespace app {
|
||||
return m_task.completed();
|
||||
}
|
||||
|
||||
bool running() const {
|
||||
return m_task.running();
|
||||
}
|
||||
|
||||
bool canceled() const {
|
||||
if (m_token)
|
||||
return m_token->canceled();
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -102,6 +102,9 @@ namespace app {
|
||||
|
||||
// Called for each point shape.
|
||||
virtual void prepareForPointShape(ToolLoop* loop, bool firstPoint, int x, int y) { }
|
||||
virtual void prepareVForPointShape(ToolLoop* loop, int y) { }
|
||||
virtual void prepareUForPointShapeWholeScanline(ToolLoop* loop, int x1) { }
|
||||
virtual void prepareUForPointShapeSlicedScanline(ToolLoop* loop, bool leftSlice, int x1) { }
|
||||
|
||||
};
|
||||
|
||||
|
@ -34,6 +34,9 @@ public:
|
||||
virtual void processScanline(int x1, int y, int x2, ToolLoop* loop) = 0;
|
||||
virtual void prepareForStrokes(ToolLoop* loop, Strokes& strokes) { }
|
||||
virtual void prepareForPointShape(ToolLoop* loop, bool firstPoint, int x, int y) { }
|
||||
virtual void prepareVForPointShape(ToolLoop* loop, int y) { }
|
||||
virtual void prepareUForPointShapeWholeScanline(ToolLoop* loop, int x1) { }
|
||||
virtual void prepareUForPointShapeSlicedScanline(ToolLoop* loop, bool leftSlice, int x1) { }
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<BaseInkProcessing> InkProcessingPtr;
|
||||
@ -1124,8 +1127,51 @@ public:
|
||||
void prepareForPointShape(ToolLoop* loop, bool firstPoint, int x, int y) override {
|
||||
if ((m_brush->pattern() == BrushPattern::ALIGNED_TO_DST && firstPoint) ||
|
||||
(m_brush->pattern() == BrushPattern::PAINT_BRUSH)) {
|
||||
m_u = (m_brush->patternOrigin().x - loop->getCelOrigin().x) % m_width;
|
||||
m_u = ((m_brush->patternOrigin().x % loop->sprite()->width()) - loop->getCelOrigin().x) % m_width;
|
||||
m_v = ((m_brush->patternOrigin().y % loop->sprite()->height()) - loop->getCelOrigin().y) % m_height;
|
||||
}
|
||||
}
|
||||
|
||||
void prepareVForPointShape(ToolLoop* loop, int y) override {
|
||||
|
||||
if (m_brush->pattern() == doc::BrushPattern::ALIGNED_TO_SRC) {
|
||||
m_v = (m_brush->patternOrigin().y - loop->getCelOrigin().y) % m_height;
|
||||
if (m_v < 0) m_v += m_height;
|
||||
}
|
||||
else {
|
||||
int spriteH = loop->sprite()->height();
|
||||
if (y/spriteH > 0)
|
||||
// 'y' is outside of the center tile.
|
||||
m_v = (m_brush->patternOrigin().y + m_height - (y/spriteH) * spriteH) % m_height;
|
||||
else
|
||||
// 'y' is inside of the center tile.
|
||||
m_v = ((m_brush->patternOrigin().y % spriteH) - loop->getCelOrigin().y) % m_height;
|
||||
}
|
||||
}
|
||||
|
||||
void prepareUForPointShapeWholeScanline(ToolLoop* loop, int x1) override {
|
||||
if (m_brush->pattern() == doc::BrushPattern::ALIGNED_TO_SRC) {
|
||||
m_u = (m_brush->patternOrigin().x - loop->getCelOrigin().x) % m_width;
|
||||
if (m_u < 0) m_u += m_height;
|
||||
}
|
||||
else {
|
||||
m_u = ((m_brush->patternOrigin().x % loop->sprite()->width()) - loop->getCelOrigin().x ) % m_width;
|
||||
if (x1/loop->sprite()->width() > 0)
|
||||
m_u = (m_brush->patternOrigin().x + m_width - (x1/loop->sprite()->width()) * loop->sprite()->width()) % m_width;
|
||||
}
|
||||
}
|
||||
|
||||
void prepareUForPointShapeSlicedScanline(ToolLoop* loop, bool leftSlice, int x1) override {
|
||||
if (loop->getBrush()->pattern() == doc::BrushPattern::ALIGNED_TO_SRC) {
|
||||
m_u = (m_brush->patternOrigin().x - loop->getCelOrigin().x) % m_width;
|
||||
if (m_u < 0) m_u += m_height;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (leftSlice)
|
||||
m_u = ((m_brush->patternOrigin().x % loop->sprite()->width()) - loop->getCelOrigin().x ) % m_width;
|
||||
else
|
||||
m_u = (m_brush->patternOrigin().x + m_width - (x1/loop->sprite()->width() + 1) * loop->sprite()->width()) % m_width;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -34,6 +34,21 @@ public:
|
||||
m_proc->prepareForPointShape(loop, firstPoint, x, y);
|
||||
}
|
||||
|
||||
void prepareVForPointShape(ToolLoop* loop, int y) override {
|
||||
ASSERT(m_proc);
|
||||
m_proc->prepareVForPointShape(loop, y);
|
||||
}
|
||||
|
||||
void prepareUForPointShapeWholeScanline(ToolLoop* loop, int x1) override {
|
||||
ASSERT(m_proc);
|
||||
m_proc->prepareUForPointShapeWholeScanline(loop, x1);
|
||||
}
|
||||
|
||||
void prepareUForPointShapeSlicedScanline(ToolLoop* loop, bool leftSlice, int x1) override {
|
||||
ASSERT(m_proc);
|
||||
m_proc->prepareUForPointShapeSlicedScanline(loop, leftSlice, x1);
|
||||
}
|
||||
|
||||
protected:
|
||||
void setProc(BaseInkProcessing* proc) {
|
||||
m_proc.reset(proc);
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -13,7 +14,9 @@
|
||||
#include "app/tools/ink.h"
|
||||
#include "app/tools/tool_loop.h"
|
||||
#include "app/util/wrap_value.h"
|
||||
#include "doc/brush.h"
|
||||
#include "doc/image.h"
|
||||
#include "doc/sprite.h"
|
||||
|
||||
namespace app {
|
||||
namespace tools {
|
||||
@ -53,13 +56,20 @@ void PointShape::doInkHline(int x1, int y, int x2, ToolLoop* loop)
|
||||
if (w >= size)
|
||||
loop->getInk()->inkHline(0, y, size-1, loop);
|
||||
else {
|
||||
x = x1;
|
||||
x = wrap_value(x, size);
|
||||
|
||||
if (x+w-1 <= size-1)
|
||||
x = wrap_value(x1, loop->sprite()->width());
|
||||
if (x+w <= loop->sprite()->width()) {
|
||||
// Here we asure that tile limit line does not bisect the current
|
||||
// scanline, i.e. the scanline is enterely contained inside the tile.
|
||||
loop->getInk()->prepareUForPointShapeWholeScanline(loop, x1);
|
||||
loop->getInk()->inkHline(x, y, x+w-1, loop);
|
||||
}
|
||||
else {
|
||||
// Here the tile limit line bisect the current scanline.
|
||||
// So we need to execute TWO times the inkHline function, each one with a different m_u.
|
||||
loop->getInk()->prepareUForPointShapeSlicedScanline(loop, true, x1);// true = left slice
|
||||
loop->getInk()->inkHline(x, y, size-1, loop);
|
||||
|
||||
loop->getInk()->prepareUForPointShapeSlicedScanline(loop, false, x1);// false = right slice
|
||||
loop->getInk()->inkHline(0, y, w-(size-x)-1, loop);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -7,6 +7,8 @@
|
||||
|
||||
#include "app/util/wrap_point.h"
|
||||
|
||||
#include "app/tools/ink.h"
|
||||
|
||||
namespace app {
|
||||
namespace tools {
|
||||
|
||||
@ -67,13 +69,24 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
if (int(loop->getTiledMode()) & int(TiledMode::X_AXIS)) {
|
||||
int wrappedPatternOriginX = wrap_value(m_brush->patternOrigin().x, loop->sprite()->width()) % m_brush->bounds().w;
|
||||
m_brush->setPatternOrigin(gfx::Point(wrappedPatternOriginX, m_brush->patternOrigin().y));
|
||||
x = wrap_value(x, loop->sprite()->width());
|
||||
}
|
||||
if (int(loop->getTiledMode()) & int(TiledMode::Y_AXIS)) {
|
||||
int wrappedPatternOriginY = wrap_value(m_brush->patternOrigin().y, loop->sprite()->height()) % m_brush->bounds().h;
|
||||
m_brush->setPatternOrigin(gfx::Point(m_brush->patternOrigin().x, wrappedPatternOriginY));
|
||||
y = wrap_value(y, loop->sprite()->height());
|
||||
}
|
||||
|
||||
loop->getInk()->prepareForPointShape(loop, m_firstPoint, x, y);
|
||||
|
||||
for (auto scanline : *m_compressedImage) {
|
||||
int u = x+scanline.x;
|
||||
loop->getInk()->prepareVForPointShape(loop, y+scanline.y);
|
||||
doInkHline(u, y+scanline.y, u+scanline.w-1, loop);
|
||||
}
|
||||
|
||||
m_firstPoint = false;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2016-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -113,7 +113,10 @@ public:
|
||||
|
||||
auto oldCanvas = m_canvas;
|
||||
m_canvas = os::instance()->createSurface(w, h, activeCS);
|
||||
m_canvas->fillRect(bgColor, gfx::Rect(0, 0, w, h));
|
||||
os::Paint paint;
|
||||
paint.color(bgColor);
|
||||
paint.style(os::Paint::Fill);
|
||||
m_canvas->drawRect(gfx::Rect(0, 0, w, h), paint);
|
||||
if (oldCanvas) {
|
||||
m_canvas->drawSurface(oldCanvas, 0, 0);
|
||||
oldCanvas->dispose();
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -111,11 +112,12 @@ void ColorSpectrum::onPaintSurfaceInBgThread(
|
||||
if (m_paintFlags & BottomBarFlag) {
|
||||
double lit = m_color.getHslLightness();
|
||||
double hue = m_color.getHslHue();
|
||||
os::Paint paint;
|
||||
for (int x=0; x<bottom.w && !stop; ++x) {
|
||||
gfx::Color color = color_utils::color_for_ui(
|
||||
app::Color::fromHsl(hue, double(x) / double(bottom.w), lit));
|
||||
|
||||
s->drawVLine(color, bottom.x+x, bottom.y, bottom.h);
|
||||
paint.color(
|
||||
color_utils::color_for_ui(
|
||||
app::Color::fromHsl(hue, double(x) / double(bottom.w), lit)));
|
||||
s->drawRect(gfx::Rect(bottom.x+x, bottom.y, 1, bottom.h), paint);
|
||||
}
|
||||
if (stop)
|
||||
return;
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2016-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -100,12 +101,14 @@ void ColorTintShadeTone::onPaintSurfaceInBgThread(
|
||||
}
|
||||
|
||||
if (m_paintFlags & BottomBarFlag) {
|
||||
os::Paint paint;
|
||||
for (int x=0; x<bottom.w && !stop; ++x) {
|
||||
gfx::Color color = color_utils::color_for_ui(
|
||||
app::Color::fromHsv(
|
||||
(360.0 * x / bottom.w), 1.0, 1.0));
|
||||
paint.color(
|
||||
color_utils::color_for_ui(
|
||||
app::Color::fromHsv(
|
||||
(360.0 * x / bottom.w), 1.0, 1.0)));
|
||||
|
||||
s->drawVLine(color, bottom.x+x, bottom.y, bottom.h);
|
||||
s->drawRect(gfx::Rect(bottom.x+x, bottom.y, 1, bottom.h), paint);
|
||||
}
|
||||
if (stop)
|
||||
return;
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -275,12 +276,13 @@ void ColorWheel::onPaintSurfaceInBgThread(os::Surface* s,
|
||||
if (m_paintFlags & BottomBarFlag) {
|
||||
double hue = m_color.getHsvHue();
|
||||
double sat = m_color.getHsvSaturation();
|
||||
|
||||
os::Paint paint;
|
||||
for (int x=0; x<bottom.w && !stop; ++x) {
|
||||
gfx::Color color = color_utils::color_for_ui(
|
||||
app::Color::fromHsv(hue, sat, double(x) / double(bottom.w)));
|
||||
paint.color(
|
||||
color_utils::color_for_ui(
|
||||
app::Color::fromHsv(hue, sat, double(x) / double(bottom.w))));
|
||||
|
||||
s->drawVLine(color, bottom.x+x, bottom.y, bottom.h);
|
||||
s->drawRect(gfx::Rect(bottom.x+x, bottom.y, 1, bottom.h), paint);
|
||||
}
|
||||
if (stop)
|
||||
return;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -40,6 +40,7 @@
|
||||
#include "ui/size_hint_event.h"
|
||||
#include "ui/system.h"
|
||||
#include "ui/view.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@ -314,7 +315,7 @@ void DataRecoveryView::fillListWith(const bool crashes)
|
||||
}
|
||||
|
||||
std::string title = session->name();
|
||||
if (session->version() != VERSION)
|
||||
if (session->version() != get_app_version())
|
||||
title =
|
||||
fmt::format(Strings::recover_files_incompatible(),
|
||||
title, session->version());
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -18,11 +19,13 @@
|
||||
#include "app/app_menus.h"
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "app/ui/workspace.h"
|
||||
#include "fmt/format.h"
|
||||
#include "ui/entry.h"
|
||||
#include "ui/message.h"
|
||||
#include "ui/system.h"
|
||||
#include "ui/textbox.h"
|
||||
#include "ui/view.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
@ -64,7 +67,8 @@ protected:
|
||||
|
||||
DevConsoleView::DevConsoleView()
|
||||
: Box(VERTICAL)
|
||||
, m_textBox("Welcome to " PACKAGE " v" VERSION " Console\n(Experimental)", LEFT)
|
||||
, m_textBox(fmt::format("Welcome to {} v{} Console\n(Experimental)",
|
||||
get_app_name(), get_app_version()), LEFT)
|
||||
, m_label(">")
|
||||
, m_entry(new CommmandEntry)
|
||||
, m_engine(App::instance()->scriptEngine())
|
||||
|
@ -394,13 +394,17 @@ void DocView::onAddLayer(DocEvent& ev)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO why note move this code to Editor::onBeforeRemoveLayer?
|
||||
void DocView::onBeforeRemoveLayer(DocEvent& ev)
|
||||
{
|
||||
Sprite* sprite = ev.sprite();
|
||||
Layer* layer = ev.layer();
|
||||
|
||||
// If the layer that was removed is the selected one
|
||||
if (layer == m_editor->layer()) {
|
||||
// If the layer that was removed is the selected one in the editor,
|
||||
// or is an ancestor of the selected one.
|
||||
if ((m_editor->layer() == layer) ||
|
||||
(m_editor->layer() &&
|
||||
m_editor->layer()->hasAncestor(layer))) {
|
||||
LayerGroup* parent = layer->parent();
|
||||
Layer* layer_select = NULL;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -142,8 +142,10 @@ private:
|
||||
|
||||
{
|
||||
os::SurfaceLock lock(surface);
|
||||
surface->fillRect(gfx::rgba(0, 0, 0, 0),
|
||||
gfx::Rect(0, 0, surface->width(), surface->height()));
|
||||
os::Paint paint;
|
||||
paint.color(gfx::rgba(0, 0, 0, 0));
|
||||
paint.style(os::Paint::Fill);
|
||||
surface->drawRect(gfx::Rect(0, 0, surface->width(), surface->height()), paint);
|
||||
}
|
||||
{
|
||||
ui::Graphics g(surface, 0, 0);
|
||||
|
@ -716,7 +716,9 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& sprite
|
||||
// internal state of a SkCanvas or SkBitmap thing is
|
||||
// updated after this, because convert_image_to_surface()
|
||||
// will overwrite these pixels anyway.
|
||||
tmp->drawRect(gfx::rgba(0, 0, 0, 255), gfx::Rect(0, 0, 1, 1));
|
||||
os::Paint paint;
|
||||
paint.color(gfx::rgba(0, 0, 0, 255));
|
||||
tmp->drawRect(gfx::Rect(0, 0, 1, 1), paint);
|
||||
}
|
||||
|
||||
convert_image_to_surface(rendered.get(), m_sprite->palette(m_frame),
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2017-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -92,6 +92,36 @@ bool MovingSliceState::onMouseMove(Editor* editor, MouseMessage* msg)
|
||||
rc.x += delta.x;
|
||||
rc.y += delta.y;
|
||||
}
|
||||
// Move/resize 9-slices center
|
||||
else if (m_hit.type() == EditorHit::SliceCenter) {
|
||||
if (m_hit.border() & LEFT) {
|
||||
rc.x += delta.x;
|
||||
rc.w -= delta.x;
|
||||
if (rc.w < 1) {
|
||||
rc.x += rc.w-1;
|
||||
rc.w = 1;
|
||||
}
|
||||
}
|
||||
if (m_hit.border() & TOP) {
|
||||
rc.y += delta.y;
|
||||
rc.h -= delta.y;
|
||||
if (rc.h < 1) {
|
||||
rc.y += rc.h-1;
|
||||
rc.h = 1;
|
||||
}
|
||||
}
|
||||
if (m_hit.border() & RIGHT) {
|
||||
rc.w += delta.x;
|
||||
if (rc.w < 1)
|
||||
rc.w = 1;
|
||||
}
|
||||
if (m_hit.border() & BOTTOM) {
|
||||
rc.h += delta.y;
|
||||
if (rc.h < 1)
|
||||
rc.h = 1;
|
||||
}
|
||||
}
|
||||
// Move/resize bounds
|
||||
else {
|
||||
if (m_hit.border() & LEFT) {
|
||||
rc.x += delta.x * (totalBounds.x2() - rc.x) / totalBounds.w;
|
||||
|
@ -57,6 +57,8 @@
|
||||
#include "render/render.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace app {
|
||||
|
||||
using namespace ui;
|
||||
@ -601,6 +603,8 @@ public:
|
||||
if (!m_editor->selectSliceBox(bounds) &&
|
||||
(bounds.w > 1 || bounds.h > 1)) {
|
||||
Slice* slice = new Slice;
|
||||
slice->setName(getUniqueSliceName());
|
||||
|
||||
SliceKey key(bounds);
|
||||
slice->insert(getFrame(), key);
|
||||
|
||||
@ -622,6 +626,21 @@ public:
|
||||
m_canceled = true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
#ifdef ENABLE_UI
|
||||
std::string getUniqueSliceName() const {
|
||||
std::string prefix = "Slice";
|
||||
int max = 0;
|
||||
|
||||
for (Slice* slice : m_sprite->slices())
|
||||
if (std::strncmp(slice->name().c_str(), prefix.c_str(), prefix.size()) == 0)
|
||||
max = std::max(max, (int)std::strtol(slice->name().c_str()+prefix.size(), nullptr, 10));
|
||||
|
||||
return fmt::format("{} {}", prefix, max+1);
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#ifdef ENABLE_UI
|
||||
|
@ -613,37 +613,34 @@ again:
|
||||
}
|
||||
// else file-name specified in the entry is really a file to open...
|
||||
|
||||
// check if the filename doesn't contain slashes or other ilegal characters...
|
||||
bool has_invalid_char = (fn.find('/') != std::string::npos);
|
||||
#ifdef _WIN32
|
||||
has_invalid_char =
|
||||
has_invalid_char ||
|
||||
(fn.find('\\') != std::string::npos ||
|
||||
fn.find(':') != std::string::npos ||
|
||||
fn.find('*') != std::string::npos ||
|
||||
fn.find('?') != std::string::npos ||
|
||||
fn.find('\"') != std::string::npos ||
|
||||
fn.find('<') != std::string::npos ||
|
||||
fn.find('>') != std::string::npos ||
|
||||
fn.find('|') != std::string::npos);
|
||||
#endif
|
||||
if (has_invalid_char) {
|
||||
const char* invalid_chars =
|
||||
"/"
|
||||
#ifdef _WIN32
|
||||
" \\ : * ? \" < > |"
|
||||
#endif
|
||||
;
|
||||
// Check that the filename doesn't contain ilegal characters.
|
||||
// Linux allows all kind of characters, only '/' is disallowed,
|
||||
// but in that case we consider that a full path was entered in
|
||||
// the filename and we can enter to the full path folder.
|
||||
if (!enter_folder) {
|
||||
const bool has_invalid_char =
|
||||
(fn.find(':') != std::string::npos ||
|
||||
fn.find('*') != std::string::npos ||
|
||||
fn.find('?') != std::string::npos ||
|
||||
fn.find('\"') != std::string::npos ||
|
||||
fn.find('<') != std::string::npos ||
|
||||
fn.find('>') != std::string::npos ||
|
||||
fn.find('|') != std::string::npos);
|
||||
if (has_invalid_char) {
|
||||
const char* invalid_chars = ": * ? \" < > |";
|
||||
|
||||
ui::Alert::show(
|
||||
fmt::format(
|
||||
Strings::alerts_invalid_chars_in_filename(),
|
||||
invalid_chars));
|
||||
ui::Alert::show(
|
||||
fmt::format(
|
||||
Strings::alerts_invalid_chars_in_filename(),
|
||||
invalid_chars));
|
||||
|
||||
// show the window again
|
||||
setVisible(true);
|
||||
goto again;
|
||||
// show the window again
|
||||
setVisible(true);
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// does it not have extension? ...we should add the extension
|
||||
// selected in the filetype combo-box
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -33,6 +33,7 @@
|
||||
#include "ui/system.h"
|
||||
#include "ui/textbox.h"
|
||||
#include "ui/view.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
#ifdef ENABLE_NEWS
|
||||
#include "app/ui/news_listbox.h"
|
||||
@ -177,7 +178,7 @@ void HomeView::onCheckingUpdates()
|
||||
void HomeView::onUpToDate()
|
||||
{
|
||||
checkUpdate()->setText(
|
||||
fmt::format(Strings::home_view_is_up_to_date(), PACKAGE));
|
||||
fmt::format(Strings::home_view_is_up_to_date(), get_app_name()));
|
||||
checkUpdate()->setVisible(true);
|
||||
|
||||
layout();
|
||||
@ -186,7 +187,8 @@ void HomeView::onUpToDate()
|
||||
void HomeView::onNewUpdate(const std::string& url, const std::string& version)
|
||||
{
|
||||
checkUpdate()->setText(
|
||||
fmt::format(Strings::home_view_new_version_available(), PACKAGE, version));
|
||||
fmt::format(Strings::home_view_new_version_available(),
|
||||
get_app_name(), version));
|
||||
checkUpdate()->setUrl(url);
|
||||
checkUpdate()->setVisible(true);
|
||||
checkUpdate()->InitTheme.connect(
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -23,6 +24,7 @@
|
||||
#include "ui/paint_event.h"
|
||||
#include "ui/size_hint_event.h"
|
||||
#include "ui/view.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
#include "tinyxml.h"
|
||||
|
||||
@ -209,7 +211,7 @@ void NewsListBox::reload()
|
||||
if (view)
|
||||
view->updateView();
|
||||
|
||||
m_loader = new HttpLoader(WEBSITE_NEWS_RSS);
|
||||
m_loader = new HttpLoader(get_app_news_rss_url());
|
||||
m_timer.start();
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -100,6 +100,7 @@ public:
|
||||
void setPlaying(bool state) {
|
||||
m_isPlaying = state;
|
||||
setupIcons();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
obs::signal<void()> Popup;
|
||||
@ -209,8 +210,7 @@ void PreviewEditorWindow::setPreviewEnabled(bool state)
|
||||
|
||||
void PreviewEditorWindow::pressPlayButton()
|
||||
{
|
||||
m_playButton->setSelected(
|
||||
!m_playButton->isSelected());
|
||||
m_playButton->setPlaying(!m_playButton->isPlaying());
|
||||
onPlayClicked();
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -51,7 +52,7 @@ FontData::~FontData()
|
||||
|
||||
os::Font* FontData::getFont(int size)
|
||||
{
|
||||
if (m_type == os::FontType::kSpriteSheet)
|
||||
if (m_type == os::FontType::SpriteSheet)
|
||||
size = 1; // Same size always
|
||||
|
||||
// Use cache
|
||||
@ -63,10 +64,10 @@ os::Font* FontData::getFont(int size)
|
||||
os::Font* font = nullptr;
|
||||
|
||||
switch (m_type) {
|
||||
case os::FontType::kSpriteSheet:
|
||||
case os::FontType::SpriteSheet:
|
||||
font = os::instance()->loadSpriteSheetFont(m_filename.c_str(), size);
|
||||
break;
|
||||
case os::FontType::kTrueType: {
|
||||
case os::FontType::FreeType: {
|
||||
font = os::instance()->loadTrueTypeFont(m_filename.c_str(), size);
|
||||
if (font)
|
||||
font->setAntialias(m_antialias);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -113,7 +113,7 @@ static FontData* load_font(std::map<std::string, FontData*>& fonts,
|
||||
if (type == "spritesheet") {
|
||||
const char* fileStr = xmlFont->Attribute("file");
|
||||
if (fileStr) {
|
||||
font.reset(new FontData(os::FontType::kSpriteSheet));
|
||||
font.reset(new FontData(os::FontType::SpriteSheet));
|
||||
font->setFilename(base::join_path(xmlDir, fileStr));
|
||||
}
|
||||
}
|
||||
@ -143,7 +143,7 @@ static FontData* load_font(std::map<std::string, FontData*>& fonts,
|
||||
// The filename can be empty if the font was not found, anyway we
|
||||
// want to keep the font information (e.g. to use the fallback
|
||||
// information of this font).
|
||||
font.reset(new FontData(os::FontType::kTrueType));
|
||||
font.reset(new FontData(os::FontType::FreeType));
|
||||
font->setFilename(fontFilename);
|
||||
font->setAntialias(antialias);
|
||||
|
||||
@ -934,7 +934,7 @@ int SkinTheme::getScrollbarSize()
|
||||
|
||||
gfx::Size SkinTheme::getEntryCaretSize(Widget* widget)
|
||||
{
|
||||
if (widget->font()->type() == os::FontType::kTrueType)
|
||||
if (widget->font()->type() == os::FontType::FreeType)
|
||||
return gfx::Size(2*guiscale(), widget->textHeight());
|
||||
else
|
||||
return gfx::Size(2*guiscale(), widget->textHeight()+2*guiscale());
|
||||
@ -986,7 +986,8 @@ public:
|
||||
void preProcessChar(const int index,
|
||||
const int codepoint,
|
||||
gfx::Color& fg,
|
||||
gfx::Color& bg) override {
|
||||
gfx::Color& bg,
|
||||
const gfx::Rect& charBounds) override {
|
||||
// Normal text
|
||||
auto& colors = SkinTheme::instance()->colors;
|
||||
bg = ColorNone;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -46,6 +46,7 @@
|
||||
#include "os/font.h"
|
||||
#include "os/surface.h"
|
||||
#include "ui/ui.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdarg>
|
||||
@ -621,7 +622,7 @@ void StatusBar::showDefaultText()
|
||||
}
|
||||
else if (App::instance()->mainWindow()->isHomeSelected()) {
|
||||
setStatusText(0, "-- %s %s by David & Gaspar Capello -- Igara Studio --",
|
||||
PACKAGE, VERSION);
|
||||
get_app_name(), get_app_version());
|
||||
}
|
||||
else {
|
||||
clearText();
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -936,7 +936,10 @@ void Tabs::createFloatingOverlay(Tab* tab)
|
||||
// Fill the surface with pink color
|
||||
{
|
||||
os::SurfaceLock lock(surface);
|
||||
surface->fillRect(gfx::rgba(0, 0, 0, 0), gfx::Rect(0, 0, surface->width(), surface->height()));
|
||||
os::Paint paint;
|
||||
paint.color(gfx::rgba(0, 0, 0, 0));
|
||||
paint.style(os::Paint::Fill);
|
||||
surface->drawRect(gfx::Rect(0, 0, surface->width(), surface->height()), paint);
|
||||
}
|
||||
{
|
||||
Graphics g(surface, 0, 0);
|
||||
|
2
src/clip
2
src/clip
@ -1 +1 @@
|
||||
Subproject commit 04fa07966a4d413f102f9c26cde229f0ef369943
|
||||
Subproject commit 8b026c048d775a2e3139e1059636fc5e65ef45b1
|
21
src/config.h
21
src/config.h
@ -1,15 +1,15 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifdef __ASE_CONFIG_H
|
||||
#ifdef __ASEPRITE_CONFIG_H
|
||||
#error You cannot use config.h two times
|
||||
#endif
|
||||
|
||||
#define __ASE_CONFIG_H
|
||||
#define __ASEPRITE_CONFIG_H
|
||||
|
||||
// In MSVC
|
||||
#ifdef _MSC_VER
|
||||
@ -26,21 +26,6 @@
|
||||
#pragma warning(disable:4710)
|
||||
#endif
|
||||
|
||||
// General information
|
||||
#define PACKAGE "Aseprite"
|
||||
#define VERSION "1.3-dev"
|
||||
|
||||
#ifdef CUSTOM_WEBSITE_URL
|
||||
#define WEBSITE CUSTOM_WEBSITE_URL // To test web server
|
||||
#else
|
||||
#define WEBSITE "http://www.aseprite.org/"
|
||||
#endif
|
||||
#define WEBSITE_DOWNLOAD WEBSITE "download/"
|
||||
#define WEBSITE_CONTRIBUTORS WEBSITE "contributors/"
|
||||
#define WEBSITE_NEWS_RSS "http://blog.aseprite.org/rss"
|
||||
#define UPDATE_URL WEBSITE "update/?xml=1"
|
||||
#define COPYRIGHT "Copyright (C) 2001-2019 Igara Studio S.A."
|
||||
|
||||
#include "base/base.h"
|
||||
#include "base/debug.h"
|
||||
#include "base/log.h"
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2019 Igara Studio S.A.
|
||||
// Copyright (c) 2001-2018 David Capello
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -179,6 +179,17 @@ bool Layer::isEditableHierarchy() const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Layer::hasAncestor(const Layer* ancestor) const
|
||||
{
|
||||
Layer* it = parent();
|
||||
while (it) {
|
||||
if (it == ancestor)
|
||||
return true;
|
||||
it = it->parent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Cel* Layer::cel(frame_t frame) const
|
||||
{
|
||||
return nullptr;
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2019 Igara Studio S.A.
|
||||
// Copyright (c) 2001-2018 David Capello
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -91,6 +91,7 @@ namespace doc {
|
||||
|
||||
bool isVisibleHierarchy() const;
|
||||
bool isEditableHierarchy() const;
|
||||
bool hasAncestor(const Layer* ancestor) const;
|
||||
|
||||
void setBackground(bool state) { switchFlags(LayerFlags::Background, state); }
|
||||
void setVisible (bool state) { switchFlags(LayerFlags::Visible, state); }
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -59,7 +59,7 @@ int app_main(int argc, char* argv[])
|
||||
std::srand(static_cast<unsigned int>(std::time(nullptr)));
|
||||
|
||||
#ifdef _WIN32
|
||||
::CoInitialize(NULL);
|
||||
::CoInitialize(nullptr);
|
||||
#endif
|
||||
|
||||
try {
|
||||
@ -70,11 +70,12 @@ int app_main(int argc, char* argv[])
|
||||
os::ScopedHandle<os::System> system(os::create_system());
|
||||
app::App app;
|
||||
|
||||
// Change the name of the memory dump file
|
||||
// Change the memory dump filename to save on disk (.dmp
|
||||
// file). Note: Only useful on Windows.
|
||||
{
|
||||
const std::string filename = app::memory_dump_filename();
|
||||
if (!filename.empty())
|
||||
memoryDump.setFileName(filename);
|
||||
const std::string fn = app::SendCrash::DefaultMemoryDumpFilename();
|
||||
if (!fn.empty())
|
||||
memoryDump.setFileName(fn);
|
||||
}
|
||||
|
||||
const int code = app.initialize(options);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -845,7 +845,9 @@ public:
|
||||
|
||||
void preProcessChar(const int index,
|
||||
const int codepoint,
|
||||
gfx::Color& fg, gfx::Color& bg) override {
|
||||
gfx::Color& fg,
|
||||
gfx::Color& bg,
|
||||
const gfx::Rect& charBounds) override {
|
||||
if (!m_boxes.empty())
|
||||
m_boxes.back().to = index;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -117,7 +117,9 @@ void Graphics::drawHLine(gfx::Color color, int x, int y, int w)
|
||||
dirty(gfx::Rect(m_dx+x, m_dy+y, w, 1));
|
||||
|
||||
os::SurfaceLock lock(m_surface);
|
||||
m_surface->drawHLine(color, m_dx+x, m_dy+y, w);
|
||||
os::Paint paint;
|
||||
paint.color(color);
|
||||
m_surface->drawRect(gfx::Rect(m_dx+x, m_dy+y, w, 1), paint);
|
||||
}
|
||||
|
||||
void Graphics::drawVLine(gfx::Color color, int x, int y, int h)
|
||||
@ -125,7 +127,9 @@ void Graphics::drawVLine(gfx::Color color, int x, int y, int h)
|
||||
dirty(gfx::Rect(m_dx+x, m_dy+y, 1, h));
|
||||
|
||||
os::SurfaceLock lock(m_surface);
|
||||
m_surface->drawVLine(color, m_dx+x, m_dy+y, h);
|
||||
os::Paint paint;
|
||||
paint.color(color);
|
||||
m_surface->drawRect(gfx::Rect(m_dx+x, m_dy+y, 1, h), paint);
|
||||
}
|
||||
|
||||
void Graphics::drawLine(gfx::Color color, const gfx::Point& _a, const gfx::Point& _b)
|
||||
@ -135,7 +139,9 @@ void Graphics::drawLine(gfx::Color color, const gfx::Point& _a, const gfx::Point
|
||||
dirty(gfx::Rect(a, b));
|
||||
|
||||
os::SurfaceLock lock(m_surface);
|
||||
m_surface->drawLine(color, a, b);
|
||||
os::Paint paint;
|
||||
paint.color(color);
|
||||
m_surface->drawLine(a, b, paint);
|
||||
}
|
||||
|
||||
void Graphics::drawRect(gfx::Color color, const gfx::Rect& rcOrig)
|
||||
@ -145,7 +151,10 @@ void Graphics::drawRect(gfx::Color color, const gfx::Rect& rcOrig)
|
||||
dirty(rc);
|
||||
|
||||
os::SurfaceLock lock(m_surface);
|
||||
m_surface->drawRect(color, rc);
|
||||
os::Paint paint;
|
||||
paint.color(color);
|
||||
paint.style(os::Paint::Stroke);
|
||||
m_surface->drawRect(rc, paint);
|
||||
}
|
||||
|
||||
void Graphics::fillRect(gfx::Color color, const gfx::Rect& rcOrig)
|
||||
@ -155,7 +164,10 @@ void Graphics::fillRect(gfx::Color color, const gfx::Rect& rcOrig)
|
||||
dirty(rc);
|
||||
|
||||
os::SurfaceLock lock(m_surface);
|
||||
m_surface->fillRect(color, rc);
|
||||
os::Paint paint;
|
||||
paint.color(color);
|
||||
paint.style(os::Paint::Fill);
|
||||
m_surface->drawRect(rc, paint);
|
||||
}
|
||||
|
||||
void Graphics::fillRegion(gfx::Color color, const gfx::Region& rgn)
|
||||
@ -321,7 +333,8 @@ public:
|
||||
void preProcessChar(const int index,
|
||||
const int codepoint,
|
||||
gfx::Color& fg,
|
||||
gfx::Color& bg) override {
|
||||
gfx::Color& bg,
|
||||
const gfx::Rect& charBounds) override {
|
||||
if (m_surface) {
|
||||
if (m_mnemonic &&
|
||||
// TODO use ICU library to lower unicode chars
|
||||
@ -344,11 +357,16 @@ public:
|
||||
if (!gfx::is_transparent(m_underscoreColor)) {
|
||||
// TODO underscore height = guiscale() should be configurable from ui::Theme
|
||||
int dy = 0;
|
||||
if (m_font->type() == os::FontType::kTrueType) // TODO use other method to locate the underline
|
||||
if (m_font->type() == os::FontType::FreeType) // TODO use other method to locate the underline
|
||||
dy += guiscale();
|
||||
gfx::Rect underscoreBounds(charBounds.x, charBounds.y+charBounds.h+dy,
|
||||
charBounds.w, guiscale());
|
||||
m_surface->fillRect(m_underscoreColor, underscoreBounds);
|
||||
|
||||
os::Paint paint;
|
||||
paint.color(m_underscoreColor);
|
||||
paint.style(os::Paint::Fill);
|
||||
m_surface->drawRect(underscoreBounds, paint);
|
||||
|
||||
m_bounds |= underscoreBounds;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -302,10 +302,11 @@ Widget* Menu::findItemById(const char* id)
|
||||
return result;
|
||||
for (auto child : children()) {
|
||||
if (child->type() == kMenuItemWidget) {
|
||||
result = static_cast<MenuItem*>(child)
|
||||
->getSubmenu()->findItemById(id);
|
||||
if (result)
|
||||
return result;
|
||||
if (Menu* submenu = static_cast<MenuItem*>(child)->getSubmenu()) {
|
||||
result = submenu->findItemById(id);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -1,4 +1,5 @@
|
||||
# ASEPRITE
|
||||
# Copyright (C) 2020 Igara Studio S.A.
|
||||
# Copyright (C) 2001-2017 David Capello
|
||||
|
||||
set(UPDATER_LIB_SOURCES
|
||||
@ -16,4 +17,5 @@ add_library(updater-lib ${UPDATER_LIB_SOURCES})
|
||||
target_link_libraries(updater-lib
|
||||
net-lib
|
||||
cfg-lib
|
||||
ver-lib
|
||||
${TINYXML_LIBRARY})
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -18,6 +19,7 @@
|
||||
#include "net/http_response.h"
|
||||
#include "tinyxml.h"
|
||||
#include "updater/user_agent.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
@ -97,12 +99,7 @@ public:
|
||||
|
||||
bool checkNewVersion(const Uuid& uuid, const std::string& extraParams, CheckUpdateDelegate* delegate)
|
||||
{
|
||||
#ifndef UPDATE_URL
|
||||
#define UPDATE_URL ""
|
||||
#pragma message("warning: Define UPDATE_URL macro")
|
||||
#endif
|
||||
|
||||
std::string url = UPDATE_URL;
|
||||
std::string url = get_app_update_url();
|
||||
if (!uuid.empty()) {
|
||||
url += "&uuid=";
|
||||
url += uuid;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -9,6 +9,9 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "updater/user_agent.h"
|
||||
#include "ver/info.h"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
@ -39,18 +42,7 @@ std::string getUserAgent()
|
||||
std::stringstream userAgent;
|
||||
|
||||
// App name and version
|
||||
|
||||
#ifndef PACKAGE
|
||||
#define PACKAGE ""
|
||||
#pragma message("warning: Define PACKAGE macro")
|
||||
#endif
|
||||
|
||||
#ifndef VERSION
|
||||
#define VERSION ""
|
||||
#pragma message("warning: Define VERSION macro")
|
||||
#endif
|
||||
|
||||
userAgent << PACKAGE << "/" << VERSION << " (";
|
||||
userAgent << get_app_name() << "/" << get_app_version() << " (";
|
||||
|
||||
#if _WIN32
|
||||
|
||||
|
18
src/ver/CMakeLists.txt
Normal file
18
src/ver/CMakeLists.txt
Normal file
@ -0,0 +1,18 @@
|
||||
# ASEPRITE
|
||||
# Copyright (C) 2020 Igara Studio S.A.
|
||||
|
||||
# Version of Aseprite
|
||||
set(VERSION "1.x-dev")
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/generated_version.h.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/generated_version.h")
|
||||
|
||||
# Custom Aseprite website (for testing server-side)
|
||||
if(NOT "${CUSTOM_WEBSITE_URL}" STREQUAL "")
|
||||
add_definitions(-DCUSTOM_WEBSITE_URL="${CUSTOM_WEBSITE_URL}")
|
||||
endif()
|
||||
|
||||
add_library(ver-lib info.c ${gen_ver_fn})
|
||||
add_dependencies(ver-lib generated_version_h)
|
||||
target_include_directories(ver-lib PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
|
1
src/ver/generated_version.h.in
Normal file
1
src/ver/generated_version.h.in
Normal file
@ -0,0 +1 @@
|
||||
#cmakedefine VERSION "@VERSION@"
|
31
src/ver/info.c
Normal file
31
src/ver/info.c
Normal file
@ -0,0 +1,31 @@
|
||||
/* Aseprite
|
||||
Copyright (C) 2020 Igara Studio S.A.
|
||||
|
||||
This program is distributed under the terms of
|
||||
the End-User License Agreement for Aseprite. */
|
||||
|
||||
#include "ver/info.h"
|
||||
#include "generated_version.h" /* It defines the VERSION macro */
|
||||
|
||||
#define PACKAGE "Aseprite"
|
||||
#define COPYRIGHT "Copyright (C) 2001-2020 Igara Studio S.A."
|
||||
|
||||
#ifdef CUSTOM_WEBSITE_URL
|
||||
#define WEBSITE CUSTOM_WEBSITE_URL /* To test web server */
|
||||
#else
|
||||
#define WEBSITE "http://www.aseprite.org/"
|
||||
#endif
|
||||
#define WEBSITE_DOWNLOAD WEBSITE "download/"
|
||||
#define WEBSITE_CONTRIBUTORS WEBSITE "contributors/"
|
||||
#define WEBSITE_NEWS_RSS "http://blog.aseprite.org/rss"
|
||||
#define WEBSITE_UPDATE WEBSITE "update/?xml=1"
|
||||
|
||||
const char* get_app_name() { return PACKAGE; }
|
||||
const char* get_app_version() { return VERSION; }
|
||||
const char* get_app_copyright() { return COPYRIGHT; }
|
||||
|
||||
const char* get_app_url() { return WEBSITE; }
|
||||
const char* get_app_download_url() { return WEBSITE_DOWNLOAD; }
|
||||
const char* get_app_contributors_url() { return WEBSITE_CONTRIBUTORS; }
|
||||
const char* get_app_news_rss_url() { return WEBSITE_NEWS_RSS; }
|
||||
const char* get_app_update_url() { return WEBSITE_UPDATE; }
|
29
src/ver/info.h
Normal file
29
src/ver/info.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* Aseprite
|
||||
Copyright (C) 2020 Igara Studio S.A.
|
||||
|
||||
This program is distributed under the terms of
|
||||
the End-User License Agreement for Aseprite. */
|
||||
|
||||
#ifndef VER_INFO_H_INCLUDED
|
||||
#define VER_INFO_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
const char* get_app_name();
|
||||
const char* get_app_version();
|
||||
const char* get_app_copyright();
|
||||
|
||||
const char* get_app_url();
|
||||
const char* get_app_download_url();
|
||||
const char* get_app_contributors_url();
|
||||
const char* get_app_news_rss_url();
|
||||
const char* get_app_update_url();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VER_INFO_H_INCLUDED */
|
2
third_party/libarchive
vendored
2
third_party/libarchive
vendored
@ -1 +1 @@
|
||||
Subproject commit ca48183b244c549841c33a2863672b46ed3cbe88
|
||||
Subproject commit e1309af03a4bcea2f0f0bb1f48530f2b794cc8b2
|
Loading…
x
Reference in New Issue
Block a user