/*
    Copyright (C) 2008  Paul Richards.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package fractals;

import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;

final class Utilities
{
    private static final ScheduledExecutorService lightThreadPool;
    private static final ScheduledExecutorService heavyThreadPool;
    
    static {
        final int lightThreadCount = 2;
        final ThreadFactory lightThreadFactory = new ThreadFactory(){
            public Thread newThread(Runnable r) {
                Thread result = new Thread(r);
                result.setDaemon(true);
                return result;
            }
        };
        lightThreadPool = new ScheduledThreadPoolExecutor(lightThreadCount, lightThreadFactory);
    }
    
    static {
        final int heavyThreadCount = Runtime.getRuntime().availableProcessors();
        final ThreadFactory heavyThreadFactory = new ThreadFactory(){
            public Thread newThread(Runnable r) {
                Thread result = new Thread(r);
                result.setDaemon(true);
                result.setPriority(Thread.MIN_PRIORITY);
                return result;
            }
        };
        heavyThreadPool = new ScheduledThreadPoolExecutor(heavyThreadCount, heavyThreadFactory);
    }
    
    private Utilities()
    {
    }
    
    static void setGraphicsToHighQuality(Graphics2D g)
    {
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    }
    
    static void setGraphicsToLowQuality(Graphics2D g)
    {
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
    }
    
    /**
        Simplistic exposure function that returns 1.0 - e^(-exposure * value).
    */
    static double expose(double value, double exposure)
    {
        return 1.0 - Math.exp(-exposure * value);
    }
    
    /**
        A thread pool intended for light background tasks (e.g. to triggering repaints).
    */
    static ScheduledExecutorService getLightThreadPool()
    {
        return lightThreadPool;
    }
    
    /**
        A thread pool intended for heavy background tasks (e.g. rendering).
    */
    static ScheduledExecutorService getHeavyThreadPool()
    {
        return heavyThreadPool;
    }
    
    /**
        Clamps the value 'x' to be in the range [min, max].
    */
    static int clamp(final int min, final int x, final int max)
    {
        if (max < min) {
            throw new IllegalArgumentException("Max is less than min");
        }
        return Math.max(min, Math.min(max, x));
    }
    
    /**
        Copies an array of doubles, returns the new copy.
    */
    static double[] copyDoubleArray(double[] source)
    {
        final double[] result = new double[source.length];
        System.arraycopy(source, 0, result, 0, source.length);
        return result;
    }
}

@@ -18,16 +18,22 @@
 (C) 2008
+, 2009
   Paul R
@@ -1025,188 +1025,223 @@
 Pool
-;%0A    private static final ScheduledExecutorService heavyThreadPool;%0A    %0A    static %7B%0A        final int lightThreadCount = 2;%0A        final ThreadFactory lightThreadFactory =
+ =%0A            new ScheduledThreadPoolExecutor(2, new MyThreadFactory(Thread.NORM_PRIORITY));%0A    private static final ScheduledExecutorService heavyThreadPool =%0A            new ScheduledThreadPoolExecutor(2,
  new 
+My
 Thre
@@ -1254,192 +1254,132 @@
 ory(
-)%7B%0A            public Thread newThread(Runnable r) %7B%0A                Thread result = new Thread(r);%0A                result.setDaemon(true);%0A                return result;%0A            %7D
+(Thread.NORM_PRIORITY + Thread.MIN_PRIORITY) / 2));%0A    private static final ScheduledExecutorService backgroundThreadPool =
 %0A   
@@ -1387,36 +1387,11 @@
     
-%7D;%0A
    
-     lightThreadPool =
  new
@@ -1423,226 +1423,277 @@
 tor(
-lightThreadCount, lightThreadFactory);%0A    %7D%0A    %0A    static %7B%0A        final int heavyThreadCount = Runtime.getRuntime().availableProcessors();%0A        final ThreadFactory heavyThreadFactory = new ThreadFactory()%7B%0A    
+2, new MyThreadFactory(Thread.MIN_PRIORITY));%0A%0A    private static final class MyThreadFactory implements ThreadFactory%0A    %7B%0A        final int priority;%0A%0A        MyThreadFactory(int priority)%0A        %7B%0A            this.priority = priority;%0A        %7D%0A%0A        @Override%0A
     
@@ -1746,20 +1746,16 @@
         
-    
 Thread r
@@ -1781,36 +1781,32 @@
 r);%0A            
-   
- 
 result.setDaemon
@@ -1803,26 +1803,28 @@
 .set
-Daemon(true);%0A    
+Priority(priority);%0A
     
@@ -1845,202 +1845,65 @@
 .set
-Priority(Thread.MIN_PRIORITY);%0A                return result;%0A            %7D%0A        %7D;%0A        heavyThreadPool = new ScheduledThreadPoolExecutor(heavyThreadCount, heavyThreadFactory);
+Daemon(true);%0A            return result;%0A        %7D
 %0A    %7D%0A
-    
 %0A   
@@ -2940,32 +2940,74 @@
 r heavy 
-background tasks
+tasks that benefit image quality%0A        in the short term
  (e.g. r
@@ -3014,16 +3014,28 @@
 endering
+, projecting
 ).%0A    *
@@ -3128,32 +3128,313 @@
 hreadPool;%0A    %7D
+%0A%0A    /**%0A        A thread pool intended for heavy tasks that benefit image quality%0A        in the long term (e.g. further sampling expected to take many seconds).%0A    */%0A    static ScheduledExecutorService getBackgroundThreadPool()%0A    %7B%0A        return backgroundThreadPool;%0A    %7D
 %0A    %0A    /**%0A  

Tweak utilities to allow for another teir of background processing.