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;
    }
  }