private boolean visitRule(RenderingRule rule, boolean loadOutput) {
    RenderingRuleProperty[] properties = rule.getProperties();
    for (int i = 0; i < properties.length; i++) {
      RenderingRuleProperty rp = properties[i];
      if (rp.isInputProperty()) {
        boolean match;
        if (rp.isFloat()) {
          match = rp.accept(rule.getFloatProp(i), fvalues[rp.getId()], this);
        } else {
          match = rp.accept(rule.getIntProp(i), values[rp.getId()], this);
        }
        if (!match) {
          return false;
        }
      } else if (rp == storage.PROPS.R_DISABLE) {
        // quick disable return even without load output
        values[rp.getId()] = rule.getIntProp(i);
      }
    }
    if (!loadOutput) {
      return true;
    }
    // accept it
    for (int i = 0; i < properties.length; i++) {
      RenderingRuleProperty rp = properties[i];
      if (rp.isOutputProperty()) {
        searchResult = true;
        if (rp.isFloat()) {
          fvalues[rp.getId()] = rule.getFloatProp(i);
          values[rp.getId()] = rule.getIntProp(i);
        } else {
          values[rp.getId()] = rule.getIntProp(i);
        }
      }
    }

    for (RenderingRule rr : rule.getIfElseChildren()) {
      boolean match = visitRule(rr, loadOutput);
      if (match) {
        break;
      }
    }

    for (RenderingRule rr : rule.getIfChildren()) {
      visitRule(rr, loadOutput);
    }
    return true;
  }
 public boolean isSpecified(RenderingRuleProperty property) {
   if (property.isFloat()) {
     return fvalues[property.getId()] != 0 || values[property.getId()] != -1;
   } else {
     int val = values[property.getId()];
     if (property.isColor()) {
       return val != 0;
     } else {
       return val != -1;
     }
   }
 }