OMG I’m sorry for the delay!!!
Finally, this saturday morning I have some spare time 
I cast the shadow using some trigonometry. If you know the location of a polygon point and the location of the light source, you can get the expression of the line that connects them. This line is one of the rays casted by the shadow.
I use polygons, not areas. I just add points to that Polygon and then I send the polygon to render. Pretty fast and simple.
I calculate all the shadow polygons in real time, it is not very resource consuming. This is some graphical sample of what I do. lines p3-p4 and p2-p4 are ignored as they are in the back of the object.
https://dl.dropboxusercontent.com/u/96150028/bitmap.png
I agree with you that
This is part of the code (removed some non important stuff) . It is a mess and it is full of spanish variable names, so it may be quite confusing for you. I will try to fix this some day. Anyways I hope that you will get the general idea.
For any doubt, please ask me!! ;(
//I call this method n times for each light, where n is the number of objects inside the scene
//ii: object number ii of the scene
//luz_baseX,int luz_base, screen location of the light
//distancia_fuera: distance of shadow trail
//lightScale: scale of the light
//gsombras: volatileimage where I store all the shadows
//dimMaxMedia: size/ of the light
private void AddSombras_to_luz(int ii,int luz_baseX,int luz_baseY,float distancia_fuera,float lightScale,Graphics2D gbsombras,int dimMaxMedia){
//LIGHT POSITION ON SCREEN (X,Y)
float centroX=(luz_baseX*light_resolution);
float centroY=(luz_baseY*light_resolution);
int quita_baseX,quita_baseY;
//POLYGON THAT STORES THE IMAGE CONTOUR
Polygon quita;
//GET POLYGON
if (!A_e.get_non_bg_objects(ii).get_cast_shadow()) return;
quita =A_e.get_non_bg_objects(ii).getPolygon(tiempoms);
//LOCATION OF THE UP-LEFT CORNER OF THIS POLYGON ON SCREEN
quita_baseX=A_e.get_non_bg_objects_x(ii);
quita_baseY=A_e.get_non_bg_objects_y(ii);
//NO POLYGON OR LESS THAN 3 VERTEX
if (quita== null || quita.npoints<3) return;
boolean anterior_shadow=false;
int cont=0;
int pos=0;
//two points of the object polygon
float pto1_x,pto1_y,pto2_x,pto2_y;
//distance from these points to light source
float dist1,dist2;
pto2_x=((quita_baseX+quita.xpoints[0]));
pto2_y=((quita_baseY+quita.ypoints[0]));
dist2=(float)Math.sqrt( (pto2_y-centroY)*(pto2_y-centroY)+(pto2_x-centroX)*(pto2_x-centroX));
//for each point of the polygon
while(cont<quita.npoints){
boolean actual_shadow=true;
//move point 2 to point 1
pto1_x=pto2_x;
pto1_y=pto2_y;
//read a new point from the polygon
if (pos<quita.npoints-1) {
pto2_x=((quita_baseX+quita.xpoints[pos+1]));
pto2_y=((quita_baseY+quita.ypoints[pos+1]));}
else {
pto2_x=((quita_baseX+quita.xpoints[0]));
pto2_y=((quita_baseY+quita.ypoints[0]));}
//distances to light source
dist1=dist2;
dist2=(float)Math.sqrt( (pto2_y-centroY)*(pto2_y-centroY)+(pto2_x-centroX)*(pto2_x-centroX));
//optimizations
//this vertex is outside light range, it should not project shadow
if (dist1>(dimMaxMedia)*lightScale && dist2>(dimMaxMedia)*lightScale ) {actual_shadow=false;}
else{
//the line between these two points creales a line. is this line in the front side of the object or in the back side
//if it is in the back side it should not project a light (useless)
//we calculate the bisector and we move us 4 pixels from the middle of the line to the line in the direction of the bisector.
//is we are inside the polygon we don't project a shadow, othwerwise we project it
float bisectriz_X=(pto1_x+pto2_x)*0.5f;
float bisectriz_Y=(pto1_y+pto2_y)*0.5f;
float dist_bis=(float)Math.sqrt( (bisectriz_Y-centroY)*(bisectriz_Y-centroY)+(bisectriz_X-centroX)*(bisectriz_X-centroX));
float bcos_1=(bisectriz_X-centroX)/dist_bis;
float bsin_1=(bisectriz_Y-centroY)/dist_bis;
float binIn_X=(bisectriz_X -bcos_1*4);
float binIn_Y=(bisectriz_Y-bsin_1*4);
if (quita.contains((binIn_X*light_resolution_inv-(quita_baseX)),
(binIn_Y*light_resolution_inv-(quita_baseY)))) {actual_shadow=false;}}
if (cont==0 && actual_shadow) {if (pos==quita.npoints-1) break; pos++;continue;}
//even more optimization!!
//cases anterior_shadow, actual shadow
// false true add pto 3 (shadow ray) y 1
// false false no shadow is projected, we ignore these points.
// true true add pto 1.
// true false (||actual=last) add pto 1, pto 2, pto 4 (shadow ray) and render
float cos_1 = (pto1_x - centroX) / dist1;
float sin_1 = (pto1_y - centroY) / dist1;
float cos_2 = (pto2_x - centroX) / dist2;
float sin_2 = (pto2_y - centroY) / dist2;
if (actual_shadow == true) {
if (anterior_shadow == true) {
//add point to the polygons
quita2.addPoint(Math.round(pto2_x+ cos_2*2), Math.round(pto2_y+ sin_2*2));
} else {
float pto3_X = (centroX + cos_1 * distancia_fuera);
float pto3_Y = (centroY + sin_1 * distancia_fuera);
//add point to the polygons
quita2.addPoint(Math.round(pto3_X), Math.round(pto3_Y));
quita2.addPoint(Math.round(pto1_x+ cos_1*2), Math.round(pto1_y+ sin_1*2));
quita2.addPoint(Math.round(pto2_x+ cos_2*2), Math.round(pto2_y+ sin_2*2));}
if (cont == quita.npoints - 1) {
float pto4_X = (centroX + cos_2 * distancia_fuera);
float pto4_Y = (centroY + sin_2 * distancia_fuera);
//add point to the polygons
quita2.addPoint(Math.round(pto4_X+ cos_2*2), Math.round(pto4_Y+ sin_2*2));
//render the polygon
{ paintShadow(gbsombras);}
quita2.reset();}
} else {
if (anterior_shadow == true) {
float pto3_X = (pto1_x + cos_1 * distancia_fuera);
float pto3_Y = (pto1_y + sin_1 * distancia_fuera);
//add point to the polygons
quita2.addPoint(Math.round(pto3_X+ cos_1*2), Math.round(pto3_Y+ sin_1*2));
//render the polygon
paintShadow(gbsombras);
quita2.reset();
}
}
anterior_shadow=actual_shadow;
cont++;
pos++;if (pos==quita.npoints) pos=0;
}
}