code: function drawRenderLayer (ctx, layer) {
    var customDrawFunc;
  
    // Performance: avoid drawing hidden layers.
    if (typeof layer.alpha === 'number' && layer.alpha <= 0) {
      return;
    }
  
    switch (layer.type) {
      case 'image':
        customDrawFunc = drawImageRenderLayer;
        break;
  
      case 'text':
        customDrawFunc = drawTextRenderLayer;
        break;
  
      case 'gradient':
        customDrawFunc = drawGradientRenderLayer;
        break;
    }
  
    // Establish drawing context for certain properties:
    // - alpha
    // - translate
    var saveContext = (layer.alpha !== null && layer.alpha < 1) ||
                      (layer.translateX || layer.translateY);
  
    if (saveContext) {
      ctx.save();
  
      // Alpha:
      if (layer.alpha !== null && layer.alpha < 1) {
        ctx.globalAlpha = layer.alpha;
      }
  
      // Translation:
      if (layer.translateX || layer.translateY) {
        ctx.translate(layer.translateX || 0, layer.translateY || 0);
      }
    }
  
    // If the layer is bitmap-cacheable, draw in a pooled off-screen canvas.
    // We disable backing stores on pad since we flip there.
    if (layer.backingStoreId) {
      drawCacheableRenderLayer(ctx, layer, customDrawFunc);
    } else {
      // Draw default properties, such as background color.
      ctx.save();
      drawBaseRenderLayer(ctx, layer);
  
      // Draw custom properties if needed.
      customDrawFunc && customDrawFunc(ctx, layer);
      ctx.restore();
  
      // Draw child layers, sorted by their z-index.
      if (layer.children) {
        layer.children.slice().sort(sortByZIndexAscending).forEach(function (childLayer) {
          drawRenderLayer(ctx, childLayer);
        });
      }
    }
  
    // Pop the context state if we established a new drawing context.
    if (saveContext) {
      ctx.restore();
    }
  }
docs: Draw a RenderLayer instance to a <canvas> context.
  
  @param {CanvasRenderingContext2d} ctx
  @param {RenderLayer} layer