All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.myfaces.trinidad.convert.RGBColorFormat Maven / Gradle / Ivy

There is a newer version: 2.2.1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.myfaces.trinidad.convert;

import java.awt.Color;

import java.text.FieldPosition;
import java.text.ParsePosition;

import org.apache.myfaces.trinidad.logging.TrinidadLogger;

/**
 * Format for colors.
 * 

* Time Format Syntax: *

* To specify the time format use a color pattern string. * In this pattern, all ASCII letters are reserved as pattern letters, * which are defined as the following: *

*
 * Symbol   Meaning                 Presentation        Example
 * ------   -------                 ------------        -------
 * r        red component           (Number)            242
 * g        green component         (Number)            242
 * b        blue component          (Number)            242
 * a        alpha component         (Number)            255
 * R        red component           (Hex)               F2
 * G        green component         (Hex)               F2
 * B        blue component          (Hex)               F2
 * A        alpha component         (Hex)               FF
 * '        escape for text         (Delimiter)
 * ''       single quote            (Literal)           '
 * 
*
*

* Examples: *

*
 * Format Pattern                         Result
 * --------------                         -------
 * "#RRGGBB"                         ->>  #6609CC
 * "rrr,ggg,bbb"                     ->>  102,009,204
 * "t"                               ->>  Transparent (when alpha is zero)
 * 
*
* * @version $Name: $ ($Revision: adfrt/faces/adf-faces-api/src/main/java/oracle/adf/view/faces/convert/RGBColorFormat.java#0 $) $Date: 10-nov-2005.19:09:13 $ * @todo This class needs to be part of the public API - need to move it to * place where our public API exists, once we have figured it out. */ class RGBColorFormat extends ColorFormat { /** * Creates a RGBColorFormat with the specified pattern. * * @param pattern the color format pattern */ public RGBColorFormat( String pattern) { if (pattern == null) throw new IllegalArgumentException(); _pattern = pattern; } /** * Returns the value as a Color. */ @Override public Object parseObject( String text, ParsePosition pos) { // do not attempt to parse null color string if (text == null) return null; int start = pos.getIndex(); int oldStart = start; boolean inQuote = false; // inQuote set true when hits 1st single quote char prevCh = 0; int count = 0; int interQuoteCount = 1; // Number of chars between quotes int[] rgba = new int[_FIELD_COUNT]; rgba[_ALPHA_FIELD] = 255; // default alpha to full (opaque) for (int i=0; i < _pattern.length(); i++) { char ch = _pattern.charAt(i); if (inQuote) { if (ch == '\'') { // ends with 2nd single quote inQuote = false; // two consecutive quotes outside a quote means we have // a quote literal we need to match. if (count == 0) { if (start >= text.length() || ch != text.charAt(start)) { pos.setIndex(oldStart); pos.setErrorIndex(start); return null; } start++; } count = 0; interQuoteCount = 0; } else { // pattern uses text following from 1st single quote. if (start >= text.length() || ch != text.charAt(start)) { // Check for cases like: 'at' in pattern vs "xt" // in time text, where 'a' doesn't match with 'x'. // If fail to match, return null. pos.setIndex(oldStart); // left unchanged pos.setErrorIndex(start); return null; } count++; start++; } } else // !inQuote { if (ch == '\'') { inQuote = true; if (count > 0) // handle cases like: e'at' { int startOffset = start; start = _subParse(rgba, text, start, prevCh, count); if (start < 0) { pos.setIndex(oldStart); pos.setErrorIndex(startOffset); return null; } count = 0; } if (interQuoteCount == 0) { // This indicates two consecutive quotes inside a quote, // for example, 'o''clock'. We need to parse this as // representing a single quote within the quote. int startOffset = start; if (start >= text.length() || ch != text.charAt(start)) { pos.setIndex(oldStart); pos.setErrorIndex(startOffset); return null; } start++; count = 1; // Make it look like we never left } } else if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z') { // ch is a color pattern if (ch != prevCh && count > 0) // e.g., rrr { int startOffset = start; start = _subParse(rgba, text, start, prevCh, count); if (start < 0) { pos.setIndex(oldStart); pos.setErrorIndex(startOffset); return null; } prevCh = ch; count = 1; } else { if (ch != prevCh) prevCh = ch; count++; } } else if (count > 0) { // handle cases like: "rrr,ggg,bbb", "RR.GG.BB", "r g b", etc // where ch = ',', '.' or ' ', repectively. int startOffset = start; start = _subParse(rgba, text, start, prevCh, count); if ( start < 0 ) { pos.setIndex(oldStart); pos.setErrorIndex(startOffset); return null; } if (start >= text.length() || ch != text.charAt(start)) { // handle cases like: 'RR g' in pattern vs. "FFx20" // in color text, where ' ' doesn't match with 'x'. pos.setIndex(oldStart); pos.setErrorIndex(start); return null; } start++; count = 0; prevCh = 0; } else // any other unquoted characters { if (start >= text.length() || ch != text.charAt(start)) { // handle cases like: 'RR g' in pattern vs. "FF,,,20" // in color text, where " " doesn't match with ",,,". pos.setIndex(oldStart); pos.setErrorIndex(start); return null; } start++; } interQuoteCount++; } } // Parse the last item in the pattern if (count > 0) { int startOffset = start; start = _subParse(rgba, text, start, prevCh, count); if (start < 0) { pos.setIndex(oldStart); pos.setErrorIndex(startOffset); return null; } } pos.setIndex(start); return new Color(rgba[_RED_FIELD], rgba[_GREEN_FIELD], rgba[_BLUE_FIELD], rgba[_ALPHA_FIELD]); } @Override public StringBuffer format( Color color, StringBuffer toAppendTo, FieldPosition pos) { // initialize pos.setBeginIndex(0); pos.setEndIndex(0); // do not attempt to format null color if (color == null) return toAppendTo; boolean inQuote = false; // true when between single quotes char prevCh = 0; // previous pattern character int count = 0; // number of time prevCh repeated for (int i=0; i < _pattern.length(); ++i) { char ch = _pattern.charAt(i); // Use subFormat() to format a repeated pattern character // when a different pattern or non-pattern character is seen if (ch != prevCh && count > 0) { toAppendTo = _subFormat(color, prevCh, count, toAppendTo); count = 0; } if (ch == '\'') { // Consecutive single quotes are a single quote literal, // either outside of quotes or between quotes if ((i+1) < _pattern.length() && _pattern.charAt(i+1) == '\'') { toAppendTo.append('\''); ++i; } else { inQuote = !inQuote; } } else if (!inQuote && (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z')) { // ch is a date-time pattern character to be interpreted // by subFormat(); count the number of times it is repeated prevCh = ch; ++count; } else { // Append quoted characters and unquoted non-pattern characters toAppendTo.append(ch); } } // Format the last item in the pattern, if any if (count > 0) { toAppendTo = _subFormat(color, prevCh, count, toAppendTo); } return toAppendTo; } public int length() { int size = 0; boolean inQuote = false; // true when between single quotes char prevCh = 0; // previous pattern character int count = 0; // number of time prevCh repeated for (int i=0; i < _pattern.length(); ++i) { char ch = _pattern.charAt(i); // Use subFormat() to format a repeated pattern character // when a different pattern or non-pattern character is seen if (ch != prevCh && count > 0) { size += _subLength(prevCh); count = 0; } if (ch == '\'') { // Consecutive single quotes are a single quote literal, // either outside of quotes or between quotes if ((i+1) < _pattern.length() && _pattern.charAt(i+1) == '\'') { size++; ++i; } else { inQuote = !inQuote; } } else if (!inQuote && (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z')) { // ch is a date-time pattern character to be interpreted // by subFormat(); count the number of times it is repeated prevCh = ch; ++count; } else { // Append quoted characters and unquoted non-pattern characters size++; } } // Format the last item in the pattern, if any if (count > 0) { size += _subLength(prevCh); } return size; } // Private member function that does the real length calculations. private int _subLength( char ch) { switch (ch) { case 'r': case 'g': case 'b': case 'a': return 3; case 'R': case 'G': case 'B': case 'A': return 2; default: throw new IllegalArgumentException(_LOG.getMessage( "ILLEGAL_PATTERN_CHARACTER", ch)); } } // Private member function that does the real color parsing. private int _subParse( int[] rgba, String text, int start, char ch, int count) { switch (ch) { case 'r': return _subParseDecimal(rgba, _RED_FIELD, text, start, count); case 'g': return _subParseDecimal(rgba, _GREEN_FIELD, text, start, count); case 'b': return _subParseDecimal(rgba, _BLUE_FIELD, text, start, count); case 'a': return _subParseDecimal(rgba, _ALPHA_FIELD, text, start, count); case 'R': return _subParseHex(rgba, _RED_FIELD, text, start, count); case 'G': return _subParseHex(rgba, _GREEN_FIELD, text, start, count); case 'B': return _subParseHex(rgba, _BLUE_FIELD, text, start, count); case 'A': return _subParseHex(rgba, _ALPHA_FIELD, text, start, count); default: throw new IllegalArgumentException(_LOG.getMessage( "ILLEGAL_PATTERN_CHARACTER", ch)); } } private int _subParseDecimal( int[] rgba, int field, String text, int start, int count) { return _subParseBase(rgba, field, text, start, count, 3, 10); } private int _subParseHex( int[] rgba, int field, String text, int start, int count) { return _subParseBase(rgba, field, text, start, count, 2, 16); } private int _subParseBase( int[] rgba, int field, String text, int start, int minDigits, int maxDigits, int base) { int length = text.length(); int atLeast = start + minDigits; // make sure the color string is long enough if (atLeast > length) return -start; int index; int end = Math.min(length, start + maxDigits); int value = 0; for(index=start; index < end; index++) { int digit = Character.digit(text.charAt(index), base); if (digit == -1) { // did not consume sufficient characters in color string if (index < atLeast) return -start; else break; } value *= base; value += digit; } rgba[field] = value; return index; } // Private member function that does the real color formatting. private StringBuffer _subFormat( Color color, char ch, int count, StringBuffer toAppendTo) throws IllegalArgumentException { switch (ch) { case 'r': return _subFormatDecimal(color.getRed(), count, toAppendTo); case 'g': return _subFormatDecimal(color.getGreen(), count, toAppendTo); case 'b': return _subFormatDecimal(color.getBlue(), count, toAppendTo); case 'a': return _subFormatDecimal(color.getAlpha(), count, toAppendTo); case 'R': return _subFormatHex(color.getRed(), count, toAppendTo); case 'G': return _subFormatHex(color.getGreen(), count, toAppendTo); case 'B': return _subFormatHex(color.getBlue(), count, toAppendTo); case 'A': return _subFormatHex(color.getAlpha(), count, toAppendTo); default: throw new IllegalArgumentException(_LOG.getMessage( "ILLEGAL_PATTERN_CHARACTER", ch)); } } private StringBuffer _subFormatDecimal( int value, int minDigits, StringBuffer toAppendTo) { _prefixZeros(value, 10, minDigits, toAppendTo); toAppendTo.append(value); return toAppendTo; } private StringBuffer _subFormatHex( int value, int minDigits, StringBuffer toAppendTo) { String hexString = Integer.toHexString(value); int digits = hexString.length(); for (int i=0; i < minDigits - digits; i++) toAppendTo.append('0'); toAppendTo.append(Integer.toHexString(value).toUpperCase()); return toAppendTo; } private StringBuffer _prefixZeros( int value, int base, int minDigits, StringBuffer toAppendTo) { if (value >= 0) { int digits = (value > 0) ? (int)Math.ceil(Math.log(value) / Math.log(base)) : 1; while (minDigits > 0 && digits < minDigits) { toAppendTo.append('0'); minDigits--; } } return toAppendTo; } private String _pattern; private static final int _RED_FIELD = 0; private static final int _GREEN_FIELD = 1; private static final int _BLUE_FIELD = 2; private static final int _ALPHA_FIELD = 3; private static final int _FIELD_COUNT = 4; private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(RGBColorFormat.class); private static final long serialVersionUID = 1L; }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy