gt:       final ResourceKey base = layoutProcess.getContextKey();
context: /*!
  * This program is free software; you can redistribute it and/or modify it under the
  * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
  * Foundation.
  *
  * You should have received a copy of the GNU Lesser General Public License along with this
  * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
  * or from the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * 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 Lesser General Public License for more details.
  *
  * Copyright (c) 2002-2013 Pentaho Corporation..  All rights reserved.
  */
  
  package org.pentaho.reporting.libraries.css.resolver.function;
  
  import org.pentaho.reporting.libraries.css.dom.DocumentContext;
  import org.pentaho.reporting.libraries.css.dom.LayoutElement;
  import org.pentaho.reporting.libraries.css.resolver.FunctionEvaluationException;
  import org.pentaho.reporting.libraries.css.values.CSSFunctionValue;
  import org.pentaho.reporting.libraries.css.values.CSSNumericType;
  import org.pentaho.reporting.libraries.css.values.CSSNumericValue;
  import org.pentaho.reporting.libraries.css.values.CSSResourceValue;
  import org.pentaho.reporting.libraries.css.values.CSSStringType;
  import org.pentaho.reporting.libraries.css.values.CSSStringValue;
  import org.pentaho.reporting.libraries.css.values.CSSValue;
  import org.pentaho.reporting.libraries.resourceloader.Resource;
  import org.pentaho.reporting.libraries.resourceloader.ResourceKey;
  import org.pentaho.reporting.libraries.resourceloader.ResourceKeyCreationException;
  import org.pentaho.reporting.libraries.resourceloader.ResourceManager;
  
  /**
   * Creation-Date: 04.07.2006, 14:30:10
   *
   * @author Thomas Morgner
   */
  public class FunctionUtilities {
    private static CSSNumericType[] KNOWN_TYPES = {
      CSSNumericType.PERCENTAGE,
      CSSNumericType.EM,
      CSSNumericType.EX,
      CSSNumericType.CM,
      CSSNumericType.MM,
      CSSNumericType.INCH,
      CSSNumericType.PT,
      CSSNumericType.PC,
      CSSNumericType.DEG,
      CSSNumericType.PX
    };
  
    private FunctionUtilities() {
    }
  
  
    public static CSSResourceValue loadResource( final DocumentContext process,
                                                 final Object value )
      throws FunctionEvaluationException {
      final Class[] supportedResourceTypes = process.getSupportedResourceTypes();
      if ( supportedResourceTypes.length == 0 ) {
        throw new FunctionEvaluationException
          ( "Failed to create URI: Resource loading failed as the output " +
            "target does not support any resource types." );
      }
      return loadResource( process, value, supportedResourceTypes );
    }
  
    public static CSSResourceValue loadResource( final DocumentContext process,
                                                 final Object value,
                                                 final Class[] type )
      throws FunctionEvaluationException {
      // ok, this is going to be expensive. Kids, you dont wanna try this at home ...
      final ResourceManager manager = process.getResourceManager();
      final ResourceKey baseKey = process.getContextKey();
      try {
        final ResourceKey key;
        if ( value instanceof ResourceKey ) {
          key = (ResourceKey) value;
        } else if ( baseKey == null ) {
          key = manager.createKey( value );
        } else if ( value instanceof String ) {
          key = manager.deriveKey( baseKey, (String) value );
        } else {
          throw new FunctionEvaluationException
            ( "Failed to create URI: Resource loading failed: Key not derivable" );
        }
  
        final Resource res = manager.create( key, baseKey, type );
        return new CSSResourceValue( res );
      } catch ( Exception e ) {
        throw new FunctionEvaluationException
          ( "Failed to create URI: Resource loading failed: " + e.getMessage(), e );
      }
    }
  
  
    public static CSSValue parseValue( final DocumentContext process,
                                       final String text ) {
      final CSSNumericValue val = convertToNumber( text );
      if ( val != null ) {
        return val;
      }
  
      // next step: That may be expensive, but we search for URLs ..
      try {
        return loadResource( process, text );
      } catch ( FunctionEvaluationException e ) {
        // ignore, it was just an attempt ...
      }
  
      return new CSSStringValue( CSSStringType.STRING, text );
    }
  
    public static CSSNumericValue parseNumberValue( final String text, final String type )
      throws FunctionEvaluationException {
      final CSSNumericValue val = convertToNumber( text, getUnitType( type ) );
      if ( val != null ) {
        return val;
      }
      throw new FunctionEvaluationException( "Unable to convert to number." );
    }
  
    public static CSSNumericValue parseNumberValue( final String text )
      throws FunctionEvaluationException {
      final CSSNumericValue val = convertToNumber( text );
      if ( val != null ) {
        return val;
      }
      throw new FunctionEvaluationException( "Unable to convert to number." );
    }
  
    private static CSSNumericValue convertToNumber( final String stringValue ) {
      final String txt = stringValue.trim();
      CSSNumericType type = null;
  
      for ( int i = 0; i < KNOWN_TYPES.length; i++ ) {
        final CSSNumericType numericType = KNOWN_TYPES[ i ];
        if ( txt.endsWith( numericType.getType() ) ) {
          type = numericType;
        }
      }
      if ( type == null ) {
        type = CSSNumericType.NUMBER;
      }
      final String number = txt.substring
        ( 0, txt.length() - type.getType().length() ).trim();
      return convertToNumber( number, type );
    }
  
    private static CSSNumericValue convertToNumber( final String stringValue,
                                                    CSSNumericType type ) {
      if ( type == null ) {
        type = CSSNumericType.NUMBER;
      }
      try {
        final String number = stringValue.trim();
        final double nVal = Double.parseDouble( number );
        return CSSNumericValue.createValue( type, nVal );
      } catch ( Exception e ) {
        return null;
      }
    }
  
    public static CSSNumericType getUnitType( final String typeText ) {
      if ( typeText == null ) {
        return CSSNumericType.NUMBER;
      }
      final String txt = typeText.trim();
      for ( int i = 0; i < KNOWN_TYPES.length; i++ ) {
        final CSSNumericType numericType = KNOWN_TYPES[ i ];
        if ( txt.equalsIgnoreCase( numericType.getType() ) ) {
          return numericType;
        }
      }
      return CSSNumericType.NUMBER;
    }
  
  
    public static String resolveString( final DocumentContext layoutProcess,
                                        final LayoutElement layoutElement,
                                        final CSSValue value )
      throws FunctionEvaluationException {
      final CSSValue notAFunctionAnymore = resolveParameter( layoutProcess, layoutElement, value );
      if ( notAFunctionAnymore instanceof CSSStringValue ) {
        final CSSStringValue strVal = (CSSStringValue) notAFunctionAnymore;
        return strVal.getValue();
      }
  
      // Falling back to the Value itself ..
  
      final String retval = notAFunctionAnymore.getCSSText();
      if ( retval == null ) {
        throw new FunctionEvaluationException
          ( "Value " + notAFunctionAnymore + " is invalid" );
      }
      return retval;
    }
  
    public static CSSValue resolveParameter( final DocumentContext layoutProcess,
                                             final LayoutElement layoutElement,
                                             final CSSValue value )
      throws FunctionEvaluationException {
      if ( value instanceof CSSFunctionValue == false ) {
        return value;
      }
  
      final CSSFunctionValue functionValue = (CSSFunctionValue) value;
  
      final StyleValueFunction function =
        FunctionFactory.getInstance().getStyleFunction
          ( functionValue.getFunctionName() );
      if ( function == null ) {
        throw new FunctionEvaluationException
          ( "Unsupported Function: " + functionValue );
      }
      return function.evaluate
        ( layoutProcess, layoutElement, functionValue );
    }
  
    public static ResourceKey createURI( final String uri, final DocumentContext layoutProcess ) {
      try {
  