shithub: riscv

Download patch

ref: 7e744bda2bfe0c664890b0f844591793fb08c976
parent: 2fdb279101563f0e72a11a83e29c40ccda924667
author: cinap_lenrek <[email protected]>
date: Thu Oct 6 18:49:12 EDT 2011

gif: implement dispose method for animations, do composing offscreen for speed

--- a/sys/src/cmd/jpg/gif.c
+++ b/sys/src/cmd/jpg/gif.c
@@ -13,7 +13,6 @@
 int		output = 0;
 ulong	outchan = CMAP8;
 Image	**allims;
-Image	**allmasks;
 int		which;
 int		defaultcolor = 1;
 
@@ -50,9 +49,7 @@
 		return;
 	r = imager();
 	border(screen, r, -Border, nil, ZP);
-	r.min.x += allims[which]->r.min.x - allims[0]->r.min.x;
-	r.min.y += allims[which]->r.min.y - allims[0]->r.min.y;
-	drawop(screen, r, allims[which], allmasks[which], allims[which]->r.min, SoverD);
+	draw(screen, r, allims[which], nil, allims[which]->r.min);
 	flushimage(display, 1);
 }
 
@@ -283,7 +280,8 @@
 show(int fd, char *name)
 {
 	Rawimage **images, **rgbv;
-	Image **ims, **masks;
+	Image *tmp, *msk, *img, *dst, **ims;
+	Rectangle r;
 	int j, k, n, ch, nloop, loopcount, dt;
 	char *err;
 	char buf[32];
@@ -295,16 +293,18 @@
 		return "decode";
 	}
 	for(n=0; images[n]; n++)
-		;
+		if(n == 0)
+			r = images[n]->r;
+		else
+			combinerect(&r, images[n]->r);
+	tmp = nil;
 	ims = malloc((n+1)*sizeof(Image*));
-	masks = malloc((n+1)*sizeof(Image*));
 	rgbv = malloc((n+1)*sizeof(Rawimage*));
-	if(masks==nil || rgbv==nil || ims==nil){
+	if(rgbv==nil || ims==nil){
 		fprint(2, "gif: malloc of masks for %s failed: %r\n", name);
 		err = "malloc";
 		goto Return;
 	}
-	memset(masks, 0, (n+1)*sizeof(Image*));
 	memset(ims, 0, (n+1)*sizeof(Image*));
 	memset(rgbv, 0, (n+1)*sizeof(Rawimage*));
 	if(!dflag){
@@ -331,26 +331,46 @@
 			goto Return;
 		}
 		if(!dflag){
-			masks[k] = transparency(images[k], name);
+			msk = transparency(images[k], name);
 			if(rgbv[k]->chandesc == CY)
-				ims[k] = allocimage(display, rgbv[k]->r, GREY8, 0, 0);
+				img = allocimage(display, rgbv[k]->r, GREY8, 0, 0);
 			else
-				ims[k] = allocimage(display, rgbv[k]->r, outchan, 0, 0);
-			if(ims[k] == nil){
+				img = allocimage(display, rgbv[k]->r, outchan, 0, 0);
+			if(tmp == nil)
+				tmp = allocimage(display, r, img->chan, 0, DWhite);
+			ims[k]= dst = allocimage(display, r, tmp->chan, 0, DWhite);
+			if(tmp == nil || img == nil || dst == nil){
 				fprint(2, "gif: allocimage %s failed: %r\n", name);
 				err = "allocimage";
 				goto Return;
 			}
-			if(loadimage(ims[k], ims[k]->r, rgbv[k]->chans[0], rgbv[k]->chanlen) < 0){
+			if(loadimage(img, img->r, rgbv[k]->chans[0], rgbv[k]->chanlen) < 0){
 				fprint(2, "gif: loadimage %s failed: %r\n", name);
 				err = "loadimage";
 				goto Return;
 			}
+			switch((images[k]->gifflags>>2)&7){
+			case 0:
+			case 1:
+				draw(tmp, img->r, img, msk, img->r.min);
+				draw(dst, tmp->r, tmp, nil, tmp->r.min);
+				break;
+			case 2:
+				draw(tmp, img->r, display->white, msk, img->r.min);
+				/* no break */
+			case 3:
+				draw(dst, tmp->r, tmp, nil, tmp->r.min);
+				draw(dst, img->r, img, msk, img->r.min);
+				break;
+			}
+			freeimage(msk);
+			freeimage(img);
 		}
 	}
+	if(tmp)
+		freeimage(tmp);
 
 	allims = ims;
-	allmasks = masks;
 	loopcount = images[0]->gifloopcount;
 	if(!dflag){
 		nloop = 0;
@@ -362,7 +382,8 @@
 				if(dt < 50)
 					dt = 50;
 				while(n==1 || ecankbd()){
-					if((ch=ekbd())=='q' || ch==0x7F || ch==0x04)	/* an odd, democratic list */
+					/* an odd, democratic list */
+					if((ch=ekbd())=='q' || ch==0x7F || ch==0x04)
 						exits(nil);
 					if(ch == '\n')
 						goto Out;
@@ -373,7 +394,7 @@
 		/* loop count has run out */
 		ekbd();
     Out:
-		drawop(screen, screen->clipr, display->white, nil, ZP, S);
+		draw(screen, screen->clipr, display->white, nil, ZP);
 	}
 	if(n>1 && output)
 		fprint(2, "gif: warning: only writing first image in %d-image GIF %s\n", n, name);
@@ -402,7 +423,6 @@
 
     Return:
 	allims = nil;
-	allmasks = nil;
 	for(k=0; images[k]; k++){
 		for(j=0; j<images[k]->nchans; j++)
 			free(images[k]->chans[j]);
@@ -410,12 +430,10 @@
 		if(rgbv[k])
 			free(rgbv[k]->chans[0]);
 		freeimage(ims[k]);
-		freeimage(masks[k]);
 		free(images[k]);
 		free(rgbv[k]);
 	}
 	free(images);
-	free(masks);
 	free(ims);
 	return err;
 }