draw.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       draw.c (4063B)
       ---
            1 #include "u.h"
            2 #include "lib.h"
            3 #include "draw.h"
            4 #include "memdraw.h"
            5 #include "memlayer.h"
            6 
            7 struct Draw
            8 {
            9         Point        deltas;
           10         Point        deltam;
           11         Memlayer                *dstlayer;
           12         Memimage        *src;
           13         Memimage        *mask;
           14         int        op;
           15 };
           16 
           17 static
           18 void
           19 ldrawop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave)
           20 {
           21         struct Draw *d;
           22         Point p0, p1;
           23         Rectangle oclipr, srcr, r, mr;
           24         int ok;
           25 
           26         d = etc;
           27         if(insave && d->dstlayer->save==nil)
           28                 return;
           29 
           30         p0 = addpt(screenr.min, d->deltas);
           31         p1 = addpt(screenr.min, d->deltam);
           32 
           33         if(insave){
           34                 r = rectsubpt(screenr, d->dstlayer->delta);
           35                 clipr = rectsubpt(clipr, d->dstlayer->delta);
           36         }else
           37                 r = screenr;
           38 
           39         /* now in logical coordinates */
           40 
           41         /* clipr may have narrowed what we should draw on, so clip if necessary */
           42         if(!rectinrect(r, clipr)){
           43                 oclipr = dst->clipr;
           44                 dst->clipr = clipr;
           45                 ok = drawclip(dst, &r, d->src, &p0, d->mask, &p1, &srcr, &mr);
           46                 dst->clipr = oclipr;
           47                 if(!ok)
           48                         return;
           49         }
           50         memdraw(dst, r, d->src, p0, d->mask, p1, d->op);
           51 }
           52 
           53 void
           54 memdraw(Memimage *dst, Rectangle r, Memimage *src, Point p0, Memimage *mask, Point p1, int op)
           55 {
           56         struct Draw d;
           57         Rectangle srcr, tr, mr;
           58         Memlayer *dl, *sl;
           59 
           60         if(drawdebug)
           61                 iprint("memdraw %p %R %p %P %p %P\n", dst, r, src, p0, mask, p1);
           62 
           63         if(mask == nil)
           64                 mask = memopaque;
           65 
           66         if(mask->layer){
           67 if(drawdebug)        iprint("mask->layer != nil\n");
           68                 return;        /* too hard, at least for now */
           69         }
           70 
           71     Top:
           72         if(dst->layer==nil && src->layer==nil){
           73                 memimagedraw(dst, r, src, p0, mask, p1, op);
           74                 return;
           75         }
           76 
           77         if(drawclip(dst, &r, src, &p0, mask, &p1, &srcr, &mr) == 0){
           78 if(drawdebug)        iprint("drawclip dstcr %R srccr %R maskcr %R\n", dst->clipr, src->clipr, mask->clipr);
           79                 return;
           80         }
           81 
           82         /*
           83           * Convert to screen coordinates.
           84          */
           85         dl = dst->layer;
           86         if(dl != nil){
           87                 r.min.x += dl->delta.x;
           88                 r.min.y += dl->delta.y;
           89                 r.max.x += dl->delta.x;
           90                 r.max.y += dl->delta.y;
           91         }
           92     Clearlayer:
           93         if(dl!=nil && dl->clear){
           94                 if(src == dst){
           95                         p0.x += dl->delta.x;
           96                         p0.y += dl->delta.y;
           97                         src = dl->screen->image;
           98                 }
           99                 dst = dl->screen->image;
          100                 goto Top;
          101         }
          102 
          103         sl = src->layer;
          104         if(sl != nil){
          105                 p0.x += sl->delta.x;
          106                 p0.y += sl->delta.y;
          107                 srcr.min.x += sl->delta.x;
          108                 srcr.min.y += sl->delta.y;
          109                 srcr.max.x += sl->delta.x;
          110                 srcr.max.y += sl->delta.y;
          111         }
          112 
          113         /*
          114          * Now everything is in screen coordinates.
          115          * mask is an image.  dst and src are images or obscured layers.
          116          */
          117 
          118         /*
          119          * if dst and src are the same layer, just draw in save area and expose.
          120          */
          121         if(dl!=nil && dst==src){
          122                 if(dl->save == nil)
          123                         return;        /* refresh function makes this case unworkable */
          124                 if(rectXrect(r, srcr)){
          125                         tr = r;
          126                         if(srcr.min.x < tr.min.x){
          127                                 p1.x += tr.min.x - srcr.min.x;
          128                                 tr.min.x = srcr.min.x;
          129                         }
          130                         if(srcr.min.y < tr.min.y){
          131                                 p1.y += tr.min.x - srcr.min.x;
          132                                 tr.min.y = srcr.min.y;
          133                         }
          134                         if(srcr.max.x > tr.max.x)
          135                                 tr.max.x = srcr.max.x;
          136                         if(srcr.max.y > tr.max.y)
          137                                 tr.max.y = srcr.max.y;
          138                         memlhide(dst, tr);
          139                 }else{
          140                         memlhide(dst, r);
          141                         memlhide(dst, srcr);
          142                 }
          143                 memdraw(dl->save, rectsubpt(r, dl->delta), dl->save,
          144                         subpt(srcr.min, src->layer->delta), mask, p1, op);
          145                 memlexpose(dst, r);
          146                 return;
          147         }
          148 
          149         if(sl){
          150                 if(sl->clear){
          151                         src = sl->screen->image;
          152                         if(dl != nil){
          153                                 r.min.x -= dl->delta.x;
          154                                 r.min.y -= dl->delta.y;
          155                                 r.max.x -= dl->delta.x;
          156                                 r.max.y -= dl->delta.y;
          157                         }
          158                         goto Top;
          159                 }
          160                 /* relatively rare case; use save area */
          161                 if(sl->save == nil)
          162                         return;        /* refresh function makes this case unworkable */
          163                 memlhide(src, srcr);
          164                 /* convert back to logical coordinates */
          165                 p0.x -= sl->delta.x;
          166                 p0.y -= sl->delta.y;
          167                 srcr.min.x -= sl->delta.x;
          168                 srcr.min.y -= sl->delta.y;
          169                 srcr.max.x -= sl->delta.x;
          170                 srcr.max.y -= sl->delta.y;
          171                 src = src->layer->save;
          172         }
          173 
          174         /*
          175          * src is now an image.  dst may be an image or a clear layer
          176          */
          177         if(dst->layer==nil)
          178                 goto Top;
          179         if(dst->layer->clear)
          180                 goto Clearlayer;
          181 
          182         /*
          183          * dst is an obscured layer
          184          */
          185         d.deltas = subpt(p0, r.min);
          186         d.deltam = subpt(p1, r.min);
          187         d.dstlayer = dl;
          188         d.src = src;
          189         d.op = op;
          190         d.mask = mask;
          191         _memlayerop(ldrawop, dst, r, r, &d);
          192 }