/******************************************************************************* * Copyright (c) 2007, 2015 Innoopract Informationssysteme GmbH and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Innoopract Informationssysteme GmbH - initial API and implementation * EclipseSource - ongoing development ******************************************************************************/ package org.eclipse.rap.rwt.internal.theme; import static org.eclipse.rap.rwt.internal.service.ContextProvider.getApplicationContext; import java.util.HashMap; import java.util.Locale; import java.util.Map; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.internal.graphics.ResourceFactory; public class CssColor implements CssValue { private static final String TRANSPARENT_STR = "transparent"; private static final Map<String, int[]> NAMED_COLORS = new HashMap<>(); public static final CssColor BLACK = new CssColor( 0, 0, 0, 1f ); public static final CssColor WHITE = new CssColor( 255, 255, 255, 1f ); public static final CssColor TRANSPARENT = new CssColor(); public final int red; public final int green; public final int blue; public final float alpha; static { // register 16 standard HTML colors NAMED_COLORS.put( "black", new int[] { 0, 0, 0 } ); NAMED_COLORS.put( "gray", new int[] { 128, 128, 128 } ); NAMED_COLORS.put( "silver", new int[] { 192, 192, 192 } ); NAMED_COLORS.put( "white", new int[] { 255, 255, 255 } ); NAMED_COLORS.put( "maroon", new int[] { 128, 0, 0 } ); NAMED_COLORS.put( "red", new int[] { 255, 0, 0 } ); NAMED_COLORS.put( "purple", new int[] { 128, 0, 128 } ); NAMED_COLORS.put( "fuchsia", new int[] { 255, 0, 255 } ); NAMED_COLORS.put( "green", new int[] { 0, 128, 0 } ); NAMED_COLORS.put( "lime", new int[] { 0, 255, 0 } ); NAMED_COLORS.put( "navy", new int[] { 0, 0, 128 } ); NAMED_COLORS.put( "blue", new int[] { 0, 0, 255 } ); NAMED_COLORS.put( "olive", new int[] { 128, 128, 0 } ); NAMED_COLORS.put( "yellow", new int[] { 255, 255, 0 } ); NAMED_COLORS.put( "teal", new int[] { 0, 128, 128 } ); NAMED_COLORS.put( "aqua", new int[] { 0, 255, 255 } ); } private CssColor() { red = 0; green = 0; blue = 0; alpha = 0f; } private CssColor( int red, int green, int blue, float alpha ) { this.red = red; this.green = green; this.blue = blue; this.alpha = alpha; } public static CssColor create( int red, int green, int blue ) { if( red == 0 && green == 0 && blue == 0 ) { return BLACK; } if( red == 255 && green == 255 && blue == 255 ) { return WHITE; } return new CssColor( red, green, blue, 1f ); } public static CssColor create( int red, int green, int blue, float alpha ) { checkAlpha( alpha ); if( alpha == 1f ) { return create( red, green, blue ); } return new CssColor( red, green, blue, alpha ); } private static void checkAlpha( float alpha ) { if( alpha < 0 || alpha > 1 ) { String msg = "Alpha out of range [ 0, 1 ]: " + alpha; throw new IllegalArgumentException( msg ); } } public static CssColor valueOf( String input ) { if( input == null ) { throw new NullPointerException( "null argument" ); } if( TRANSPARENT_STR.equals( input ) ) { return TRANSPARENT; } int red, green, blue; float alpha = 1f; String lowerCaseInput = input.toLowerCase( Locale.ENGLISH ); if( input.startsWith( "#" ) ) { try { if( input.length() == 7 ) { red = Integer.parseInt( input.substring( 1, 3 ), 16 ); green = Integer.parseInt( input.substring( 3, 5 ), 16 ); blue = Integer.parseInt( input.substring( 5, 7 ), 16 ); } else if( input.length() == 4 ) { red = Integer.parseInt( input.substring( 1, 2 ), 16 ) * 17; green = Integer.parseInt( input.substring( 2, 3 ), 16 ) * 17; blue = Integer.parseInt( input.substring( 3, 4 ), 16 ) * 17; } else { String message = "Illegal number of characters in color definition: " + input; throw new IllegalArgumentException( message ); } } catch( NumberFormatException e ) { String message = "Illegal number format in color definition: " + input; throw new IllegalArgumentException( message, e ); } } else if( NAMED_COLORS.containsKey( lowerCaseInput ) ) { int[] values = NAMED_COLORS.get( lowerCaseInput ); red = values[ 0 ]; green = values[ 1 ]; blue = values[ 2 ]; } else { String[] parts = input.split( "\\s*,\\s*" ); if( parts.length >= 3 && parts.length <= 4 ) { try { red = Integer.parseInt( parts[ 0 ] ); green = Integer.parseInt( parts[ 1 ] ); blue = Integer.parseInt( parts[ 2 ] ); if( parts.length == 4 ) { alpha = Float.parseFloat( parts[ 3 ] ); } } catch( NumberFormatException e ) { String message = "Illegal number format in color definition: " + input; throw new IllegalArgumentException( message, e ); } } else { String message = "Invalid color name: " + input; throw new IllegalArgumentException( message ); } } return create( red, green, blue, alpha ); } public boolean isTransparent() { return alpha == 0f; } @Override public String toDefaultString() { if( isTransparent() ) { return TRANSPARENT_STR; } return alpha == 1f ? toHtmlString( red, green, blue ) : toRgbaString( red, green, blue, alpha ); } @Override public boolean equals( Object object ) { if( object == this ) { return true; } if( object instanceof CssColor ) { CssColor other = ( CssColor )object; return other.red == red && other.green == green && other.blue == blue && other.alpha == alpha; } return false; } @Override public int hashCode() { int result = -1; if( !isTransparent() ) { result = 41; result += 19 * result + red; result += 19 * result + green; result += 19 * result + blue; result += 19 * result + Float.floatToIntBits( alpha ); } return result; } @Override public String toString() { String colors = red + ", " + green + ", " + blue + ", " + alpha; return "CssColor{ " + ( isTransparent() ? TRANSPARENT_STR : colors ) + " }"; } public static String toHtmlString( int red, int green, int blue ) { StringBuilder sb = new StringBuilder(); sb.append( "#" ); sb.append( getHexStr( red ) ); sb.append( getHexStr( green ) ); sb.append( getHexStr( blue ) ); return sb.toString(); } public static Color createColor( CssColor color ) { Color result = null; if( color.alpha != 0f ) { ResourceFactory resourceFactory = getApplicationContext().getResourceFactory(); result = resourceFactory.getColor( color.red, color.green, color.blue ); } return result; } private static String getHexStr( int value ) { String hex = Integer.toHexString( value ); return hex.length() == 1 ? "0" + hex : hex; } private static String toRgbaString( int red, int green, int blue, float alpha ) { StringBuilder sb = new StringBuilder(); sb.append( "rgba(" ); sb.append( red ); sb.append( "," ); sb.append( green ); sb.append( "," ); sb.append( blue ); sb.append( "," ); sb.append( alpha ); sb.append( ")" ); return sb.toString(); } }