class SoftPaintContext implements PaintContext
    {
        private final PaintContext context;

        SoftPaintContext(PaintContext context)
        {
            this.context = context;
        }

        @Override
        public ColorModel getColorModel()
        {
            return ARGB_COLOR_MODEL;
        }

        @Override
        public Raster getRaster(int x1, int y1, int w, int h)
        {<FILL_FUNCTION_BODY>}

        @Override
        public void dispose()
        {
            context.dispose();
        }
    }

            Raster raster = context.getRaster(x1, y1, w, h);
            ColorModel rasterCM = context.getColorModel();
            float[] input = null;
            Float[] map = null;

            if (transferFunction != null)
            {
                map = new Float[256];
                input = new float[1];
            }

            // buffer
            WritableRaster output = getColorModel().createCompatibleWritableRaster(w, h);

            // the soft mask has its own bbox
            x1 = x1 - (int)bboxDevice.getX();
            y1 = y1 - (int)bboxDevice.getY();

            int[] gray = new int[4];
            Object pixelInput = null;
            int[] pixelOutput = new int[4];
            for (int y = 0; y < h; y++)
            {
                for (int x = 0; x < w; x++)
                {
                    pixelInput = raster.getDataElements(x, y, pixelInput);

                    pixelOutput[0] = rasterCM.getRed(pixelInput);
                    pixelOutput[1] = rasterCM.getGreen(pixelInput);
                    pixelOutput[2] = rasterCM.getBlue(pixelInput);
                    pixelOutput[3] = rasterCM.getAlpha(pixelInput);
                    
                    // get the alpha value from the gray mask, if within mask bounds
                    gray[0] = 0;
                    if (x1 + x >= 0 && y1 + y >= 0 && x1 + x < mask.getWidth() && y1 + y < mask.getHeight())
                    {
                        mask.getRaster().getPixel(x1 + x, y1 + y, gray);
                        int g = gray[0];
                        if (transferFunction != null)
                        {
                            // apply transfer function
                            try
                            {
                                if (map[g] != null)
                                {
                                    // was calculated before
                                    pixelOutput[3] = Math.round(pixelOutput[3] * map[g]);
                                }
                                else
                                {
                                    // calculate and store in map
                                    input[0] = g / 255f;
                                    float f = transferFunction.eval(input)[0];
                                    map[g] = f;
                                    pixelOutput[3] = Math.round(pixelOutput[3] * f);
                                }
                            }
                            catch (IOException ex)
                            {
                                // ignore exception, treat as outside
                                LOG.debug("Couldn't apply transferFunction - treating as outside", ex);
                                pixelOutput[3] = Math.round(pixelOutput[3] * (bc / 255f));
                            }
                        }
                        else
                        {
                            pixelOutput[3] = Math.round(pixelOutput[3] * (g / 255f));
                        }
                    }
                    else
                    {
                        pixelOutput[3] = Math.round(pixelOutput[3] * (bc / 255f));
                    }
                    output.setPixel(x, y, pixelOutput);
                }
            }

            return output;
        
<no_super_class>