View Javadoc

1   /*
2    * Copyright (c) 2003-2008 by Cosylab d. d.
3    *
4    * This file is part of CosyBeans-Common.
5    *
6    * CosyBeans-Common is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU General Public License as published by
8    * the Free Software Foundation, either version 3 of the License, or
9    * (at your option) any later version.
10   *
11   * CosyBeans-Common is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.
15   *
16   * You should have received a copy of the GNU General Public License
17   * along with CosyBeans-Common.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  
20  package com.cosylab.gui.components.ledder;
21  import java.awt.Color;
22  
23  /**
24   * This is a specialized class for rendering LED icons. It is implemented as a
25   * minimal ray-tracer with specular lighting overlay rendering.<p>
26   * NOTE: Due to performance reasons this class is not thread-safe and should 
27   * not be shared in multiple instances.
28   * 
29   * @author <a href="mailto:ales.pucelj@cosylab.com">Ales Pucelj</a>
30   * @version $id$
31   */
32  public class LedRenderer {
33  
34  	private int centerX;
35  	private int centerY;
36  
37  	private double radiusOffset;
38  
39  	private int radius;
40  
41  	private int red;
42  	private int green;
43  	private int blue;
44  
45  	private double highlightFactor = 0.85;
46  	private double highlightFocus = 3;
47  
48  	private double shadowIntensity = 1.5;
49  
50  	private int ro1;
51  	private int ro2;
52  
53  	private final float[] colorHSB = new float[3];
54  
55  	private double[] l = getLight(-0.2, -0.5);
56  
57  	/**
58  	 * @param x int
59  	 * @param y int
60  	 * @param r int
61  	 * @param lpp LedPaintParameters
62  	 */
63  	public LedRenderer(int x, int y, int r, LedPaintParameters lpp) {
64  		super();
65  
66  		centerX = x;
67  		centerY = y;
68  		radius = r;
69  
70  		l = getLight(lpp.lightX, lpp.lightY);
71  
72  		highlightFactor = lpp.highlightFactor;
73  		highlightFocus = lpp.highlightFocus;
74  		shadowIntensity = lpp.shadowIntensity;
75  
76  		radiusOffset = (1 - lpp.borderSize) * radius;
77  		ro1 = (int) (radiusOffset * radiusOffset);
78  		ro2 = radius * radius;
79  
80  		red = lpp.color.getRed();
81  		green = lpp.color.getGreen();
82  		blue = lpp.color.getBlue();
83  
84  	}
85  
86  	/**
87  	 * @param x double
88  	 * @param p double
89  	 * @return float
90  	 */
91  	private final float getHighlight(double x, final double p) {
92  
93  		x = (x - highlightFactor) / (1 - highlightFactor);
94  
95  		return (float) ((x < 0) ? p : p * (1 - Math.pow(x, highlightFocus)));
96  	}
97  
98  	/**
99  	 * @param x double
100 	 * @param p double
101 	 * @return float
102 	 */
103 	private final float getIntensity(final double x, final double p) {
104 		return (float) (p * Math.pow(x, shadowIntensity));
105 		//		return (float) (p * x * x * shadowIntensity);
106 	}
107 
108 	/**
109 	 * @param angle double
110 	 * @return int
111 	 */
112 	private final int getColor(final double angle) {
113 		Color.RGBtoHSB(red, green, blue, colorHSB);
114 
115 		return Color.HSBtoRGB(
116 			colorHSB[0],
117 			getHighlight(angle, colorHSB[1]),
118 			getIntensity(angle, colorHSB[2]));
119 	}
120 
121 	/**
122 	 * @param x double
123 	 * @param y double
124 	 * @param v double[]
125 	 * @return double[]
126 	 */
127 	public double[] getLight(double x, double y) {
128 		double[] v = new double[3];
129 		v[0] = x;
130 		v[1] = y;
131 		v[2] = Math.sqrt(1.0 - x * x - y * y);
132 
133 		return v;
134 	}
135 
136 	/**
137 	 * @param x int
138 	 * @param y int
139 	 * @param w int
140 	 * @param h int
141 	 * @return int[]
142 	 */
143 	public final int[] renderSection(
144 		final int x,
145 		final int y,
146 		final int w,
147 		final int h) {
148 
149 		final int[] data = new int[w * h * 4];
150 
151 		int col;
152 		int base = 0;
153 		double dot;
154 		double angle;
155 
156 		for (int py = 0; py < h; py++) {
157 
158 			base = 4 * (py * w);
159 			int dy = y + py - centerY;
160 			int dx = x - centerX;
161 
162 			for (int px = 0; px < w; px++) {
163 
164 				int d = dx * dx + dy * dy;
165 
166 				if (d < ro1) {
167 
168 					dot = dx * l[0]	+ dy * l[1]	+ Math.sqrt(ro2 - d) * l[2];
169 
170 					angle = (1 + dot / radius) / 2;
171 
172 					col = getColor(angle);
173 
174 				} else {
175 					col = (d <= ro2) ? 0xFF000000 : 0x0;
176 				}
177 
178 				data[base + 0] = (col >> 0x10) & 0xFF;
179 				data[base + 1] = (col >> 0x08) & 0xFF;
180 				data[base + 2] = (col >> 0x00) & 0xFF;
181 				data[base + 3] = (col >> 0x18) & 0xFF;
182 
183 				base += 4;
184 				dx++;
185 			}
186 		}
187 		return data;
188 	}
189 }