Skip to content

Commit

Permalink
Merge branch 'v1.6.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
SonarSonic committed Jun 21, 2023
2 parents de6f587 + 9615e00 commit d3ecbfd
Show file tree
Hide file tree
Showing 215 changed files with 2,815 additions and 2,244 deletions.
52 changes: 52 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,55 @@
### [v1.6.0-Beta](https://github.com/SonarSonic/DrawingBotV3/releases/tag/v1.6.0-beta-free)
- **IMPORTANT: Premium Versions now have License Keys**, if you already own the Premium Version you'll find your license key [here](https://drawingbotv3.com/my-account/license_keys/). If you purchase DBV3 Premium in the future you'll also receive this License Key with your Order Confirmation. More details [here](https://drawingbotv3.com/license-keys/).
- **IMPORTANT:** .jar versions of DBV3 will no longer be distributed, please use the dedicated Windows/Mac/Linux installers. This is to allow more advanced features which require specific Java versions, DBV3 now uses JAVA 19.
- Added: **13 NEW PFMS** -
- **Sketch Sweeping Curves**: A new Sketch PFM focused on creating long sweeping curves which are more natural / human-like, focused on creating longer curves. It shares most setting with other Sketch PFMS.
- 'Curvature': Controls the appearance of "knots" in the curve. It translates to spline types: 0 = Uniform Catmull-Rom, 0.5 = Centripetal Catmull-Rom (Default), 1.0 Chordal Catmull-Rom
- **LBG Shapes, Triangulation, Tree, Stippling, Dashes, Letters, Diagram, TSP, Circular Scribbles** - LBS (Linde Buzo Gray) PFMs combine the speed of Adaptive PFMs with the Quality of Voronoi PFMs and in most cases will outperform both in detail retention. They also respond better to large variations in stipple spacing.
- 'Stipple Radius Min/Max' - Controls the spacing of the stipple points, smaller stipple radii will result in more detailed results.-
- 'Density' - Controls the tone of the resulting image, a low density will be low contrast and may lose detail when the min/max stipple radius are far apart, a high density will be high contrast and retain more detail but will result in longer plotting times.
- 'Threshold' - Controls the luminance at which stipples will stop being placed, similar to "Ignore White" but with finer control.
- 'Max Iteration' - The number of times the stipple points will be refined, far fewer iterations are required to get good results than with Voronoi PFMs
- **LBG Quad Tiles**: An LBG PFM which currently has no Voronoi / Adaptive counterpart, this PFM draws a Quad Tree from the LBS Stippling points.
- **ECS Drawing:** This PFM has three separate components **E**dge Detection, **C**ontour Detection & **S**hading. Each component can be controlled independently, you can also run them individually and then combine ECS with other PFMs instead using PFM Layers.
- 'Simplify' - Simplifies the Edges & Contours generated.
- 'Draw Edges' - Disables/Enables edge detection.
- 'Edge Blur' - Affects the pre-filter blur applied before edges are detected, higher edge blur will result in less edges but the edges will be smoother.
- 'Edge Threshold' - Controls the amount of edges which are generated: lower threshold -> more edges : higher threshold -> less edges
- 'Draw Contours' - Disables/Enables contour detection.
- 'Contour Blur' - Similar to Edge Blur but for contours, has a greater impact on the amount of contours and quality of the contours.
- 'Contour Detail' - Controls the amount of contours to be generated.
- 'Draw Shading' - Disables/Enables shading. The shading component uses a simplified version of the Sketch Lines shading feature, you may choose to disable the shading entirely and overlay another Sketch PFM using PFM Layers.
- 'Shading Threshold' - Controls the luminance at which shading will be stopped: lower -> less shading : higher -> more shading
- 'Shading Detail' - Controls the accuracy of the shading: lower -> less accurate, more stylised : higher -> more accurate, less stylised
- 'Shading Length' - Controls the maximum length of the lines which make up the shading.
- **Pen Calibration:** This PFM is used for generating Pen Calibration tests which can be used to select the most accurate nib size for "Rescale to Pen Width". Choose a suitable Nib Size range for the pen you wish to test and then plot the test. Then set your Pen Width for future plots with that pen to the highest nib size which has no gaps between the lines.
- 'Nib Size Min' - The smallest nib size to test
- 'Nib Size Max' - The largest nib size to test
- 'Test Count' - The number of tests to run between the Min/Max nib size
- 'Rotation' - Controls the angle of the lines in the generated line tests
- 'Line Tests' - Generates simple hatches line tests
- 'Circle Tests' - Generates concentric circle tests
- 'Test Size' - The width/height in mm of each nib size test
- 'Spacing X/Y' - The grid spacing in mm between each test in the grid
- 'SVG Font' - The SVG Font to use to draw the labels for each nib size test
- 'Title' - An optional title to draw at the top of page, you can leave this blank to have no title.
- 'Font Size' - The height in mm of the label/title text.
- Added: **New Image Filter "Custom Overlay"** - import Black & White image overlays to create new unique styles!
- Added: **New PFM Setting - 'Draw Outlines'** - Draws the outlines of the shapes generated by Mosaic PFMS, great for creating more stylised results!
- Added: **CMYK Offset Settings** & **CMYK Display Settings** - Controlled in the "Configure" panel, Offset settings allow you to slightly offset each colour channel, display settings allow you to control the opacity of the pens, it will automatically update the colour of the pens and re-draw the drawing (this is a on-screen change only).
- Added: **LP Space** - A new shape type available in Voronoi Shapes / Adaptive Shapes / LBG Shapes - it roughly imitates the LP Space/p-norm function to create shapes which vary from Diamond -> Circle -> Rounded Square. This shape type can better represent the tonality of the original image by adjusting its shape to match. It also produces more variety in the final drawing.
- Added: **New Special Pens: Original Colour (Inverted), Original Grayscale (Inverted)** - Samples the original colour of the source image and inverts it, for use with Digital Only outputs. Great for creating stylised Digital Drawings on a black background.
- Added: "Distortion" setting to all Dashes PFMs
- Added: "Clarity" setting to Sketch PFMs, which increases sharpness and detail in the final output, behind the scenes this effectively adds a Unsharp Mask Filter too the image before processing.
- Improved: Drawing Pen presets now be created easily with "New Preset" - you can select from existing categories and choose a colour
- Improved: Setting pop up windows for Colour Separation / Image Filters / Presets have been improved and standardised
- Improved: Console/Error Logging - log files will now be exported to the Config Folder / Logs, the last 10 logs will be retained
- Improved: Circular Scribbles curve quality
- Fixed: Projects with multiple versions creating massive project files which may fail to load.
- Fixed: Mosaic PFMs not responding in some situations
- Fixed: Batch Processing now supports SVG Files and all Image File types.
- Fixed: UI State Reloading

### [v1.5.3-stable](https://github.com/SonarSonic/DrawingBotV3/releases/tag/v1.5.3-stable-free)
- Added: "Create Curves" option to Voronoi TSP, matching Adaptive TSP.
- Improved: Stars & Triangles in Adaptive Shapes are now symmetrical
Expand Down
14 changes: 7 additions & 7 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ plugins {
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.13'
id 'com.github.johnrengelman.shadow' version '7.1.2'
id "org.beryx.runtime" version "1.12.7"
id "org.beryx.runtime" version "1.13.0"
}

apply plugin: 'org.openjfx.javafxplugin'
apply plugin: 'com.github.johnrengelman.shadow'

repositories {
jcenter()
mavenCentral()
flatDir {
dirs 'libs'
Expand Down Expand Up @@ -44,10 +43,11 @@ dependencies {
implementation "com.aparapi:aparapi:${aparapi_version}"
implementation "org.controlsfx:controlsfx:${controlsfx_version}"
implementation "org.sejda.imageio:webp-imageio:${webp_imageio_version}" //google webp support
implementation 'org.fxmisc.easybind:easybind:1.0.3'
implementation "org.fxmisc.easybind:easybind:${easy_bind_version}"

//required for cross platform compatibility, src: https://stackoverflow.com/questions/61579722/making-a-cross-platform-build-of-javafx-using-gradle

/*
implementation group: 'org.openjfx', name: 'javafx-base', version: javaFX_version, classifier: 'win'
implementation group: 'org.openjfx', name: 'javafx-base', version: javaFX_version, classifier: 'mac'
implementation group: 'org.openjfx', name: 'javafx-base', version: javaFX_version, classifier: 'linux'
Expand All @@ -63,14 +63,14 @@ dependencies {
implementation group: 'org.openjfx', name: 'javafx-swing', version: javaFX_version, classifier: 'win'
implementation group: 'org.openjfx', name: 'javafx-swing', version: javaFX_version, classifier: 'mac'
implementation group: 'org.openjfx', name: 'javafx-swing', version: javaFX_version, classifier: 'linux'

*/
//// JOGL
implementation "org.jogamp.gluegen:gluegen-rt-main:${jogl_version}"
implementation "org.jogamp.jogl:jogl-all-main:${jogl_version}"
}

//targetCompatibility = "11"
//sourceCompatibility = "11"
targetCompatibility = "19"
sourceCompatibility = "19"

project.setArchivesBaseName(app_name + "-" + app_version + "-" + app_state)
project.setApplicationName(app_name)
Expand Down Expand Up @@ -120,7 +120,7 @@ runtime {
imageOptions += ["--verbose"]
installerOptions += ["--verbose", '--mac-package-name', "drawingbotv3"]
if(project.hasProperty("developer")){
String id = project.getProperty("developer");
String id = project.getProperty("developer")
project.logger.lifecycle('Found a developer id, adding mac-signing')
imageOptions += ['--mac-sign', "--mac-signing-key-user-name", id]
installerOptions += ['--mac-sign', "--mac-signing-key-user-name", id]
Expand Down
10 changes: 5 additions & 5 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#app version
app_name=DrawingBotV3-Free
app_version=1.5.3
app_state=stable
app_version=1.6.0
app_state=beta

javaFX_version=17.0.2
javaFX_version=17.0.7

#tests
junit_version=4.13
Expand All @@ -19,11 +19,11 @@ xml_graphics_version=1.16
commons_math3_version=3.6.1
controlsfx_version=11.1.2
jhlabs_version=2.0.235-1
joml_version=1.10.4
joml_version=1.10.5
jcodec_version=0.2.5
bcel_version=6.5.0
aparapi_version=3.0.0
jogl_version=2.3.2
apache_commons_version=3.12.0
webp_imageio_version=0.1.6
fx_gson_version=4.0.1
easy_bind_version=1.0.3
94 changes: 33 additions & 61 deletions src/main/java/drawingbot/DrawingBotV3.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.logging.Level;
import java.util.logging.Logger;

Expand All @@ -18,6 +19,7 @@
import drawingbot.files.loaders.AbstractFileLoader;
import drawingbot.image.format.FilteredImageData;
import drawingbot.integrations.vpype.VpypeSettings;
import drawingbot.javafx.FXController;
import drawingbot.javafx.preferences.DBPreferences;
import drawingbot.plotting.ITaskManager;
import drawingbot.javafx.*;
Expand Down Expand Up @@ -91,7 +93,7 @@ public class DrawingBotV3 {
public final MonadicBinding<String> projectNameBinding = EasyBind.select(activeProject).selectObject(project -> project.name);
public final MonadicBinding<FilteredImageData> imageBinding = EasyBind.select(activeProject).selectObject(project -> project.openImage);
public final MonadicBinding<PlottedDrawing> drawingBinding = EasyBind.select(activeProject).selectObject(project -> project.currentDrawing);
public final MonadicBinding<PFMTask> activeTaskBinding = EasyBind.select(activeProject).selectObject(project -> project.activeTask);
public final MonadicBinding<DBTask<?>> activeTaskBinding = EasyBind.select(activeProject).selectObject(project -> project.activeTask);
public final MonadicBinding<PFMTask> renderedTaskBinding = EasyBind.select(activeProject).selectObject(project -> project.renderedTask);
public final MonadicBinding<ObservableList<ExportedDrawingEntry>> exportedDrawingsBinding = EasyBind.select(activeProject).selectObject(project -> project.exportedDrawings);

Expand Down Expand Up @@ -173,7 +175,7 @@ public void updateLocalProgress(double progress){
public void tick(){

// Update the latest shapes/vertices counts from the active task
PFMTask activeTask = context().taskManager().getActiveTask();
PFMTask renderedTask = context().taskManager().getRenderedTask();
PlottedDrawing currentDrawing = context().taskManager().getCurrentDrawing();
FilteredImageData openImage = project().openImage.get();

Expand Down Expand Up @@ -207,10 +209,10 @@ public void tick(){
}

// Update Drawing Stats
if(activeTask != null){
geometryCount.set(activeTask.getCurrentGeometryCount());
vertexCount.set(activeTask.getCurrentVertexCount());
elapsedTimeMS.set(activeTask.getElapsedTime());
if(renderedTask != null){
geometryCount.set(renderedTask.getCurrentGeometryCount());
vertexCount.set(renderedTask.getCurrentVertexCount());
elapsedTimeMS.set(renderedTask.getElapsedTime());
}else if(currentDrawing != null){
geometryCount.set(currentDrawing.getDisplayedShapeMax() - currentDrawing.getDisplayedShapeMin());
vertexCount.set(currentDrawing.getDisplayedVertexCount());
Expand Down Expand Up @@ -319,29 +321,27 @@ public void resetTaskService(){
///////////////////////////////////////////////////////////////////////////////////////////////////////


public void openFile(DBTaskContext context, File file, boolean internal, boolean changeDisplayMode) {
AbstractFileLoader loadingTask = getImageLoaderTask(context, file, internal, changeDisplayMode);
public void openFile(DBTaskContext context, File file, boolean internal, boolean isSubTask) {
AbstractFileLoader loadingTask = getImageLoaderTask(context, file, internal, isSubTask);
if(loadingTask != null){
taskMonitor.queueTask(loadingTask);
}
}

public AbstractFileLoader getImageLoaderTask(DBTaskContext context, File file, boolean internal, boolean changeDisplayMode){
AbstractFileLoader loadingTask = MasterRegistry.INSTANCE.getFileLoader(context, file, internal);
public AbstractFileLoader getImageLoaderTask(DBTaskContext context, File file, boolean internal, boolean isSubTask){
AbstractFileLoader loadingTask = MasterRegistry.INSTANCE.getFileLoader(context, file, internal, isSubTask);

//if the file loader could provide an image, wipe the current one
if(loadingTask.hasImageData() && context.project.activeTask.get() != null){
if(!isSubTask && loadingTask.hasImageData() && context.project.activeTask.get() != null){
context.project.activeTask.get().cancel();
context.taskManager().setActiveTask(null);
context.project.openImage.set(null);
}

loadingTask.setOnSucceeded(e -> {
if(e.getSource().getValue() != null){
if(!isSubTask && e.getSource().getValue() != null){
context.project.openImage.set((FilteredImageData) e.getSource().getValue());
if(changeDisplayMode){
Platform.runLater(() -> context.project().setDisplayMode(Register.INSTANCE.DISPLAY_MODE_IMAGE));
}
Platform.runLater(() -> context.project().setDisplayMode(Register.INSTANCE.DISPLAY_MODE_IMAGE));
projectName.set(file.getName());
}
loadingTask.onFileLoaded();
Expand Down Expand Up @@ -395,6 +395,7 @@ public void resetView(){
DrawingBotV3.INSTANCE.controller.viewportScrollPane.setHvalue(0.5);
DrawingBotV3.INSTANCE.controller.viewportScrollPane.setVvalue(0.5);
DrawingBotV3.INSTANCE.controller.viewportScrollPane.setScale(project().dpiScaling.get() ? getDPIScaleFactor() / DrawingBotV3.RENDERER.canvasScaling : 1);
DrawingBotV3.INSTANCE.displayMode.get().getRenderer().updateCanvasPosition();
DrawingBotV3.INSTANCE.controller.viewportScrollPane.layout();
DrawingBotV3.INSTANCE.controller.viewportScrollPane.setHvalue(0.5);
DrawingBotV3.INSTANCE.controller.viewportScrollPane.setVvalue(0.5);
Expand Down Expand Up @@ -465,71 +466,42 @@ public void startTask(ExecutorService service, Task<?> task){
taskMonitor.logTask(task);
}

public final Thread.UncaughtExceptionHandler exceptionHandler = (thread, throwable) -> {
DrawingBotV3.logger.log(Level.SEVERE, "Thread Exception: " + thread.getName(), throwable);
};

public ExecutorService initTaskService(){
return Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r, "DrawingBotV3 - Task Thread");
t.setDaemon(true);
t.setUncaughtExceptionHandler(exceptionHandler);
return t;
});
return Executors.newSingleThreadExecutor(threadFactory("DrawingBotV3 - Task Runner"));
}

public ExecutorService initBackgroundService(){
return Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r, "DrawingBotV3 - Background Thread");
t.setDaemon(true);
t.setUncaughtExceptionHandler(exceptionHandler);
return t ;
});
return Executors.newSingleThreadExecutor(threadFactory("DrawingBotV3 - Main Background"));
}

public ExecutorService initLazyBackgroundService(){
return Executors.newCachedThreadPool(r -> {
Thread t = new Thread(r, "DrawingBotV3 - Background Thread");
t.setDaemon(true);
t.setUncaughtExceptionHandler(exceptionHandler);
return t ;
});
}

public ExecutorService initImageLoadingService(){
return Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r, "DrawingBotV3 - Image Loading Thread");
t.setDaemon(true);
t.setUncaughtExceptionHandler(exceptionHandler);
return t;
});
return Executors.newCachedThreadPool(threadFactory("DrawingBotV3 - Lazy Background"));
}

public ExecutorService initImageFilteringService(){
return Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r, "DrawingBotV3 - Image Filtering Thread");
t.setDaemon(true);
t.setUncaughtExceptionHandler(exceptionHandler);
return t;
});
return Executors.newSingleThreadExecutor(threadFactory("DrawingBotV3 - Image Filtering"));
}

public ExecutorService initParallelPlottingService(){
return Executors.newFixedThreadPool(5, r -> {
Thread t = new Thread(r, "DrawingBotV3 - Parallel Plotting Service");
t.setDaemon(true);
t.setUncaughtExceptionHandler(exceptionHandler);
return t;
});
return Executors.newFixedThreadPool(5, threadFactory("DrawingBotV3 - Parallel Plotting"));
}

public ExecutorService initSerialConnectionService(){
return Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r, "DrawingBotV3 - Serial Connection Writing Service");
return Executors.newSingleThreadExecutor(threadFactory("DrawingBotV3 - Serial Connection Writing"));
}

public final static Thread.UncaughtExceptionHandler exceptionHandler = (thread, throwable) -> {
DrawingBotV3.logger.log(Level.SEVERE, "Thread Exception: " + thread.getName(), throwable);
};

public static ThreadFactory threadFactory(String name){
return r -> {
Thread t = new Thread(r, name);
t.setDaemon(true);
t.setUncaughtExceptionHandler(exceptionHandler);
return t;
});
};
}

///////////////////////////////////////////////////////////////////////////////////////////////////////
}
Loading

0 comments on commit d3ecbfd

Please sign in to comment.