12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345 |
- #include <lib9.h>
- #include <kernel.h>
- #include "interp.h"
- #include "isa.h"
- #include "runt.h"
- #include "raise.h"
- #include "drawmod.h"
- #include "draw.h"
- #include "drawif.h"
- #include "memdraw.h"
- #include "memlayer.h"
- /*
- * When a Display is remote, it must be locked to synchronize the
- * outgoing message buffer with the refresh demon, which runs as a
- * different process. When it is local, the refresh demon does nothing
- * and it is sufficient to use the interpreter's own acquire/release protection
- * to lock the buffer.
- *
- * Most action to the buffer is caused by calls from Limbo, so locking at
- * the top before going into the library is good enough. However, the
- * garbage collector can call the free routines at other times, so they
- * need to protect themselves whether called through the Draw module
- * or not; hence the need for check against recursive locking in lockdisplay().
- * This also means that we needn't lock around calls to destroy if it's
- * extra work to do so.
- */
- typedef struct Cache Cache;
- typedef struct DRef DRef;
- typedef struct DDisplay DDisplay;
- typedef struct DImage DImage;
- typedef struct DScreen DScreen;
- typedef struct DFont DFont;
- struct Cache
- {
- int ref;
- char* name;
- Display*display;
- union{
- Subfont* sf;
- Font* f;
- void* ptr;
- }u;
- Cache* next;
- };
- /* not visible to Limbo; used only for internal reference counting */
- struct DRef
- {
- int ref;
- Display* display;
- };
- struct DDisplay
- {
- Draw_Display drawdisplay;
- Display* display;
- DRef* dref;
- };
- struct DImage
- {
- Draw_Image drawimage;
- Image* image;
- void* refreshptr;
- DRef* dref;
- int flush;
- };
- struct DScreen
- {
- Draw_Screen drawscreen;
- Screen* screen;
- DRef* dref;
- };
- struct DFont
- {
- Draw_Font drawfont;
- Font* font;
- DRef* dref;
- };
- Cache* sfcache[BIHASH];
- Cache* fcache[BIHASH];
- void* cacheqlock;
- static Cache *cachelookup(Cache**, Display*, char*);
- uchar fontmap[] = Draw_Font_map;
- uchar imagemap[] = Draw_Image_map;
- uchar screenmap[] = Draw_Screen_map;
- uchar displaymap[] = Draw_Display_map;
- Type* TFont;
- Type* TImage;
- Type* TScreen;
- Type* TDisplay;
- Draw_Image* allocdrawimage(DDisplay*, Draw_Rect, ulong, Image*, int, int);
- Draw_Image* color(DDisplay*, ulong);
- Draw_Screen *mkdrawscreen(Screen*, Draw_Display*);
- char deffontname[] = "*default*";
- void refreshslave(Display*);
- void subfont_close(Subfont*);
- void freeallsubfonts(Display*);
- void
- drawmodinit(void)
- {
- TFont = dtype(freedrawfont, sizeof(DFont), fontmap, sizeof(fontmap));
- TImage = dtype(freedrawimage, sizeof(DImage), imagemap, sizeof(imagemap));
- TScreen = dtype(freedrawscreen, sizeof(DScreen), screenmap, sizeof(screenmap));
- TDisplay = dtype(freedrawdisplay, sizeof(DDisplay), displaymap, sizeof(displaymap));
- builtinmod("$Draw", Drawmodtab, Drawmodlen);
- }
- static int
- drawhash(char *s)
- {
- int h;
- h = 0;
- while(*s){
- h += *s++;
- h <<= 1;
- if(h & (1<<8))
- h |= 1;
- }
- return (h&0xFFFF)%BIHASH;
- }
- static Cache*
- cachelookup(Cache *cache[], Display *d, char *name)
- {
- Cache *c;
- libqlock(cacheqlock);
- c = cache[drawhash(name)];
- while(c!=nil && (d!=c->display || strcmp(name, c->name)!=0))
- c = c->next;
- libqunlock(cacheqlock);
- return c;
- }
- Cache*
- cacheinstall(Cache **cache, Display *d, char *name, void *ptr, char *type)
- {
- Cache *c;
- int hash;
- USED(type);
- c = cachelookup(cache, d, name);
- if(c){
- /* print("%s %s already in cache\n", type, name); /**/
- return nil;
- }
- c = malloc(sizeof(Cache));
- if(c == nil)
- return nil;
- hash = drawhash(name);
- c->ref = 0; /* will be incremented by caller */
- c->display = d;
- c->name = strdup(name);
- c->u.ptr = ptr;
- libqlock(cacheqlock);
- c->next = cache[hash];
- cache[hash] = c;
- libqunlock(cacheqlock);
- return c;
- }
- void
- cacheuninstall(Cache **cache, Display *d, char *name, char *type)
- {
- Cache *c, *prev;
- int hash;
- hash = drawhash(name);
- libqlock(cacheqlock);
- c = cache[hash];
- if(c == nil){
- Notfound:
- libqunlock(cacheqlock);
- print("%s not in %s cache\n", name, type);
- return;
- }
- prev = nil;
- while(c!=nil && (d!=c->display || strcmp(name, c->name)!=0)){
- prev = c;
- c = c->next;
- }
- if(c == nil)
- goto Notfound;
- if(prev == 0)
- cache[hash] = c->next;
- else
- prev->next = c->next;
- libqunlock(cacheqlock);
- free(c->name);
- free(c);
- }
- Image*
- lookupimage(Draw_Image *di)
- {
- Display *disp;
- Image *i;
- int locked;
- if(di == H || D2H(di)->t != TImage)
- return nil;
- i = ((DImage*)di)->image;
- if(i == nil)
- return nil;
- if(!eqrect(IRECT(di->clipr), i->clipr) || di->repl!=i->repl){
- disp = i->display;
- locked = lockdisplay(disp);
- replclipr(i, di->repl, IRECT(di->clipr));
- if(locked)
- unlockdisplay(disp);
- }
- return i;
- }
- Screen*
- lookupscreen(Draw_Screen *ds)
- {
- if(ds == H || D2H(ds)->t != TScreen)
- return nil;
- return ((DScreen*)ds)->screen;
- }
- Font*
- lookupfont(Draw_Font *df)
- {
- if(df == H || D2H(df)->t != TFont)
- return nil;
- return ((DFont*)df)->font;
- }
- Display*
- lookupdisplay(Draw_Display *dd)
- {
- if(dd == H || D2H(dd)->t != TDisplay)
- return nil;
- return ((DDisplay*)dd)->display;
- }
- Image*
- checkimage(Draw_Image *di)
- {
- Image *i;
- if(di == H)
- error("nil Image");
- i = lookupimage(di);
- if(i == nil)
- error(exType);
- return i;
- }
- Screen*
- checkscreen(Draw_Screen *ds)
- {
- Screen *s;
- if(ds == H)
- error("nil Screen");
- s = lookupscreen(ds);
- if(s == nil)
- error(exType);
- return s;
- }
- Font*
- checkfont(Draw_Font *df)
- {
- Font *f;
- if(df == H)
- error("nil Font");
- f = lookupfont(df);
- if(f == nil)
- error(exType);
- return f;
- }
- Display*
- checkdisplay(Draw_Display *dd)
- {
- Display *d;
- if(dd == H)
- error("nil Display");
- d = lookupdisplay(dd);
- if(d == nil)
- error(exType);
- return d;
- }
- void
- Display_allocate(void *fp)
- {
- F_Display_allocate *f;
- char buf[128], *dev;
- Subfont *df;
- Display *display;
- DDisplay *dd;
- Heap *h;
- Draw_Rect r;
- DRef *dr;
- Cache *c;
- f = fp;
- destroy(*f->ret);
- *f->ret = H;
- if(cacheqlock == nil){
- cacheqlock = libqlalloc();
- if(cacheqlock == nil)
- return;
- }
- dev = string2c(f->dev);
- if(dev[0] == 0)
- dev = 0;
- display = initdisplay(dev, dev, nil); /* TO DO: win, error */
- if(display == 0)
- return;
- dr = malloc(sizeof(DRef));
- if(dr == nil)
- return;
- h = heap(TDisplay);
- if(h == H){
- closedisplay(display);
- return;
- }
- dd = H2D(DDisplay*, h);
- dd->display = display;
- *f->ret = &dd->drawdisplay;
- dd->dref = dr;
- display->limbo = dr;
- dr->display = display;
- dr->ref = 1;
- df = getdefont(display);
- if(df){
- display->defaultsubfont = df;
- sprint(buf, "%d %d\n0 %d\t%s\n", df->height, df->ascent,
- df->n-1, deffontname);
- display->defaultfont = buildfont(display, buf, deffontname);
- if(display->defaultfont){
- c = cacheinstall(fcache, display, deffontname, display->defaultfont, "font");
- if(c)
- c->ref++;
- /* else BUG? */
- }
- }
- R2R(r, display->image->r);
- dd->drawdisplay.image = allocdrawimage(dd, r, display->image->chan, display->image, 0, 0);
- R2R(r, display->white->r);
- dd->drawdisplay.black = allocdrawimage(dd, r, display->black->chan, display->black, 1, 0);
- dd->drawdisplay.white = allocdrawimage(dd, r, display->white->chan, display->white, 1, 0);
- dd->drawdisplay.opaque = allocdrawimage(dd, r, display->opaque->chan, display->opaque, 1, 0);
- dd->drawdisplay.transparent = allocdrawimage(dd, r, display->transparent->chan, display->transparent, 1, 0);
- /* don't call unlockdisplay because the qlock was left up by initdisplay */
- libqunlock(display->qlock);
- }
- void
- Display_getwindow(void *fp)
- {
- F_Display_getwindow *f;
- Display *disp;
- int locked;
- Image *image;
- Screen *screen;
- char *wn;
- void *r;
- f = fp;
- r = f->ret->t0;
- f->ret->t0 = H;
- destroy(r);
- r = f->ret->t1;
- f->ret->t1 = H;
- destroy(r);
- disp = checkdisplay(f->d);
- if(f->winname == H)
- wn = "/dev/winname";
- else
- wn = string2c(f->winname);
- if(f->image == H)
- image = nil;
- else
- image = checkimage(f->image);
- if(f->screen == H)
- screen = nil;
- else
- screen = checkscreen(f->screen);
- locked = lockdisplay(disp);
- if(gengetwindow(disp, wn, &image, &screen, f->backup) < 0){
- /* TO DO: eliminate f->image and f->screen's references to Image and Screen */
- goto Return;
- }
- if(screen != nil){
- if(f->screen != H){
- f->ret->t0 = f->screen;
- D2H(f->screen)->ref++;
- }else
- f->ret->t0 = mkdrawscreen(screen, f->d);
- }
- if(image != nil){
- if(f->image != H){
- f->ret->t1 = f->image;
- D2H(f->image)->ref++;
- }else
- f->ret->t1 = mkdrawimage(image, f->ret->t0, f->d, nil);
- }
- Return:
- if(locked)
- unlockdisplay(disp);
- }
- void
- Display_startrefresh(void *fp)
- {
- F_Display_startrefresh *f;
- Display *disp;
- f = fp;
- disp = checkdisplay(f->d);
- refreshslave(disp);
- }
- void
- display_dec(void *v)
- {
- DRef *dr;
- Display *d;
- int locked;
- dr = v;
- if(dr->ref-- != 1)
- return;
- d = dr->display;
- locked = lockdisplay(d);
- font_close(d->defaultfont);
- subfont_close(d->defaultsubfont);
- if(locked)
- unlockdisplay(d);
- freeallsubfonts(d);
- closedisplay(d);
- free(dr);
- }
- void
- freedrawdisplay(Heap *h, int swept)
- {
- DDisplay *dd;
- Display *d;
- dd = H2D(DDisplay*, h);
- if(!swept) {
- destroy(dd->drawdisplay.image);
- destroy(dd->drawdisplay.black);
- destroy(dd->drawdisplay.white);
- destroy(dd->drawdisplay.opaque);
- destroy(dd->drawdisplay.transparent);
- }
- /* we've now released dd->image etc.; make sure they're not freed again */
- d = dd->display;
- d->image = nil;
- d->white = nil;
- d->black = nil;
- d->opaque = nil;
- d->transparent = nil;
- display_dec(dd->dref);
- /* Draw_Display header will be freed by caller */
- }
- void
- Display_color(void *fp)
- {
- F_Display_color *f;
- Display *d;
- int locked;
- f = fp;
- destroy(*f->ret);
- *f->ret = H;
- d = checkdisplay(f->d);
- locked = lockdisplay(d);
- *f->ret = color((DDisplay*)f->d, f->color);
- if(locked)
- unlockdisplay(d);
- }
- void
- Image_flush(void *fp)
- {
- F_Image_flush *f;
- Image *d;
- DImage *di;
- int locked;
- f = fp;
- d = checkimage(f->win);
- di = (DImage*)f->win;
- switch(f->func){
- case 0: /* Draw->Flushoff */
- di->flush = 0;
- break;
- case 1: /* Draw->Flushon */
- di->flush = 1;
- /* fall through */
- case 2: /* Draw->Flushnow */
- locked = lockdisplay(d->display);
- if(d->id==0 || d->screen!=0)
- flushimage(d->display, 1);
- if(locked)
- unlockdisplay(d->display);
- break;
- default:
- error(exInval);
- }
- }
- void
- checkflush(Draw_Image *dst)
- {
- DImage *di;
- di = (DImage*)dst;
- if(di->flush && (di->image->id==0 || di->image->screen!=nil))
- flushimage(di->image->display, 1);
- }
- static void
- imagedraw(void *fp, int op)
- {
- F_Image_draw *f;
- Image *d, *s, *m;
- int locked;
- f = fp;
- d = checkimage(f->dst);
- if(f->src == H)
- s = d->display->black;
- else
- s = checkimage(f->src);
- if(f->matte == H)
- m = d->display->white; /* ones */
- else
- m = checkimage(f->matte);
- if(d->display!=s->display || d->display!=m->display)
- return;
- locked = lockdisplay(d->display);
- drawop(d, IRECT(f->r), s, m, IPOINT(f->p), op);
- checkflush(f->dst);
- if(locked)
- unlockdisplay(d->display);
- }
- void
- Image_draw(void *fp)
- {
- imagedraw(fp, SoverD);
- }
- void
- Image_drawop(void *fp)
- {
- F_Image_drawop *f;
- f = fp;
- imagedraw(fp, f->op);
- }
- static void
- imagegendraw(void *fp, int op)
- {
- F_Image_gendraw *f;
- Image *d, *s, *m;
- int locked;
- f = fp;
- d = checkimage(f->dst);
- if(f->src == H)
- s = d->display->black;
- else
- s = checkimage(f->src);
- if(f->matte == H)
- m = d->display->white; /* ones */
- else
- m = checkimage(f->matte);
- if(d->display!=s->display || d->display!=m->display)
- return;
- locked = lockdisplay(d->display);
- gendrawop(d, IRECT(f->r), s, IPOINT(f->p0), m, IPOINT(f->p1), op);
- checkflush(f->dst);
- if(locked)
- unlockdisplay(d->display);
- }
- void
- Image_gendraw(void *fp)
- {
- imagegendraw(fp, SoverD);
- }
- void
- Image_gendrawop(void *fp)
- {
- F_Image_gendrawop *f;
- f = fp;
- imagegendraw(fp, f->op);
- }
- static void
- drawline(void *fp, int op)
- {
- F_Image_line *f;
- Image *d, *s;
- int locked;
- f = fp;
- d = checkimage(f->dst);
- s = checkimage(f->src);
- if(d->display != s->display || f->radius < 0)
- return;
- locked = lockdisplay(d->display);
- lineop(d, IPOINT(f->p0), IPOINT(f->p1), f->end0, f->end1, f->radius, s, IPOINT(f->sp), op);
- checkflush(f->dst);
- if(locked)
- unlockdisplay(d->display);
- }
- void
- Image_line(void *fp)
- {
- drawline(fp, SoverD);
- }
- void
- Image_lineop(void *fp)
- {
- F_Image_lineop *f;
- f = fp;
- drawline(fp, f->op);
- }
- static void
- drawsplinepoly(void *fp, int smooth, int op)
- {
- F_Image_poly *f;
- Image *d, *s;
- int locked;
- f = fp;
- d = checkimage(f->dst);
- s = checkimage(f->src);
- if(d->display != s->display|| f->radius < 0)
- return;
- locked = lockdisplay(d->display);
- /* sleazy: we know that Draw_Points have same shape as Points */
- if(smooth)
- bezsplineop(d, (Point*)f->p->data, f->p->len,
- f->end0, f->end1, f->radius, s, IPOINT(f->sp), op);
- else
- polyop(d, (Point*)f->p->data, f->p->len, f->end0,
- f->end1, f->radius, s, IPOINT(f->sp), op);
- checkflush(f->dst);
- if(locked)
- unlockdisplay(d->display);
- }
- void
- Image_poly(void *fp)
- {
- drawsplinepoly(fp, 0, SoverD);
- }
- void
- Image_polyop(void *fp)
- {
- F_Image_polyop *f;
- f = fp;
- drawsplinepoly(fp, 0, f->op);
- }
- void
- Image_bezspline(void *fp)
- {
- drawsplinepoly(fp, 1, SoverD);
- }
- void
- Image_bezsplineop(void *fp)
- {
- F_Image_bezsplineop *f;
- f = fp;
- drawsplinepoly(fp, 1, f->op);
- }
- static void
- drawbezier(void *fp, int op)
- {
- F_Image_bezier *f;
- Image *d, *s;
- int locked;
- f = fp;
- d = checkimage(f->dst);
- s = checkimage(f->src);
- if(d->display != s->display || f->radius < 0)
- return;
- locked = lockdisplay(d->display);
- bezierop(d, IPOINT(f->a), IPOINT(f->b), IPOINT(f->c),
- IPOINT(f->d), f->end0, f->end1, f->radius, s, IPOINT(f->sp), op);
- checkflush(f->dst);
- if(locked)
- unlockdisplay(d->display);
- }
- void
- Image_bezier(void *fp)
- {
- drawbezier(fp, SoverD);
- }
- void
- Image_bezierop(void *fp)
- {
- F_Image_bezierop *f;
- f = fp;
- drawbezier(fp, f->op);
- }
- static void
- drawfillbezier(void *fp, int op)
- {
- F_Image_fillbezier *f;
- Image *d, *s;
- int locked;
- f = fp;
- d = checkimage(f->dst);
- s = checkimage(f->src);
- if(d->display != s->display)
- return;
- locked = lockdisplay(d->display);
- fillbezierop(d, IPOINT(f->a), IPOINT(f->b), IPOINT(f->c),
- IPOINT(f->d), f->wind, s, IPOINT(f->sp), op);
- checkflush(f->dst);
- if(locked)
- unlockdisplay(d->display);
- }
- void
- Image_fillbezier(void *fp)
- {
- drawfillbezier(fp, SoverD);
- }
- void
- Image_fillbezierop(void *fp)
- {
- F_Image_fillbezierop *f;
- f = fp;
- drawfillbezier(fp, f->op);
- }
- static void
- drawfillsplinepoly(void *fp, int smooth, int op)
- {
- F_Image_fillpoly *f;
- Image *d, *s;
- int locked;
- f = fp;
- d = checkimage(f->dst);
- s = checkimage(f->src);
- if(d->display != s->display)
- return;
- locked = lockdisplay(d->display);
- /* sleazy: we know that Draw_Points have same shape as Points */
- if(smooth)
- fillbezsplineop(d, (Point*)f->p->data, f->p->len,
- f->wind, s, IPOINT(f->sp), op);
- else
- fillpolyop(d, (Point*)f->p->data, f->p->len,
- f->wind, s, IPOINT(f->sp), op);
- checkflush(f->dst);
- if(locked)
- unlockdisplay(d->display);
- }
- void
- Image_fillpoly(void *fp)
- {
- drawfillsplinepoly(fp, 0, SoverD);
- }
- void
- Image_fillpolyop(void *fp)
- {
- F_Image_fillpolyop *f;
- f = fp;
- drawfillsplinepoly(fp, 0, f->op);
- }
- void
- Image_fillbezspline(void *fp)
- {
- drawfillsplinepoly(fp, 1, SoverD);
- }
- void
- Image_fillbezsplineop(void *fp)
- {
- F_Image_fillbezsplineop *f;
- f = fp;
- drawfillsplinepoly(fp, 1, f->op);
- }
- static void
- drawarcellipse(void *fp, int isarc, int alpha, int phi, int op)
- {
- F_Image_arc *f;
- Image *d, *s;
- int locked;
- f = fp;
- d = checkimage(f->dst);
- s = checkimage(f->src);
- if(d->display != s->display || f->thick < 0 || f->a<0 || f->b<0)
- return;
- locked = lockdisplay(d->display);
- if(isarc)
- arcop(d, IPOINT(f->c), f->a, f->b, f->thick, s,
- IPOINT(f->sp), alpha, phi, op);
- else
- ellipseop(d, IPOINT(f->c), f->a, f->b, f->thick, s,
- IPOINT(f->sp), op);
- checkflush(f->dst);
- if(locked)
- unlockdisplay(d->display);
- }
- void
- Image_ellipse(void *fp)
- {
- drawarcellipse(fp, 0, 0, 0, SoverD);
- }
- void
- Image_ellipseop(void *fp)
- {
- F_Image_ellipseop *f;
- f = fp;
- drawarcellipse(fp, 0, 0, 0, f->op);
- }
- void
- Image_arc(void *fp)
- {
- F_Image_arc *f;
- f = fp;
- drawarcellipse(fp, 1, f->alpha, f->phi, SoverD);
- }
- void
- Image_arcop(void *fp)
- {
- F_Image_arcop *f;
- f = fp;
- drawarcellipse(fp, 1, f->alpha, f->phi, f->op);
- }
- static void
- drawfillarcellipse(void *fp, int isarc, int alpha, int phi, int op)
- {
- F_Image_fillarc *f;
- Image *d, *s;
- int locked;
- f = fp;
- d = checkimage(f->dst);
- s = checkimage(f->src);
- if(d->display != s->display || f->a<0 || f->b<0)
- return;
- locked = lockdisplay(d->display);
- if(isarc)
- fillarcop(d, IPOINT(f->c), f->a, f->b, s, IPOINT(f->sp), alpha, phi, op);
- else
- fillellipseop(d, IPOINT(f->c), f->a, f->b, s, IPOINT(f->sp), op);
- checkflush(f->dst);
- if(locked)
- unlockdisplay(d->display);
- }
- void
- Image_fillellipse(void *fp)
- {
- drawfillarcellipse(fp, 0, 0, 0, SoverD);
- }
- void
- Image_fillellipseop(void *fp)
- {
- F_Image_fillellipseop *f;
- f = fp;
- drawfillarcellipse(fp, 0, 0, 0, f->op);
- }
- void
- Image_fillarc(void *fp)
- {
- F_Image_fillarc *f;
- f = fp;
- drawfillarcellipse(fp, 1, f->alpha, f->phi, SoverD);
- }
- void
- Image_fillarcop(void *fp)
- {
- F_Image_fillarcop *f;
- f = fp;
- drawfillarcellipse(fp, 1, f->alpha, f->phi, f->op);
- }
- static void
- drawtext(void *fp, int op)
- {
- F_Image_text *f;
- Font *font;
- Point pt;
- Image *s, *d;
- String *str;
- int locked;
- f = fp;
- if(f->dst == H || f->src == H)
- goto Return;
- if(f->font == H || f->str == H)
- goto Return;
- str = f->str;
- d = checkimage(f->dst);
- s = checkimage(f->src);
- font = checkfont(f->font);
- if(d->display!=s->display || d->display!=font->display)
- return;
- locked = lockdisplay(d->display);
- if(str->len >= 0)
- pt = stringnop(d, IPOINT(f->p), s, IPOINT(f->sp), font, str->Sascii, str->len, op);
- else
- pt = runestringnop(d, IPOINT(f->p), s, IPOINT(f->sp), font, str->Srune, -str->len, op);
- checkflush(f->dst);
- if(locked)
- unlockdisplay(d->display);
- Return:
- P2P(*f->ret, pt);
- }
- void
- Image_text(void *fp)
- {
- drawtext(fp, SoverD);
- }
- void
- Image_textop(void *fp)
- {
- F_Image_textop *f;
- f = fp;
- drawtext(fp, f->op);
- }
- static void
- drawtextbg(void *fp, int op)
- {
- F_Image_textbg *f;
- Font *font;
- Point pt;
- Image *s, *d, *bg;
- String *str;
- int locked;
- f = fp;
- if(f->dst == H || f->src == H)
- goto Return;
- if(f->font == H || f->str == H)
- goto Return;
- str = f->str;
- d = checkimage(f->dst);
- s = checkimage(f->src);
- bg = checkimage(f->bg);
- font = checkfont(f->font);
- if(d->display!=s->display || d->display!=font->display)
- return;
- locked = lockdisplay(d->display);
- if(str->len >= 0)
- pt = stringnbgop(d, IPOINT(f->p), s, IPOINT(f->sp), font, str->Sascii, str->len, bg, IPOINT(f->bgp), op);
- else
- pt = runestringnbgop(d, IPOINT(f->p), s, IPOINT(f->sp), font, str->Srune, -str->len, bg, IPOINT(f->bgp), op);
- checkflush(f->dst);
- if(locked)
- unlockdisplay(d->display);
- Return:
- P2P(*f->ret, pt);
- }
- void
- Image_textbg(void *fp)
- {
- drawtextbg(fp, SoverD);
- }
- void
- Image_textbgop(void *fp)
- {
- F_Image_textbgop *f;
- f = fp;
- drawtextbg(fp, f->op);
- }
- static void
- drawborder(void *fp, int op)
- {
- F_Image_border *f;
- Image *d, *s;
- int locked;
- f = fp;
- d = checkimage(f->dst);
- s = checkimage(f->src);
- if(d->display != s->display)
- return;
- locked = lockdisplay(d->display);
- borderop(d, IRECT(f->r), f->i, s, IPOINT(f->sp), op);
- checkflush(f->dst);
- if(locked)
- unlockdisplay(d->display);
- }
- void
- Image_border(void *fp)
- {
- drawborder(fp, SoverD);
- }
- void
- Display_newimage(void *fp)
- {
- F_Display_newimage *f;
- Display *d;
- int locked;
- f = fp;
- d = checkdisplay(f->d);
- destroy(*f->ret);
- *f->ret = H;
- locked = lockdisplay(d);
- *f->ret = allocdrawimage((DDisplay*)f->d, f->r, f->chans.desc,
- nil, f->repl, f->color);
- if(locked)
- unlockdisplay(d);
- }
- void
- Display_colormix(void *fp)
- {
- F_Display_colormix *f;
- Display *disp;
- Image *i;
- int locked;
- f = fp;
- destroy(*f->ret);
- *f->ret = H;
- disp = checkdisplay(f->d);
- locked = lockdisplay(disp);
- i = allocimagemix(disp, f->c1, f->c2);
- if(locked)
- unlockdisplay(disp);
- *f->ret = mkdrawimage(i, H, f->d, nil);
- }
- void
- Image_readpixels(void *fp)
- {
- F_Image_readpixels *f;
- Rectangle r;
- Image *i;
- int locked;
- f = fp;
- R2R(r, f->r);
- i = checkimage(f->src);
- locked = lockdisplay(i->display);
- *f->ret = unloadimage(i, r, f->data->data, f->data->len);
- if(locked)
- unlockdisplay(i->display);
- }
- void
- Image_writepixels(void *fp)
- {
- Rectangle r;
- F_Image_writepixels *f;
- Image *i;
- int locked;
- f = fp;
- R2R(r, f->r);
- i = checkimage(f->dst);
- locked = lockdisplay(i->display);
- *f->ret = loadimage(i, r, f->data->data, f->data->len);
- checkflush(f->dst);
- if(locked)
- unlockdisplay(i->display);
- }
- void
- Image_arrow(void *fp)
- {
- F_Image_arrow *f;
- f = fp;
- *f->ret = ARROW(f->a, f->b, f->c);
- }
- void
- Image_name(void *fp)
- {
- F_Image_name *f;
- Image *i;
- int locked, ok;
- char *name;
- f = fp;
- *f->ret = -1;
- i = checkimage(f->src);
- name = string2c(f->name);
- locked = lockdisplay(i->display);
- *f->ret = ok = nameimage(i, name, f->in);
- if(locked)
- unlockdisplay(i->display);
- if(ok){
- destroy(f->src->iname);
- if(f->in){
- f->src->iname = f->name;
- D2H(f->name)->ref++;
- }else
- f->src->iname = H;
- }
- }
- Image*
- display_open(Display *disp, char *name)
- {
- Image *i;
- int fd;
- fd = libopen(name, OREAD);
- if(fd < 0)
- return nil;
- i = readimage(disp, fd, 1);
- libclose(fd);
- return i;
- }
- void
- Display_open(void *fp)
- {
- Image *i;
- Display *disp;
- F_Display_open *f;
- f = fp;
- destroy(*f->ret);
- *f->ret = H;
- disp = lookupdisplay(f->d);
- if(disp == nil)
- return;
- i = display_open(disp, string2c(f->name));
- if(i == nil)
- return;
- *f->ret = allocdrawimage((DDisplay*)f->d, DRECT(i->r), i->chan, i, 0, 0);
- }
- void
- Display_namedimage(void *fp)
- {
- F_Display_namedimage *f;
- Display *d;
- Image *i;
- Draw_Image *di;
- int locked;
- f = fp;
- destroy(*f->ret);
- *f->ret = H;
- d = checkdisplay(f->d);
- locked = lockdisplay(d);
- i = namedimage(d, string2c(f->name));
- if(locked)
- unlockdisplay(d);
- if(i == nil)
- return;
- di = allocdrawimage((DDisplay*)f->d, DRECT(i->r), i->chan, i, i->repl, 0);
- *f->ret = di;
- if(di == H){
- locked = lockdisplay(d);
- freeimage(i);
- if(locked)
- unlockdisplay(d);
- }else{
- di->iname = f->name;
- D2H(f->name)->ref++;
- }
- }
- void
- Display_readimage(void *fp)
- {
- Image *i;
- Display *disp;
- F_Display_readimage *f;
- Sys_FD *fd;
- int locked;
- f = fp;
- destroy(*f->ret);
- *f->ret = H;
- fd = f->fd;
- if(fd == H)
- return;
- disp = checkdisplay(f->d);
- i = readimage(disp, fd->fd, 1);
- if(i == nil)
- return;
- *f->ret = allocdrawimage((DDisplay*)f->d, DRECT(i->r), i->chan, i, 0, 0);
- if(*f->ret == H){
- locked = lockdisplay(disp);
- freeimage(i);
- if(locked)
- unlockdisplay(disp);
- }
- }
- void
- Display_writeimage(void *fp)
- {
- Image *i;
- F_Display_writeimage *f;
- Sys_FD *fd;
- f = fp;
- *f->ret = -1;
- fd = f->fd;
- if(fd == H)
- return;
- i = checkimage(f->i);
- if(checkdisplay(f->d) != i->display)
- return;
- *f->ret = writeimage(fd->fd, i, 1); /* TO DO: dolock? */
- }
- Draw_Screen*
- mkdrawscreen(Screen *s, Draw_Display *display)
- {
- Heap *h;
- DScreen *ds;
- Draw_Image *dimage, *dfill;
- dimage = mkdrawimage(s->image, H, display, nil);
- dfill = mkdrawimage(s->fill, H, display, nil);
- h = heap(TScreen);
- if(h == H)
- return nil;
- ds = H2D(DScreen*, h);
- ds->screen = s;
- ds->drawscreen.fill = dfill;
- D2H(dfill)->ref++;
- ds->drawscreen.image = dimage;
- D2H(dimage)->ref++;
- ds->drawscreen.display = dimage->display;
- D2H(dimage->display)->ref++;
- ds->drawscreen.id = s->id;
- ds->dref = s->display->limbo;
- ds->dref->ref++;
- return &ds->drawscreen;
- }
- static DScreen*
- allocdrawscreen(Draw_Image *dimage, Draw_Image *dfill, int public)
- {
- Heap *h;
- Screen *s;
- DScreen *ds;
- Image *image, *fill;
- image = ((DImage*)dimage)->image;
- fill = ((DImage*)dfill)->image;
- s = allocscreen(image, fill, public);
- if(s == 0)
- return nil;
- h = heap(TScreen);
- if(h == H)
- return nil;
- ds = H2D(DScreen*, h);
- ds->screen = s;
- ds->drawscreen.fill = dfill;
- D2H(dfill)->ref++;
- ds->drawscreen.image = dimage;
- D2H(dimage)->ref++;
- ds->drawscreen.display = dimage->display;
- D2H(dimage->display)->ref++;
- ds->drawscreen.id = s->id;
- ds->dref = image->display->limbo;
- ds->dref->ref++;
- return ds;
- }
- void
- Screen_allocate(void *fp)
- {
- F_Screen_allocate *f;
- DScreen *ds;
- Image *image;
- int locked;
- f = fp;
- destroy(*f->ret);
- *f->ret = H;
- image = checkimage(f->image);
- checkimage(f->fill);
- locked = lockdisplay(image->display);
- ds = allocdrawscreen(f->image, f->fill, f->public);
- if(ds != nil)
- *f->ret = &ds->drawscreen;
- if(locked)
- unlockdisplay(image->display);
- }
- void
- Display_publicscreen(void *fp)
- {
- F_Display_publicscreen *f;
- Heap *h;
- Screen *s;
- DScreen *ds;
- Display *disp;
- int locked;
- f = fp;
- destroy(*f->ret);
- *f->ret = H;
- disp = checkdisplay(f->d);
- locked = lockdisplay(disp);
- s = publicscreen(disp, f->id, disp->image->chan);
- if(locked)
- unlockdisplay(disp);
- if(s == nil)
- return;
- h = heap(TScreen);
- if(h == H)
- return;
- ds = H2D(DScreen*, h);
- ds->screen = s;
- ds->drawscreen.fill = H;
- ds->drawscreen.image =H;
- ds->drawscreen.id = s->id;
- ds->drawscreen.display = f->d;
- D2H(f->d)->ref++;
- ds->dref = disp->limbo;
- ds->dref->ref++;
- *f->ret = &ds->drawscreen;
- }
- void
- freedrawscreen(Heap *h, int swept)
- {
- DScreen *ds;
- Screen *s;
- Display *disp;
- int locked;
- ds = H2D(DScreen*, h);
- if(!swept) {
- destroy(ds->drawscreen.image);
- destroy(ds->drawscreen.fill);
- destroy(ds->drawscreen.display);
- }
- s = lookupscreen(&ds->drawscreen);
- if(s == nil){
- if(!swept)
- freeptrs(ds, TScreen);
- return;
- }
- disp = s->display;
- locked = lockdisplay(disp);
- freescreen(s);
- if(locked)
- unlockdisplay(disp);
- display_dec(ds->dref);
- /* screen header will be freed by caller */
- }
- void
- Font_build(void *fp)
- {
- F_Font_build *f;
- Font *font;
- DFont *dfont;
- Heap *h;
- char buf[128];
- char *name, *data;
- Subfont *df;
- Display *disp;
- int locked;
- f = fp;
- destroy(*f->ret);
- *f->ret = H;
- disp = checkdisplay(f->d);
- name = string2c(f->name);
- font = font_open(disp, name);
- if(font == nil) {
- if(strcmp(name, deffontname) == 0) {
- df = disp->defaultsubfont;
- sprint(buf, "%d %d\n0 %d\t%s\n",
- df->height, df->ascent, df->n-1, name);
- data = buf;
- }
- else
- if(f->desc == H)
- return;
- else
- data = string2c(f->desc);
- locked = lockdisplay(disp);
- font = buildfont(disp, data, name);
- if(locked)
- unlockdisplay(disp);
- if(font == nil)
- return;
- }
- h = heap(TFont);
- if(h == H)
- return;
- dfont = H2D(DFont*, h);
- dfont->font = font;
- dfont->drawfont.name = f->name;
- D2H(f->name)->ref++;
- dfont->drawfont.height = font->height;
- dfont->drawfont.ascent = font->ascent;
- dfont->drawfont.display = f->d;
- D2H(f->d)->ref++;
- dfont->dref = disp->limbo;
- dfont->dref->ref++;
- *f->ret = &dfont->drawfont;
- }
- Font*
- font_open(Display *display, char *name)
- {
- Cache *c;
- Font *font;
- int locked;
- c = cachelookup(fcache, display, name);
- if(c)
- font = c->u.f;
- else {
- locked = lockdisplay(display);
- font = openfont(display, name);
- if(locked)
- unlockdisplay(display);
- if(font == nil)
- return nil;
- c = cacheinstall(fcache, display, name, font, "font");
- }
- if(c)
- c->ref++;
- return font;
- }
- void
- font_close(Font *f)
- {
- Cache *c;
- Display *disp;
- int locked;
- disp = f->display;
- if(f->name == nil)
- return;
- /* fonts from Font_build() aren't always in fcache, but we still need to free them */
- c = cachelookup(fcache, disp, f->name);
- if(c != nil && f == c->u.f) {
- if(c->ref <= 0)
- return;
- if(c->ref-- != 1)
- return;
- cacheuninstall(fcache, disp, f->name, "font");
- }
- locked = lockdisplay(disp);
- freefont(f);
- if(locked)
- unlockdisplay(disp);
- }
- void
- freecachedsubfont(Subfont *sf)
- {
- Cache *c;
- Display *disp;
- disp = sf->bits->display;
- c = cachelookup(sfcache, disp, sf->name);
- if(c == nil){
- fprint(2, "subfont %s not cached\n", sf->name);
- return;
- }
- if(c->ref > 0)
- c->ref--;
- /* if ref is zero, we leave it around for later harvesting by freeallsubfonts */
- }
- void
- freeallsubfonts(Display *d)
- {
- int i;
- Cache *c, *prev, *o;
- Subfont *sf;
- int locked;
- if(cacheqlock == nil) /* may not have allocated anything yet */
- return;
- libqlock(cacheqlock);
- for(i=0; i<BIHASH; i++){
- c = sfcache[i];
- prev = 0;
- while(c != nil){
- if(c->ref==0 && (d==nil || c->display==d)){
- if(prev == 0)
- sfcache[i] = c->next;
- else
- prev->next = c->next;
- free(c->name);
- sf = c->u.sf;
- if(--sf->ref==0){
- free(sf->info);
- locked = lockdisplay(c->display);
- freeimage(sf->bits);
- if(locked)
- unlockdisplay(c->display);
- free(sf);
- }
- o = c;
- c = c->next;
- free(o);
- }else{
- prev = c;
- c = c->next;
- }
- }
- }
- libqunlock(cacheqlock);
- }
- void
- subfont_close(Subfont *sf)
- {
- freecachedsubfont(sf);
- }
- void
- freesubfont(Subfont *sf)
- {
- freecachedsubfont(sf);
- }
- void
- Font_open(void *fp)
- {
- Heap *h;
- Font *font;
- Display *disp;
- DFont *df;
- F_Font_open *f;
- f = fp;
- destroy(*f->ret);
- *f->ret = H;
- disp = checkdisplay(f->d);
- font = font_open(disp, string2c(f->name));
- if(font == 0)
- return;
- h = heap(TFont);
- if(h == H)
- return;
- df = H2D(DFont*, h);
- df->font = font;
- df->drawfont.name = f->name;
- D2H(f->name)->ref++;
- df->drawfont.height = font->height;
- df->drawfont.ascent = font->ascent;
- df->drawfont.display = f->d;
- D2H(f->d)->ref++;
- df->dref = disp->limbo;
- df->dref->ref++;
- *f->ret = &df->drawfont;
- }
- void
- Font_width(void *fp)
- {
- F_Font_width *f;
- Font *font;
- char *s;
- int locked;
- f = fp;
- s = string2c(f->str);
- if(f->f == H || s[0]=='\0')
- *f->ret = 0;
- else{
- font = checkfont(f->f);
- locked = lockdisplay(font->display);
- *f->ret = stringwidth(font, s);
- if(locked)
- unlockdisplay(font->display);
- }
- }
- void
- Font_bbox(void *fp)
- {
- F_Font_bbox *f;
- Draw_Rect *ret;
- /* place holder for the real thing */
- f = fp;
- ret = f->ret;
- ret->min.x = ret->min.y = 0;
- ret->max.x = ret->max.y = 0;
- }
- /*
- * BUG: would be nice if this cached the whole font.
- * Instead only the subfonts are cached and the fonts are
- * freed when released.
- */
- void
- freedrawfont(Heap*h, int swept)
- {
- Draw_Font *d;
- Font *f;
- d = H2D(Draw_Font*, h);
- f = lookupfont(d);
- if(!swept) {
- destroy(d->name);
- destroy(d->display);
- }
- font_close(f);
- display_dec(((DFont*)d)->dref);
- }
- void
- Chans_text(void *fp)
- {
- F_Chans_text *f;
- char buf[16];
- f = fp;
- destroy(*f->ret);
- *f->ret = H;
- if(chantostr(buf, f->c.desc) != nil)
- retstr(buf, f->ret);
- }
- void
- Chans_depth(void *fp)
- {
- F_Chans_depth *f;
- f = fp;
- *f->ret = chantodepth(f->c.desc);
- }
- void
- Chans_eq(void *fp)
- {
- F_Chans_eq *f;
- f = fp;
- *f->ret = f->c.desc == f->d.desc;
- }
- void
- Chans_mk(void *fp)
- {
- F_Chans_mk *f;
- f = fp;
- f->ret->desc = strtochan(string2c(f->s));
- }
- void
- Display_rgb(void *fp)
- {
- ulong c;
- Display *disp;
- F_Display_rgb *f;
- int locked;
- void *r;
- f = fp;
- r = *f->ret;
- *f->ret = H;
- destroy(r);
- disp = checkdisplay(f->d);
- c = ((f->r&255)<<24)|((f->g&255)<<16)|((f->b&255)<<8)|0xFF;
- locked = lockdisplay(disp);
- *f->ret = color((DDisplay*)f->d, c);
- if(locked)
- unlockdisplay(disp);
- }
- void
- Display_rgb2cmap(void *fp)
- {
- F_Display_rgb2cmap *f;
- f = fp;
- /* f->display is unused, but someday may have color map */
- *f->ret = rgb2cmap(f->r, f->g, f->b);
- }
- void
- Display_cmap2rgb(void *fp)
- {
- F_Display_cmap2rgb *f;
- ulong c;
- f = fp;
- /* f->display is unused, but someday may have color map */
- c = cmap2rgb(f->c);
- f->ret->t0 = (c>>16)&0xFF;
- f->ret->t1 = (c>>8)&0xFF;
- f->ret->t2 = (c>>0)&0xFF;
- }
- void
- Display_cmap2rgba(void *fp)
- {
- F_Display_cmap2rgba *f;
- f = fp;
- /* f->display is unused, but someday may have color map */
- *f->ret = cmap2rgba(f->c);
- }
- void
- Draw_setalpha(void *fp)
- {
- F_Draw_setalpha *f;
- f = fp;
- *f->ret = setalpha(f->c, f->a);
- }
- void
- Draw_icossin(void *fp)
- {
- F_Draw_icossin *f;
- int s, c;
- f = fp;
- icossin(f->deg, &s, &c);
- f->ret->t0 = s;
- f->ret->t1 = c;
- }
- void
- Draw_icossin2(void *fp)
- {
- F_Draw_icossin2 *f;
- int s, c;
- f = fp;
- icossin2(f->p.x, f->p.y, &s, &c);
- f->ret->t0 = s;
- f->ret->t1 = c;
- }
- void
- Draw_bytesperline(void *fp)
- {
- F_Draw_bytesperline *f;
- f = fp;
- *f->ret = bytesperline(IRECT(f->r), f->d);
- }
- Draw_Image*
- color(DDisplay *dd, ulong color)
- {
- int c;
- Draw_Rect r;
- r.min.x = 0;
- r.min.y = 0;
- r.max.x = 1;
- r.max.y = 1;
- c = (color&0xff) == 0xff ? RGB24: RGBA32;
- return allocdrawimage(dd, r, c, nil, 1, color);
- }
- Draw_Image*
- mkdrawimage(Image *i, Draw_Screen *screen, Draw_Display *display, void *ref)
- {
- Heap *h;
- DImage *di;
- h = heap(TImage);
- if(h == H)
- return H;
- di = H2D(DImage*, h);
- di->image = i;
- di->drawimage.screen = screen;
- if(screen != H)
- D2H(screen)->ref++;
- di->drawimage.display = display;
- if(display != H)
- D2H(display)->ref++;
- di->refreshptr = ref;
- R2R(di->drawimage.r, i->r);
- R2R(di->drawimage.clipr, i->clipr);
- di->drawimage.chans.desc = i->chan;
- di->drawimage.depth = i->depth;
- di->drawimage.repl = i->repl;
- di->flush = 1;
- di->dref = i->display->limbo;
- di->dref->ref++;
- return &di->drawimage;
- }
- void
- Screen_newwindow(void *fp)
- {
- F_Screen_newwindow *f;
- Image *i;
- Screen *s;
- Rectangle r;
- int locked;
- void *v;
- f = fp;
- s = checkscreen(f->screen);
- R2R(r, f->r);
- if(f->backing != Refnone && f->backing != Refbackup)
- f->backing = Refbackup;
- v = *f->ret;
- *f->ret = H;
- destroy(v);
- locked = lockdisplay(s->display);
- i = allocwindow(s, r, f->backing, f->color);
- if(locked)
- unlockdisplay(s->display);
- if(i == nil)
- return;
- *f->ret = mkdrawimage(i, f->screen, f->screen->display, 0);
- }
- static
- void
- screentopbot(Draw_Screen *screen, Array *array, void (*topbot)(Image **, int))
- {
- Screen *s;
- Draw_Image **di;
- Image **ip;
- int i, n, locked;
- s = checkscreen(screen);
- di = (Draw_Image**)array->data;
- ip = malloc(array->len * sizeof(Image*));
- if(ip == nil)
- return;
- n = 0;
- for(i=0; i<array->len; i++)
- if(di[i] != H){
- ip[n] = lookupimage(di[i]);
- if(ip[n]==nil || ip[n]->screen != s){
- free(ip);
- return;
- }
- n++;
- }
- if(n == 0){
- free(ip);
- return;
- }
- locked = lockdisplay(s->display);
- (*topbot)(ip, n);
- free(ip);
- flushimage(s->display, 1);
- if(locked)
- unlockdisplay(s->display);
- }
- void
- Screen_top(void *fp)
- {
- F_Screen_top *f;
- f = fp;
- screentopbot(f->screen, f->wins, topnwindows);
- }
- void
- Screen_bottom(void *fp)
- {
- F_Screen_top *f;
- f = fp;
- screentopbot(f->screen, f->wins, bottomnwindows);
- }
- void
- freedrawimage(Heap *h, int swept)
- {
- Image *i;
- int locked;
- Display *disp;
- Draw_Image *d;
- d = H2D(Draw_Image*, h);
- i = lookupimage(d);
- if(i == nil) {
- if(!swept)
- freeptrs(d, TImage);
- return;
- }
- disp = i->display;
- locked = lockdisplay(disp);
- freeimage(i);
- if(locked)
- unlockdisplay(disp);
- display_dec(((DImage*)d)->dref);
- /* image/layer header will be freed by caller */
- }
- void
- Image_top(void *fp)
- {
- F_Image_top *f;
- Image *i;
- int locked;
- f = fp;
- i = checkimage(f->win);
- locked = lockdisplay(i->display);
- topwindow(i);
- flushimage(i->display, 1);
- if(locked)
- unlockdisplay(i->display);
- }
- void
- Image_origin(void *fp)
- {
- F_Image_origin *f;
- Image *i;
- int locked;
- f = fp;
- i = checkimage(f->win);
- locked = lockdisplay(i->display);
- if(originwindow(i, IPOINT(f->log), IPOINT(f->scr)) < 0)
- *f->ret = -1;
- else{
- f->win->r = DRECT(i->r);
- f->win->clipr = DRECT(i->clipr);
- *f->ret = 1;
- }
- if(locked)
- unlockdisplay(i->display);
- }
- void
- Image_bottom(void *fp)
- {
- F_Image_top *f;
- Image *i;
- int locked;
- f = fp;
- i = checkimage(f->win);
- locked = lockdisplay(i->display);
- bottomwindow(i);
- flushimage(i->display, 1);
- if(locked)
- unlockdisplay(i->display);
- }
- Draw_Image*
- allocdrawimage(DDisplay *ddisplay, Draw_Rect r, ulong chan, Image *iimage, int repl, int color)
- {
- Heap *h;
- DImage *di;
- Rectangle rr;
- Image *image;
- image = iimage;
- if(iimage == nil){
- R2R(rr, r);
- image = allocimage(ddisplay->display, rr, chan, repl, color);
- if(image == nil)
- return H;
- }
- h = heap(TImage);
- if(h == H){
- if(iimage == nil)
- freeimage(image);
- return H;
- }
- di = H2D(DImage*, h);
- di->drawimage.r = r;
- R2R(di->drawimage.clipr, image->clipr);
- di->drawimage.chans.desc = chan;
- di->drawimage.depth = chantodepth(chan);
- di->drawimage.repl = repl;
- di->drawimage.display = (Draw_Display*)ddisplay;
- D2H(di->drawimage.display)->ref++;
- di->drawimage.screen = H;
- di->dref = ddisplay->display->limbo;
- di->dref->ref++;
- di->image = image;
- di->refreshptr = 0;
- di->flush = 1;
- return &di->drawimage;
- }
- /*
- * Entry points called from the draw library
- */
- Subfont*
- lookupsubfont(Display *d, char *name)
- {
- Cache *c;
- c = cachelookup(sfcache, d, name);
- if(c == nil)
- return nil;
- /*c->u.sf->ref++;*/ /* TO DO: need to revisit the reference counting */
- return c->u.sf;
- }
- void
- installsubfont(char *name, Subfont *subfont)
- {
- Cache *c;
- c = cacheinstall(sfcache, subfont->bits->display, name, subfont, "subfont");
- if(c)
- c->ref++;
- }
- /*
- * BUG version
- */
- char*
- subfontname(char *cfname, char *fname, int maxdepth)
- {
- char *t, *u, tmp1[256], tmp2[256];
- int i, fd;
- if(strcmp(cfname, deffontname) == 0)
- return strdup(cfname);
- t = cfname;
- if(t[0] != '/'){
- strcpy(tmp2, fname);
- u = utfrrune(tmp2, '/');
- if(u)
- u[0] = 0;
- else
- strcpy(tmp2, ".");
- snprint(tmp1, sizeof tmp1, "%s/%s", tmp2, t);
- t = tmp1;
- }
- if(maxdepth > 8)
- maxdepth = 8;
- for(i=3; i>=0; i--){
- if((1<<i) > maxdepth)
- continue;
- /* try i-bit grey */
- snprint(tmp2, sizeof tmp2, "%s.%d", t, i);
- fd = libopen(tmp2, OREAD);
- if(fd >= 0){
- libclose(fd);
- return strdup(tmp2);
- }
- }
- return strdup(t);
- }
- void
- refreshslave(Display *d)
- {
- int i, n, id;
- uchar buf[5*(5*4)], *p;
- Rectangle r;
- Image *im;
- int locked;
- for(;;){
- release();
- n = kchanio(d->refchan, buf, sizeof buf, OREAD);
- acquire();
- if(n < 0) /* probably caused by closedisplay() closing refchan */
- return; /* will fall off end of thread and close down */
- locked = lockdisplay(d);
- p = buf;
- for(i=0; i<n; i+=5*4,p+=5*4){
- id = BGLONG(p+0*4);
- r.min.x = BGLONG(p+1*4);
- r.min.y = BGLONG(p+2*4);
- r.max.x = BGLONG(p+3*4);
- r.max.y = BGLONG(p+4*4);
- for(im=d->windows; im; im=im->next)
- if(im->id == id)
- break;
- if(im && im->screen && im->reffn)
- (*im->reffn)(im, r, im->refptr);
- }
- flushimage(d, 1);
- if(locked)
- unlockdisplay(d);
- }
- }
- void
- startrefresh(Display *disp)
- {
- USED(disp);
- }
- static
- int
- doflush(Display *d)
- {
- int m, n;
- char err[ERRMAX];
- uchar *tp;
- n = d->bufp-d->buf;
- if(n <= 0)
- return 1;
- if(d->local == 0)
- release();
- if((m = kchanio(d->datachan, d->buf, n, OWRITE)) != n){
- if(d->local == 0)
- acquire();
- kgerrstr(err, sizeof err);
- if(_drawdebug || strcmp(err, "screen id in use") != 0 && strcmp(err, exImage) != 0){
- print("flushimage fail: (%d not %d) d=%lux: %s\nbuffer: ", m, n, (ulong)d, err);
- for(tp = d->buf; tp < d->bufp; tp++)
- print("%.2x ", (int)*tp);
- print("\n");
- }
- d->bufp = d->buf; /* might as well; chance of continuing */
- return -1;
- }
- d->bufp = d->buf;
- if(d->local == 0)
- acquire();
- return 1;
- }
- int
- flushimage(Display *d, int visible)
- {
- int ret;
- Refreshq *r;
- for(;;){
- if(visible)
- *d->bufp++ = 'v'; /* one byte always reserved for this */
- ret = doflush(d);
- if(d->refhead == nil)
- break;
- while(r = d->refhead){ /* assign = */
- d->refhead = r->next;
- if(d->refhead == nil)
- d->reftail = nil;
- r->reffn(nil, r->r, r->refptr);
- free(r);
- }
- }
- return ret;
- }
- /*
- * Turn off refresh for this window and remove any pending refresh events for it.
- */
- void
- delrefresh(Image *i)
- {
- Refreshq *r, *prev, *next;
- int locked;
- Display *d;
- void *refptr;
- d = i->display;
- /*
- * Any refresh function will do, because the data pointer is nil.
- * Can't use nil, though, because that turns backing store back on.
- */
- if(d->local)
- drawlsetrefresh(d->dataqid, i->id, memlnorefresh, nil);
- refptr = i->refptr;
- i->refptr = nil;
- if(d->refhead==nil || refptr==nil)
- return;
- locked = lockdisplay(d);
- prev = nil;
- for(r=d->refhead; r; r=next){
- next = r->next;
- if(r->refptr == refptr){
- if(prev)
- prev->next = next;
- else
- d->refhead = next;
- if(d->reftail == r)
- d->reftail = prev;
- free(r);
- }else
- prev = r;
- }
- if(locked)
- unlockdisplay(d);
- }
- void
- queuerefresh(Image *i, Rectangle r, Reffn reffn, void *refptr)
- {
- Display *d;
- Refreshq *rq;
- d = i->display;
- rq = malloc(sizeof(Refreshq));
- if(rq == nil)
- return;
- if(d->reftail)
- d->reftail->next = rq;
- else
- d->refhead = rq;
- d->reftail = rq;
- rq->reffn = reffn;
- rq->refptr = refptr;
- rq->r = r;
- }
- uchar*
- bufimage(Display *d, int n)
- {
- uchar *p;
- if(n<0 || n>Displaybufsize){
- kwerrstr("bad count in bufimage");
- return 0;
- }
- if(d->bufp+n > d->buf+Displaybufsize){
- if(d->local==0 && currun()!=libqlowner(d->qlock)) {
- print("bufimage: %lux %lux\n", (ulong)libqlowner(d->qlock), (ulong)currun());
- abort();
- }
- if(doflush(d) < 0)
- return 0;
- }
- p = d->bufp;
- d->bufp += n;
- /* return with buffer locked */
- return p;
- }
- void
- drawerror(Display *d, char *s)
- {
- USED(d);
- fprint(2, "draw: %s: %r\n", s);
- }
|