code: public boolean hasDecompBoundary(int c, boolean before) {
          for(;;) {
              if(c<minDecompNoCP) {
                  return true;
              }
              int norm16=getNorm16(c);
              if(isHangul(norm16) || isDecompYesAndZeroCC(norm16)) {
                  return true;
              } else if(norm16>MIN_NORMAL_MAYBE_YES) {
                  return false;  // ccc!=0
              } else if(isDecompNoAlgorithmic(norm16)) {
                  c=mapAlgorithmic(c, norm16);
              } else {
                  // c decomposes, get everything from the variable-length extra data
                  int firstUnit=extraData.charAt(norm16);
                  if((firstUnit&MAPPING_LENGTH_MASK)==0) {
                      return false;
                  }
                  if(!before) {
                      // decomp after-boundary: same as hasFCDBoundaryAfter(),
                      // fcd16<=1 || trailCC==0
                      if(firstUnit>0x1ff) {
                          return false;  // trailCC>1
                      }
                      if(firstUnit<=0xff) {
                          return true;  // trailCC==0
                      }
                      // if(trailCC==1) test leadCC==0, same as checking for before-boundary
                  }
                  // true if leadCC==0 (hasFCDBoundaryBefore())
                  return (firstUnit&MAPPING_HAS_CCC_LCCC_WORD)==0 || (extraData.charAt(norm16-1)&0xff00)==0;
              }
          }
      }
docs: at the cost of building the FCD trie for a decomposition normalizer.