001: /*
002: * Copyright (c) 2005-2008 Substance Kirill Grouchnikov. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of Substance Kirill Grouchnikov nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030: package org.jvnet.substance.painter;
031:
032: import java.awt.*;
033: import java.awt.image.BufferedImage;
034:
035: import org.jvnet.substance.color.ColorScheme;
036: import org.jvnet.substance.utils.SubstanceColorUtilities;
037: import org.jvnet.substance.utils.SubstanceCoreUtilities;
038:
039: /**
040: * Gradient painter that returns images with subtle 3D gradient appearance. This
041: * class is part of officially supported API.
042: *
043: * @author Kirill Grouchnikov
044: */
045: public class StandardGradientPainter extends BaseGradientPainter {
046: /*
047: * (non-Javadoc)
048: *
049: * @see org.jvnet.substance.painter.SubstanceGradientPainter#getDisplayName()
050: */
051: public String getDisplayName() {
052: return "Standard";
053: }
054:
055: /*
056: * (non-Javadoc)
057: *
058: * @see org.jvnet.substance.painter.SubstanceGradientPainter#getContourBackground(int,
059: * int, java.awt.Shape, boolean, org.jvnet.substance.color.ColorScheme,
060: * org.jvnet.substance.color.ColorScheme, float, boolean, boolean)
061: */
062: public BufferedImage getContourBackground(int width, int height,
063: Shape contour, boolean isFocused, ColorScheme colorScheme1,
064: ColorScheme colorScheme2, float cyclePos, boolean hasShine,
065: boolean useCyclePosAsInterpolation) {
066:
067: BufferedImage mixResult = this .getMixContourBackground(width,
068: height, contour, isFocused, colorScheme1, colorScheme2,
069: cyclePos, hasShine, useCyclePosAsInterpolation);
070: if (mixResult != null)
071: return mixResult;
072:
073: // long millis = System.nanoTime();
074:
075: BufferedImage image = SubstanceCoreUtilities.getBlankImage(
076: width, height);
077: Graphics2D graphics = (Graphics2D) image.getGraphics();
078: graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
079: RenderingHints.VALUE_ANTIALIAS_ON);
080:
081: ColorScheme interpolationScheme1 = colorScheme1;
082: ColorScheme interpolationScheme2 = useCyclePosAsInterpolation ? colorScheme2
083: : colorScheme1;
084:
085: double cycleCoef = 1.0 - cyclePos / 10.0;
086:
087: // Color topBorderColor = this.getTopBorderColor(interpolationScheme1,
088: // interpolationScheme2, cycleCoef, useCyclePosAsInterpolation);
089: // Color midBorderColor = this.getMidBorderColor(interpolationScheme1,
090: // interpolationScheme2, cycleCoef, useCyclePosAsInterpolation);
091: // Color bottomBorderColor = this.getBottomBorderColor(
092: // interpolationScheme1, interpolationScheme2, cycleCoef,
093: // useCyclePosAsInterpolation);
094: Color topFillColor = this .getTopFillColor(interpolationScheme1,
095: interpolationScheme2, cycleCoef,
096: useCyclePosAsInterpolation);
097: Color midFillColorTop = this .getMidFillColorTop(
098: interpolationScheme1, interpolationScheme2, cycleCoef,
099: useCyclePosAsInterpolation);
100: Color midFillColorBottom = this .getMidFillColorBottom(
101: interpolationScheme1, interpolationScheme2, cycleCoef,
102: useCyclePosAsInterpolation);
103: Color bottomFillColor = this .getBottomFillColor(
104: interpolationScheme1, interpolationScheme2, cycleCoef,
105: useCyclePosAsInterpolation);
106: Color topShineColor = this .getTopShineColor(
107: interpolationScheme1, interpolationScheme2, cycleCoef,
108: useCyclePosAsInterpolation);
109: Color bottomShineColor = this .getBottomShineColor(
110: interpolationScheme1, interpolationScheme2, cycleCoef,
111: useCyclePosAsInterpolation);
112:
113: graphics.setStroke(new BasicStroke((float) 1.3,
114: BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
115:
116: // Fill background
117: // long millis000 = System.nanoTime();
118:
119: graphics.setClip(contour);
120: GradientPaint gradientTop = new GradientPaint(0, 0,
121: topFillColor, 0, height / 2, midFillColorTop);
122: graphics.setPaint(gradientTop);
123: graphics.fillRect(0, 0, width, height / 2);
124:
125: GradientPaint gradientBottom = new GradientPaint(0, height / 2,
126: midFillColorBottom, 0, height - 2, bottomFillColor);
127: graphics.setPaint(gradientBottom);
128: graphics.fillRect(0, height / 2, width, height - height / 2);
129: // long millis001 = System.nanoTime();
130:
131: // long millis003 = 0, millis004 = 0, millis005 = 0;
132: if (hasShine && (topShineColor != null)
133: && (bottomShineColor != null)) {
134: int shineHeight = (int) (height / 1.8);
135: int kernelSize = (int) Math.min(12, Math.pow(Math.min(
136: width, height), 0.8) / 4);
137: if (kernelSize < 3)
138: kernelSize = 3;
139:
140: BufferedImage blurredGhostContour = SubstanceCoreUtilities
141: .getBlankImage(width + 2 * kernelSize, height + 2
142: * kernelSize);
143: Graphics2D blurredGhostGraphics = (Graphics2D) blurredGhostContour
144: .getGraphics().create();
145: blurredGhostGraphics.setRenderingHint(
146: RenderingHints.KEY_ANTIALIASING,
147: RenderingHints.VALUE_ANTIALIAS_ON);
148:
149: blurredGhostGraphics.setColor(Color.black);
150: blurredGhostGraphics.translate(kernelSize, kernelSize);
151: int step = kernelSize > 5 ? 2 : 1;
152: for (int strokeSize = 2 * kernelSize - 1; strokeSize > 0; strokeSize -= step) {
153: float transp = 1.0f - strokeSize / (2.0f * kernelSize);
154: blurredGhostGraphics.setComposite(AlphaComposite
155: .getInstance(AlphaComposite.SRC, transp));
156: blurredGhostGraphics.setStroke(new BasicStroke(
157: strokeSize));
158: // double scaleX = 1.0f - 0.1 * strokeSize / kernelSize;
159: // // double newCenterX = scaleX * (kernelSize + width / 2.0);
160: // AffineTransform transform = AffineTransform.getScaleInstance(
161: // 1.0, scaleX);
162: // transform.concatenate(AffineTransform.getTranslateInstance(
163: // kernelSize, kernelSize / scaleX));
164: // // AffineTransform transform =
165: // // AffineTransform.getTranslateInstance(
166: // // kernelSize + width / 2.0 - newCenterX, 0);
167: // blurredGhostGraphics.setTransform(transform);
168: blurredGhostGraphics.draw(contour);
169: }
170: blurredGhostGraphics.dispose();
171:
172: // millis003 = System.nanoTime();
173:
174: BufferedImage reverseGhostContour = SubstanceCoreUtilities
175: .getBlankImage(width + 2 * kernelSize, height + 2
176: * kernelSize);
177: Graphics2D reverseGraphics = (Graphics2D) reverseGhostContour
178: .getGraphics();
179: Color bottomShineColorTransp = new Color(bottomShineColor
180: .getRed(), bottomShineColor.getGreen(),
181: bottomShineColor.getBlue(), 64);
182: GradientPaint gradientShine = new GradientPaint(0,
183: kernelSize, topShineColor, 0, kernelSize
184: + shineHeight, bottomShineColorTransp);
185: reverseGraphics.setPaint(gradientShine);
186: reverseGraphics.fillRect(0, kernelSize, width + 2
187: * kernelSize, kernelSize + shineHeight);
188: reverseGraphics.setComposite(AlphaComposite.DstOut);
189: reverseGraphics.drawImage(blurredGhostContour, 0, 0, null);
190: // millis004 = System.nanoTime();
191:
192: graphics
193: .drawImage(reverseGhostContour, 0, 0, width - 1,
194: shineHeight, kernelSize, kernelSize,
195: kernelSize + width - 1, kernelSize
196: + shineHeight, null);
197:
198: BufferedImage overGhostContour = SubstanceCoreUtilities
199: .getBlankImage(width + 2 * kernelSize, height + 2
200: * kernelSize);
201: Graphics2D overGraphics = (Graphics2D) overGhostContour
202: .getGraphics();
203: overGraphics.setPaint(new GradientPaint(0, kernelSize,
204: topFillColor, 0, kernelSize + height / 2,
205: midFillColorTop));
206: overGraphics.fillRect(kernelSize, kernelSize, kernelSize
207: + width, kernelSize + shineHeight);
208: overGraphics.setComposite(AlphaComposite.DstIn);
209: overGraphics.drawImage(blurredGhostContour, 0, 0, null);
210: // millis005 = System.nanoTime();
211:
212: graphics
213: .drawImage(overGhostContour, 0, 0, width - 1,
214: shineHeight, kernelSize, kernelSize,
215: kernelSize + width - 1, kernelSize
216: + shineHeight, null);
217: }
218:
219: // long millis006 = System.nanoTime();
220:
221: // long millis2 = System.nanoTime();
222: // if (width * height > 5000) {
223: // System.out.println("new - " + width + "*" + height + " = "
224: // + format(millis2 - millis));
225: // System.out.println("\tfill : " + format(millis001 - millis000));
226: // System.out.println("\tcontour : " + format(millis003 - millis001));
227: // System.out.println("\trevert : " + format(millis004 - millis003));
228: // System.out.println("\toverlay : " + format(millis005 - millis004));
229: // System.out.println("\tborder : " + format(millis006 - millis005));
230: // }
231:
232: return image;
233: }
234:
235: // /**
236: // * Computes the color of the top portion of the border. Override to
237: // provide
238: // * different visual.
239: // *
240: // * @param interpolationScheme1
241: // * The first interpolation scheme.
242: // * @param interpolationScheme2
243: // * The second interpolation scheme.
244: // * @param cycleCoef
245: // * Cycle coefficient.
246: // * @param useCyclePosAsInterpolation
247: // * Indicates whether the cycle coefficient should be used as the
248: // * interpolation parameter.
249: // * @return The color of the top portion of the border.
250: // */
251: // public Color getTopBorderColor(ColorScheme interpolationScheme1,
252: // ColorScheme interpolationScheme2, double cycleCoef,
253: // boolean useCyclePosAsInterpolation) {
254: // return SubstanceColorUtilities.getTopBorderColor(interpolationScheme1,
255: // interpolationScheme2, cycleCoef);
256: // }
257: //
258: // /**
259: // * Computes the color of the middle portion of the border. Override to
260: // * provide different visual.
261: // *
262: // * @param interpolationScheme1
263: // * The first interpolation scheme.
264: // * @param interpolationScheme2
265: // * The second interpolation scheme.
266: // * @param cycleCoef
267: // * Cycle coefficient.
268: // * @param useCyclePosAsInterpolation
269: // * Indicates whether the cycle coefficient should be used as the
270: // * interpolation parameter.
271: // * @return The color of the middle portion of the border.
272: // */
273: // public Color getMidBorderColor(ColorScheme interpolationScheme1,
274: // ColorScheme interpolationScheme2, double cycleCoef,
275: // boolean useCyclePosAsInterpolation) {
276: // return SubstanceColorUtilities.getMidBorderColor(interpolationScheme1,
277: // interpolationScheme2, cycleCoef);
278: // }
279: //
280: // /**
281: // * Computes the color of the bottom portion of the border. Override to
282: // * provide different visual.
283: // *
284: // * @param interpolationScheme1
285: // * The first interpolation scheme.
286: // * @param interpolationScheme2
287: // * The second interpolation scheme.
288: // * @param cycleCoef
289: // * Cycle coefficient.
290: // * @param useCyclePosAsInterpolation
291: // * Indicates whether the cycle coefficient should be used as the
292: // * interpolation parameter.
293: // * @return The color of the bottom portion of the border.
294: // */
295: // public Color getBottomBorderColor(ColorScheme interpolationScheme1,
296: // ColorScheme interpolationScheme2, double cycleCoef,
297: // boolean useCyclePosAsInterpolation) {
298: // return SubstanceColorUtilities.getBottomBorderColor(
299: // interpolationScheme1, interpolationScheme2, cycleCoef);
300: // }
301:
302: /**
303: * Computes the color of the top portion of the fill. Override to provide
304: * different visual.
305: *
306: * @param interpolationScheme1
307: * The first interpolation scheme.
308: * @param interpolationScheme2
309: * The second interpolation scheme.
310: * @param cycleCoef
311: * Cycle coefficient.
312: * @param useCyclePosAsInterpolation
313: * Indicates whether the cycle coefficient should be used as the
314: * interpolation parameter.
315: * @return The color of the top portion of the fill.
316: */
317: public Color getTopFillColor(ColorScheme interpolationScheme1,
318: ColorScheme interpolationScheme2, double cycleCoef,
319: boolean useCyclePosAsInterpolation) {
320: return SubstanceColorUtilities.getTopFillColor(
321: interpolationScheme1, interpolationScheme2, cycleCoef,
322: useCyclePosAsInterpolation);
323: }
324:
325: /**
326: * Computes the color of the middle portion of the fill from the top.
327: * Override to provide different visual.
328: *
329: * @param interpolationScheme1
330: * The first interpolation scheme.
331: * @param interpolationScheme2
332: * The second interpolation scheme.
333: * @param cycleCoef
334: * Cycle coefficient.
335: * @param useCyclePosAsInterpolation
336: * Indicates whether the cycle coefficient should be used as the
337: * interpolation parameter.
338: * @return The color of the middle portion of the fill from the top.
339: */
340: public Color getMidFillColorTop(ColorScheme interpolationScheme1,
341: ColorScheme interpolationScheme2, double cycleCoef,
342: boolean useCyclePosAsInterpolation) {
343:
344: return SubstanceColorUtilities.getMidFillColor(
345: interpolationScheme1, interpolationScheme2, cycleCoef,
346: useCyclePosAsInterpolation);
347: }
348:
349: /**
350: * Computes the color of the middle portion of the fill from the bottom.
351: * Override to provide different visual.
352: *
353: * @param interpolationScheme1
354: * The first interpolation scheme.
355: * @param interpolationScheme2
356: * The second interpolation scheme.
357: * @param cycleCoef
358: * Cycle coefficient.
359: * @param useCyclePosAsInterpolation
360: * Indicates whether the cycle coefficient should be used as the
361: * interpolation parameter.
362: * @return The color of the middle portion of the fill from the bottom.
363: */
364: public Color getMidFillColorBottom(
365: ColorScheme interpolationScheme1,
366: ColorScheme interpolationScheme2, double cycleCoef,
367: boolean useCyclePosAsInterpolation) {
368:
369: return this .getMidFillColorTop(interpolationScheme1,
370: interpolationScheme2, cycleCoef,
371: useCyclePosAsInterpolation);
372: }
373:
374: /**
375: * Computes the color of the bottom portion of the fill. Override to provide
376: * different visual.
377: *
378: * @param interpolationScheme1
379: * The first interpolation scheme.
380: * @param interpolationScheme2
381: * The second interpolation scheme.
382: * @param cycleCoef
383: * Cycle coefficient.
384: * @param useCyclePosAsInterpolation
385: * Indicates whether the cycle coefficient should be used as the
386: * interpolation parameter.
387: * @return The color of the bottom portion of the fill.
388: */
389: public Color getBottomFillColor(ColorScheme interpolationScheme1,
390: ColorScheme interpolationScheme2, double cycleCoef,
391: boolean useCyclePosAsInterpolation) {
392: return SubstanceColorUtilities.getBottomFillColor(
393: interpolationScheme1, interpolationScheme2, cycleCoef,
394: useCyclePosAsInterpolation);
395: }
396:
397: /**
398: * Computes the color of the top portion of the shine. Override to provide
399: * different visual.
400: *
401: * @param interpolationScheme1
402: * The first interpolation scheme.
403: * @param interpolationScheme2
404: * The second interpolation scheme.
405: * @param cycleCoef
406: * Cycle coefficient.
407: * @param useCyclePosAsInterpolation
408: * Indicates whether the cycle coefficient should be used as the
409: * interpolation parameter.
410: * @return The color of the top portion of the shine.
411: */
412: public Color getTopShineColor(ColorScheme interpolationScheme1,
413: ColorScheme interpolationScheme2, double cycleCoef,
414: boolean useCyclePosAsInterpolation) {
415: return SubstanceColorUtilities.getTopShineColor(
416: interpolationScheme1, interpolationScheme2, cycleCoef,
417: useCyclePosAsInterpolation);
418: }
419:
420: /**
421: * Computes the color of the bottom portion of the shine. Override to
422: * provide different visual.
423: *
424: * @param interpolationScheme1
425: * The first interpolation scheme.
426: * @param interpolationScheme2
427: * The second interpolation scheme.
428: * @param cycleCoef
429: * Cycle coefficient.
430: * @param useCyclePosAsInterpolation
431: * Indicates whether the cycle coefficient should be used as the
432: * interpolation parameter.
433: * @return The color of the bottom portion of the shine.
434: */
435: public Color getBottomShineColor(ColorScheme interpolationScheme1,
436: ColorScheme interpolationScheme2, double cycleCoef,
437: boolean useCyclePosAsInterpolation) {
438: return SubstanceColorUtilities.getBottomShineColor(
439: interpolationScheme1, interpolationScheme2, cycleCoef,
440: useCyclePosAsInterpolation);
441: }
442: }
|