protected CSSValue parseFirstPosition(final LexicalUnit value) {
    if (value == null) {
      return null;
    }

    if (value.getLexicalUnitType() == LexicalUnit.SAC_IDENT) {
      if ("left".equalsIgnoreCase(value.getStringValue())) {
        return LEFT;
      } else if ("center".equalsIgnoreCase(value.getStringValue())) {
        return CENTER;
      } else if ("right".equalsIgnoreCase(value.getStringValue())) {
        return RIGHT;
      } else if ("top".equalsIgnoreCase(value.getStringValue())) {
        return TOP;
      } else if ("bottom".equalsIgnoreCase(value.getStringValue())) {
        return BOTTOM;
      }

      // ignore this rule.
      return null;
    }

    if (value.getLexicalUnitType() == LexicalUnit.SAC_PERCENTAGE) {
      return CSSNumericValue.createValue(CSSNumericType.PERCENTAGE, value.getFloatValue());
    }
    if (CSSValueFactory.isLengthValue(value)) {
      return CSSValueFactory.createLengthValue(value);
    }
    // contains errors, we ignore this rule.
    return null;
  }
  private float calculateInternal(
      final LexicalUnit lu, final Styles parentStyles, final Styles styles) {

    final DisplayDevice device = DisplayDevice.getCurrent();
    float baseFontSize = DEFAULT_FONT_SIZE_POINTS * device.getVerticalPPI() / 72;

    if (parentStyles != null) {
      baseFontSize = parentStyles.getFontSize();
    }

    if (lu == null) {
      return baseFontSize;
    } else if (isLength(lu)) {
      return getFloatLength(lu, baseFontSize, device.getVerticalPPI());
    } else if (isPercentage(lu)) {
      return baseFontSize * lu.getFloatValue() / 100;
    } else if (lu.getLexicalUnitType() == LexicalUnit.SAC_IDENT) {
      final String s = lu.getStringValue();

      if (s.equals(CSS.XX_SMALL)) {
        return baseFontSize * FONT_FACTOR_XX_SMALL;

      } else if (s.equals(CSS.X_SMALL)) {
        return baseFontSize * FONT_FACTOR_X_SMALL;

      } else if (s.equals(CSS.SMALL)) {
        return baseFontSize * FONT_FACTOR_SMALL;

      } else if (s.equals(CSS.MEDIUM)) {
        return baseFontSize * FONT_FACTOR_MEDIUM;

      } else if (s.equals(CSS.LARGE)) {
        return baseFontSize * FONT_FACTOR_LARGE;

      } else if (s.equals(CSS.X_LARGE)) {
        return baseFontSize * FONT_FACTOR_X_LARGE;

      } else if (s.equals(CSS.XX_LARGE)) {
        return baseFontSize * FONT_FACTOR_XX_LARGE;

      } else if (s.equals(CSS.SMALLER)) {
        return baseFontSize / FONT_SIZE_FACTOR;

      } else if (s.equals(CSS.LARGER)) {
        return baseFontSize * FONT_SIZE_FACTOR;

      } else {
        return baseFontSize;
      }
    } else {
      return baseFontSize;
    }
  }
  private CSSValue parseSingleSpacingValue(final LexicalUnit value) {
    if (value == null) {
      return null;
    }

    if (value.getLexicalUnitType() == LexicalUnit.SAC_IDENT) {
      if (value.getStringValue().equalsIgnoreCase("normal")) {
        return SpacingLimitReadHandler.NORMAL;
      }
      return null;
    }
    if (value.getLexicalUnitType() == LexicalUnit.SAC_PERCENTAGE) {
      return CSSNumericValue.createValue(CSSNumericType.PERCENTAGE, value.getFloatValue());
    }

    return CSSValueFactory.createLengthValue(value);
  }
 void write(LexicalUnit lu) {
   short type = lu.getLexicalUnitType();
   switch (type) {
     case LexicalUnit.SAC_URI:
       write("url(");
       write(lu.getStringValue());
       write(")");
       break;
     case LexicalUnit.SAC_STRING_VALUE:
       write('"');
       write(lu.getStringValue());
       write('"');
       break;
     case LexicalUnit.SAC_IDENT:
       write(lu.getStringValue());
       break;
     case LexicalUnit.SAC_REAL:
       write(lu.getFloatValue());
       break;
     case LexicalUnit.SAC_PIXEL:
       write(lu.getFloatValue());
       write("px");
       break;
     case LexicalUnit.SAC_MILLIMETER:
       write(lu.getFloatValue());
       write("mm");
       break;
     case LexicalUnit.SAC_CENTIMETER:
       write(lu.getFloatValue());
       write("cm");
       break;
     case LexicalUnit.SAC_PERCENTAGE:
       write(lu.getFloatValue());
       write("%");
       break;
     case LexicalUnit.SAC_POINT:
       write(lu.getFloatValue());
       write("pt");
       break;
     case LexicalUnit.SAC_EM:
       write(lu.getFloatValue());
       write("em");
       break;
     case LexicalUnit.SAC_INTEGER:
       write(lu.getIntegerValue());
       break;
     case LexicalUnit.SAC_FUNCTION:
       write(lu.getFunctionName());
       write("(");
       write(lu.getParameters(), "");
       write(")");
       break;
     case LexicalUnit.SAC_RGBCOLOR:
       // Use hexadecimal notation instead
       writeHex(lu.getParameters());
       break;
     case LexicalUnit.SAC_OPERATOR_COMMA:
       write(",");
       break;
     case LexicalUnit.SAC_INHERIT:
       write("inherit");
       break;
     default:
       throw new UnsupportedOperationException("Lexical unit type " + type + " is not handled");
   }
 }