draw.c 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345
  1. #include <lib9.h>
  2. #include <kernel.h>
  3. #include "interp.h"
  4. #include "isa.h"
  5. #include "runt.h"
  6. #include "raise.h"
  7. #include "drawmod.h"
  8. #include "draw.h"
  9. #include "drawif.h"
  10. #include "memdraw.h"
  11. #include "memlayer.h"
  12. /*
  13. * When a Display is remote, it must be locked to synchronize the
  14. * outgoing message buffer with the refresh demon, which runs as a
  15. * different process. When it is local, the refresh demon does nothing
  16. * and it is sufficient to use the interpreter's own acquire/release protection
  17. * to lock the buffer.
  18. *
  19. * Most action to the buffer is caused by calls from Limbo, so locking at
  20. * the top before going into the library is good enough. However, the
  21. * garbage collector can call the free routines at other times, so they
  22. * need to protect themselves whether called through the Draw module
  23. * or not; hence the need for check against recursive locking in lockdisplay().
  24. * This also means that we needn't lock around calls to destroy if it's
  25. * extra work to do so.
  26. */
  27. typedef struct Cache Cache;
  28. typedef struct DRef DRef;
  29. typedef struct DDisplay DDisplay;
  30. typedef struct DImage DImage;
  31. typedef struct DScreen DScreen;
  32. typedef struct DFont DFont;
  33. struct Cache
  34. {
  35. int ref;
  36. char* name;
  37. Display*display;
  38. union{
  39. Subfont* sf;
  40. Font* f;
  41. void* ptr;
  42. }u;
  43. Cache* next;
  44. };
  45. /* not visible to Limbo; used only for internal reference counting */
  46. struct DRef
  47. {
  48. int ref;
  49. Display* display;
  50. };
  51. struct DDisplay
  52. {
  53. Draw_Display drawdisplay;
  54. Display* display;
  55. DRef* dref;
  56. };
  57. struct DImage
  58. {
  59. Draw_Image drawimage;
  60. Image* image;
  61. void* refreshptr;
  62. DRef* dref;
  63. int flush;
  64. };
  65. struct DScreen
  66. {
  67. Draw_Screen drawscreen;
  68. Screen* screen;
  69. DRef* dref;
  70. };
  71. struct DFont
  72. {
  73. Draw_Font drawfont;
  74. Font* font;
  75. DRef* dref;
  76. };
  77. Cache* sfcache[BIHASH];
  78. Cache* fcache[BIHASH];
  79. void* cacheqlock;
  80. static Cache *cachelookup(Cache**, Display*, char*);
  81. uchar fontmap[] = Draw_Font_map;
  82. uchar imagemap[] = Draw_Image_map;
  83. uchar screenmap[] = Draw_Screen_map;
  84. uchar displaymap[] = Draw_Display_map;
  85. Type* TFont;
  86. Type* TImage;
  87. Type* TScreen;
  88. Type* TDisplay;
  89. Draw_Image* allocdrawimage(DDisplay*, Draw_Rect, ulong, Image*, int, int);
  90. Draw_Image* color(DDisplay*, ulong);
  91. Draw_Screen *mkdrawscreen(Screen*, Draw_Display*);
  92. char deffontname[] = "*default*";
  93. void refreshslave(Display*);
  94. void subfont_close(Subfont*);
  95. void freeallsubfonts(Display*);
  96. void
  97. drawmodinit(void)
  98. {
  99. TFont = dtype(freedrawfont, sizeof(DFont), fontmap, sizeof(fontmap));
  100. TImage = dtype(freedrawimage, sizeof(DImage), imagemap, sizeof(imagemap));
  101. TScreen = dtype(freedrawscreen, sizeof(DScreen), screenmap, sizeof(screenmap));
  102. TDisplay = dtype(freedrawdisplay, sizeof(DDisplay), displaymap, sizeof(displaymap));
  103. builtinmod("$Draw", Drawmodtab, Drawmodlen);
  104. }
  105. static int
  106. drawhash(char *s)
  107. {
  108. int h;
  109. h = 0;
  110. while(*s){
  111. h += *s++;
  112. h <<= 1;
  113. if(h & (1<<8))
  114. h |= 1;
  115. }
  116. return (h&0xFFFF)%BIHASH;
  117. }
  118. static Cache*
  119. cachelookup(Cache *cache[], Display *d, char *name)
  120. {
  121. Cache *c;
  122. libqlock(cacheqlock);
  123. c = cache[drawhash(name)];
  124. while(c!=nil && (d!=c->display || strcmp(name, c->name)!=0))
  125. c = c->next;
  126. libqunlock(cacheqlock);
  127. return c;
  128. }
  129. Cache*
  130. cacheinstall(Cache **cache, Display *d, char *name, void *ptr, char *type)
  131. {
  132. Cache *c;
  133. int hash;
  134. USED(type);
  135. c = cachelookup(cache, d, name);
  136. if(c){
  137. /* print("%s %s already in cache\n", type, name); /**/
  138. return nil;
  139. }
  140. c = malloc(sizeof(Cache));
  141. if(c == nil)
  142. return nil;
  143. hash = drawhash(name);
  144. c->ref = 0; /* will be incremented by caller */
  145. c->display = d;
  146. c->name = strdup(name);
  147. c->u.ptr = ptr;
  148. libqlock(cacheqlock);
  149. c->next = cache[hash];
  150. cache[hash] = c;
  151. libqunlock(cacheqlock);
  152. return c;
  153. }
  154. void
  155. cacheuninstall(Cache **cache, Display *d, char *name, char *type)
  156. {
  157. Cache *c, *prev;
  158. int hash;
  159. hash = drawhash(name);
  160. libqlock(cacheqlock);
  161. c = cache[hash];
  162. if(c == nil){
  163. Notfound:
  164. libqunlock(cacheqlock);
  165. print("%s not in %s cache\n", name, type);
  166. return;
  167. }
  168. prev = nil;
  169. while(c!=nil && (d!=c->display || strcmp(name, c->name)!=0)){
  170. prev = c;
  171. c = c->next;
  172. }
  173. if(c == nil)
  174. goto Notfound;
  175. if(prev == 0)
  176. cache[hash] = c->next;
  177. else
  178. prev->next = c->next;
  179. libqunlock(cacheqlock);
  180. free(c->name);
  181. free(c);
  182. }
  183. Image*
  184. lookupimage(Draw_Image *di)
  185. {
  186. Display *disp;
  187. Image *i;
  188. int locked;
  189. if(di == H || D2H(di)->t != TImage)
  190. return nil;
  191. i = ((DImage*)di)->image;
  192. if(i == nil)
  193. return nil;
  194. if(!eqrect(IRECT(di->clipr), i->clipr) || di->repl!=i->repl){
  195. disp = i->display;
  196. locked = lockdisplay(disp);
  197. replclipr(i, di->repl, IRECT(di->clipr));
  198. if(locked)
  199. unlockdisplay(disp);
  200. }
  201. return i;
  202. }
  203. Screen*
  204. lookupscreen(Draw_Screen *ds)
  205. {
  206. if(ds == H || D2H(ds)->t != TScreen)
  207. return nil;
  208. return ((DScreen*)ds)->screen;
  209. }
  210. Font*
  211. lookupfont(Draw_Font *df)
  212. {
  213. if(df == H || D2H(df)->t != TFont)
  214. return nil;
  215. return ((DFont*)df)->font;
  216. }
  217. Display*
  218. lookupdisplay(Draw_Display *dd)
  219. {
  220. if(dd == H || D2H(dd)->t != TDisplay)
  221. return nil;
  222. return ((DDisplay*)dd)->display;
  223. }
  224. Image*
  225. checkimage(Draw_Image *di)
  226. {
  227. Image *i;
  228. if(di == H)
  229. error("nil Image");
  230. i = lookupimage(di);
  231. if(i == nil)
  232. error(exType);
  233. return i;
  234. }
  235. Screen*
  236. checkscreen(Draw_Screen *ds)
  237. {
  238. Screen *s;
  239. if(ds == H)
  240. error("nil Screen");
  241. s = lookupscreen(ds);
  242. if(s == nil)
  243. error(exType);
  244. return s;
  245. }
  246. Font*
  247. checkfont(Draw_Font *df)
  248. {
  249. Font *f;
  250. if(df == H)
  251. error("nil Font");
  252. f = lookupfont(df);
  253. if(f == nil)
  254. error(exType);
  255. return f;
  256. }
  257. Display*
  258. checkdisplay(Draw_Display *dd)
  259. {
  260. Display *d;
  261. if(dd == H)
  262. error("nil Display");
  263. d = lookupdisplay(dd);
  264. if(d == nil)
  265. error(exType);
  266. return d;
  267. }
  268. void
  269. Display_allocate(void *fp)
  270. {
  271. F_Display_allocate *f;
  272. char buf[128], *dev;
  273. Subfont *df;
  274. Display *display;
  275. DDisplay *dd;
  276. Heap *h;
  277. Draw_Rect r;
  278. DRef *dr;
  279. Cache *c;
  280. f = fp;
  281. destroy(*f->ret);
  282. *f->ret = H;
  283. if(cacheqlock == nil){
  284. cacheqlock = libqlalloc();
  285. if(cacheqlock == nil)
  286. return;
  287. }
  288. dev = string2c(f->dev);
  289. if(dev[0] == 0)
  290. dev = 0;
  291. display = initdisplay(dev, dev, nil); /* TO DO: win, error */
  292. if(display == 0)
  293. return;
  294. dr = malloc(sizeof(DRef));
  295. if(dr == nil)
  296. return;
  297. h = heap(TDisplay);
  298. if(h == H){
  299. closedisplay(display);
  300. return;
  301. }
  302. dd = H2D(DDisplay*, h);
  303. dd->display = display;
  304. *f->ret = &dd->drawdisplay;
  305. dd->dref = dr;
  306. display->limbo = dr;
  307. dr->display = display;
  308. dr->ref = 1;
  309. df = getdefont(display);
  310. if(df){
  311. display->defaultsubfont = df;
  312. sprint(buf, "%d %d\n0 %d\t%s\n", df->height, df->ascent,
  313. df->n-1, deffontname);
  314. display->defaultfont = buildfont(display, buf, deffontname);
  315. if(display->defaultfont){
  316. c = cacheinstall(fcache, display, deffontname, display->defaultfont, "font");
  317. if(c)
  318. c->ref++;
  319. /* else BUG? */
  320. }
  321. }
  322. R2R(r, display->image->r);
  323. dd->drawdisplay.image = allocdrawimage(dd, r, display->image->chan, display->image, 0, 0);
  324. R2R(r, display->white->r);
  325. dd->drawdisplay.black = allocdrawimage(dd, r, display->black->chan, display->black, 1, 0);
  326. dd->drawdisplay.white = allocdrawimage(dd, r, display->white->chan, display->white, 1, 0);
  327. dd->drawdisplay.opaque = allocdrawimage(dd, r, display->opaque->chan, display->opaque, 1, 0);
  328. dd->drawdisplay.transparent = allocdrawimage(dd, r, display->transparent->chan, display->transparent, 1, 0);
  329. /* don't call unlockdisplay because the qlock was left up by initdisplay */
  330. libqunlock(display->qlock);
  331. }
  332. void
  333. Display_getwindow(void *fp)
  334. {
  335. F_Display_getwindow *f;
  336. Display *disp;
  337. int locked;
  338. Image *image;
  339. Screen *screen;
  340. char *wn;
  341. void *r;
  342. f = fp;
  343. r = f->ret->t0;
  344. f->ret->t0 = H;
  345. destroy(r);
  346. r = f->ret->t1;
  347. f->ret->t1 = H;
  348. destroy(r);
  349. disp = checkdisplay(f->d);
  350. if(f->winname == H)
  351. wn = "/dev/winname";
  352. else
  353. wn = string2c(f->winname);
  354. if(f->image == H)
  355. image = nil;
  356. else
  357. image = checkimage(f->image);
  358. if(f->screen == H)
  359. screen = nil;
  360. else
  361. screen = checkscreen(f->screen);
  362. locked = lockdisplay(disp);
  363. if(gengetwindow(disp, wn, &image, &screen, f->backup) < 0){
  364. /* TO DO: eliminate f->image and f->screen's references to Image and Screen */
  365. goto Return;
  366. }
  367. if(screen != nil){
  368. if(f->screen != H){
  369. f->ret->t0 = f->screen;
  370. D2H(f->screen)->ref++;
  371. }else
  372. f->ret->t0 = mkdrawscreen(screen, f->d);
  373. }
  374. if(image != nil){
  375. if(f->image != H){
  376. f->ret->t1 = f->image;
  377. D2H(f->image)->ref++;
  378. }else
  379. f->ret->t1 = mkdrawimage(image, f->ret->t0, f->d, nil);
  380. }
  381. Return:
  382. if(locked)
  383. unlockdisplay(disp);
  384. }
  385. void
  386. Display_startrefresh(void *fp)
  387. {
  388. F_Display_startrefresh *f;
  389. Display *disp;
  390. f = fp;
  391. disp = checkdisplay(f->d);
  392. refreshslave(disp);
  393. }
  394. void
  395. display_dec(void *v)
  396. {
  397. DRef *dr;
  398. Display *d;
  399. int locked;
  400. dr = v;
  401. if(dr->ref-- != 1)
  402. return;
  403. d = dr->display;
  404. locked = lockdisplay(d);
  405. font_close(d->defaultfont);
  406. subfont_close(d->defaultsubfont);
  407. if(locked)
  408. unlockdisplay(d);
  409. freeallsubfonts(d);
  410. closedisplay(d);
  411. free(dr);
  412. }
  413. void
  414. freedrawdisplay(Heap *h, int swept)
  415. {
  416. DDisplay *dd;
  417. Display *d;
  418. dd = H2D(DDisplay*, h);
  419. if(!swept) {
  420. destroy(dd->drawdisplay.image);
  421. destroy(dd->drawdisplay.black);
  422. destroy(dd->drawdisplay.white);
  423. destroy(dd->drawdisplay.opaque);
  424. destroy(dd->drawdisplay.transparent);
  425. }
  426. /* we've now released dd->image etc.; make sure they're not freed again */
  427. d = dd->display;
  428. d->image = nil;
  429. d->white = nil;
  430. d->black = nil;
  431. d->opaque = nil;
  432. d->transparent = nil;
  433. display_dec(dd->dref);
  434. /* Draw_Display header will be freed by caller */
  435. }
  436. void
  437. Display_color(void *fp)
  438. {
  439. F_Display_color *f;
  440. Display *d;
  441. int locked;
  442. f = fp;
  443. destroy(*f->ret);
  444. *f->ret = H;
  445. d = checkdisplay(f->d);
  446. locked = lockdisplay(d);
  447. *f->ret = color((DDisplay*)f->d, f->color);
  448. if(locked)
  449. unlockdisplay(d);
  450. }
  451. void
  452. Image_flush(void *fp)
  453. {
  454. F_Image_flush *f;
  455. Image *d;
  456. DImage *di;
  457. int locked;
  458. f = fp;
  459. d = checkimage(f->win);
  460. di = (DImage*)f->win;
  461. switch(f->func){
  462. case 0: /* Draw->Flushoff */
  463. di->flush = 0;
  464. break;
  465. case 1: /* Draw->Flushon */
  466. di->flush = 1;
  467. /* fall through */
  468. case 2: /* Draw->Flushnow */
  469. locked = lockdisplay(d->display);
  470. if(d->id==0 || d->screen!=0)
  471. flushimage(d->display, 1);
  472. if(locked)
  473. unlockdisplay(d->display);
  474. break;
  475. default:
  476. error(exInval);
  477. }
  478. }
  479. void
  480. checkflush(Draw_Image *dst)
  481. {
  482. DImage *di;
  483. di = (DImage*)dst;
  484. if(di->flush && (di->image->id==0 || di->image->screen!=nil))
  485. flushimage(di->image->display, 1);
  486. }
  487. static void
  488. imagedraw(void *fp, int op)
  489. {
  490. F_Image_draw *f;
  491. Image *d, *s, *m;
  492. int locked;
  493. f = fp;
  494. d = checkimage(f->dst);
  495. if(f->src == H)
  496. s = d->display->black;
  497. else
  498. s = checkimage(f->src);
  499. if(f->matte == H)
  500. m = d->display->white; /* ones */
  501. else
  502. m = checkimage(f->matte);
  503. if(d->display!=s->display || d->display!=m->display)
  504. return;
  505. locked = lockdisplay(d->display);
  506. drawop(d, IRECT(f->r), s, m, IPOINT(f->p), op);
  507. checkflush(f->dst);
  508. if(locked)
  509. unlockdisplay(d->display);
  510. }
  511. void
  512. Image_draw(void *fp)
  513. {
  514. imagedraw(fp, SoverD);
  515. }
  516. void
  517. Image_drawop(void *fp)
  518. {
  519. F_Image_drawop *f;
  520. f = fp;
  521. imagedraw(fp, f->op);
  522. }
  523. static void
  524. imagegendraw(void *fp, int op)
  525. {
  526. F_Image_gendraw *f;
  527. Image *d, *s, *m;
  528. int locked;
  529. f = fp;
  530. d = checkimage(f->dst);
  531. if(f->src == H)
  532. s = d->display->black;
  533. else
  534. s = checkimage(f->src);
  535. if(f->matte == H)
  536. m = d->display->white; /* ones */
  537. else
  538. m = checkimage(f->matte);
  539. if(d->display!=s->display || d->display!=m->display)
  540. return;
  541. locked = lockdisplay(d->display);
  542. gendrawop(d, IRECT(f->r), s, IPOINT(f->p0), m, IPOINT(f->p1), op);
  543. checkflush(f->dst);
  544. if(locked)
  545. unlockdisplay(d->display);
  546. }
  547. void
  548. Image_gendraw(void *fp)
  549. {
  550. imagegendraw(fp, SoverD);
  551. }
  552. void
  553. Image_gendrawop(void *fp)
  554. {
  555. F_Image_gendrawop *f;
  556. f = fp;
  557. imagegendraw(fp, f->op);
  558. }
  559. static void
  560. drawline(void *fp, int op)
  561. {
  562. F_Image_line *f;
  563. Image *d, *s;
  564. int locked;
  565. f = fp;
  566. d = checkimage(f->dst);
  567. s = checkimage(f->src);
  568. if(d->display != s->display || f->radius < 0)
  569. return;
  570. locked = lockdisplay(d->display);
  571. lineop(d, IPOINT(f->p0), IPOINT(f->p1), f->end0, f->end1, f->radius, s, IPOINT(f->sp), op);
  572. checkflush(f->dst);
  573. if(locked)
  574. unlockdisplay(d->display);
  575. }
  576. void
  577. Image_line(void *fp)
  578. {
  579. drawline(fp, SoverD);
  580. }
  581. void
  582. Image_lineop(void *fp)
  583. {
  584. F_Image_lineop *f;
  585. f = fp;
  586. drawline(fp, f->op);
  587. }
  588. static void
  589. drawsplinepoly(void *fp, int smooth, int op)
  590. {
  591. F_Image_poly *f;
  592. Image *d, *s;
  593. int locked;
  594. f = fp;
  595. d = checkimage(f->dst);
  596. s = checkimage(f->src);
  597. if(d->display != s->display|| f->radius < 0)
  598. return;
  599. locked = lockdisplay(d->display);
  600. /* sleazy: we know that Draw_Points have same shape as Points */
  601. if(smooth)
  602. bezsplineop(d, (Point*)f->p->data, f->p->len,
  603. f->end0, f->end1, f->radius, s, IPOINT(f->sp), op);
  604. else
  605. polyop(d, (Point*)f->p->data, f->p->len, f->end0,
  606. f->end1, f->radius, s, IPOINT(f->sp), op);
  607. checkflush(f->dst);
  608. if(locked)
  609. unlockdisplay(d->display);
  610. }
  611. void
  612. Image_poly(void *fp)
  613. {
  614. drawsplinepoly(fp, 0, SoverD);
  615. }
  616. void
  617. Image_polyop(void *fp)
  618. {
  619. F_Image_polyop *f;
  620. f = fp;
  621. drawsplinepoly(fp, 0, f->op);
  622. }
  623. void
  624. Image_bezspline(void *fp)
  625. {
  626. drawsplinepoly(fp, 1, SoverD);
  627. }
  628. void
  629. Image_bezsplineop(void *fp)
  630. {
  631. F_Image_bezsplineop *f;
  632. f = fp;
  633. drawsplinepoly(fp, 1, f->op);
  634. }
  635. static void
  636. drawbezier(void *fp, int op)
  637. {
  638. F_Image_bezier *f;
  639. Image *d, *s;
  640. int locked;
  641. f = fp;
  642. d = checkimage(f->dst);
  643. s = checkimage(f->src);
  644. if(d->display != s->display || f->radius < 0)
  645. return;
  646. locked = lockdisplay(d->display);
  647. bezierop(d, IPOINT(f->a), IPOINT(f->b), IPOINT(f->c),
  648. IPOINT(f->d), f->end0, f->end1, f->radius, s, IPOINT(f->sp), op);
  649. checkflush(f->dst);
  650. if(locked)
  651. unlockdisplay(d->display);
  652. }
  653. void
  654. Image_bezier(void *fp)
  655. {
  656. drawbezier(fp, SoverD);
  657. }
  658. void
  659. Image_bezierop(void *fp)
  660. {
  661. F_Image_bezierop *f;
  662. f = fp;
  663. drawbezier(fp, f->op);
  664. }
  665. static void
  666. drawfillbezier(void *fp, int op)
  667. {
  668. F_Image_fillbezier *f;
  669. Image *d, *s;
  670. int locked;
  671. f = fp;
  672. d = checkimage(f->dst);
  673. s = checkimage(f->src);
  674. if(d->display != s->display)
  675. return;
  676. locked = lockdisplay(d->display);
  677. fillbezierop(d, IPOINT(f->a), IPOINT(f->b), IPOINT(f->c),
  678. IPOINT(f->d), f->wind, s, IPOINT(f->sp), op);
  679. checkflush(f->dst);
  680. if(locked)
  681. unlockdisplay(d->display);
  682. }
  683. void
  684. Image_fillbezier(void *fp)
  685. {
  686. drawfillbezier(fp, SoverD);
  687. }
  688. void
  689. Image_fillbezierop(void *fp)
  690. {
  691. F_Image_fillbezierop *f;
  692. f = fp;
  693. drawfillbezier(fp, f->op);
  694. }
  695. static void
  696. drawfillsplinepoly(void *fp, int smooth, int op)
  697. {
  698. F_Image_fillpoly *f;
  699. Image *d, *s;
  700. int locked;
  701. f = fp;
  702. d = checkimage(f->dst);
  703. s = checkimage(f->src);
  704. if(d->display != s->display)
  705. return;
  706. locked = lockdisplay(d->display);
  707. /* sleazy: we know that Draw_Points have same shape as Points */
  708. if(smooth)
  709. fillbezsplineop(d, (Point*)f->p->data, f->p->len,
  710. f->wind, s, IPOINT(f->sp), op);
  711. else
  712. fillpolyop(d, (Point*)f->p->data, f->p->len,
  713. f->wind, s, IPOINT(f->sp), op);
  714. checkflush(f->dst);
  715. if(locked)
  716. unlockdisplay(d->display);
  717. }
  718. void
  719. Image_fillpoly(void *fp)
  720. {
  721. drawfillsplinepoly(fp, 0, SoverD);
  722. }
  723. void
  724. Image_fillpolyop(void *fp)
  725. {
  726. F_Image_fillpolyop *f;
  727. f = fp;
  728. drawfillsplinepoly(fp, 0, f->op);
  729. }
  730. void
  731. Image_fillbezspline(void *fp)
  732. {
  733. drawfillsplinepoly(fp, 1, SoverD);
  734. }
  735. void
  736. Image_fillbezsplineop(void *fp)
  737. {
  738. F_Image_fillbezsplineop *f;
  739. f = fp;
  740. drawfillsplinepoly(fp, 1, f->op);
  741. }
  742. static void
  743. drawarcellipse(void *fp, int isarc, int alpha, int phi, int op)
  744. {
  745. F_Image_arc *f;
  746. Image *d, *s;
  747. int locked;
  748. f = fp;
  749. d = checkimage(f->dst);
  750. s = checkimage(f->src);
  751. if(d->display != s->display || f->thick < 0 || f->a<0 || f->b<0)
  752. return;
  753. locked = lockdisplay(d->display);
  754. if(isarc)
  755. arcop(d, IPOINT(f->c), f->a, f->b, f->thick, s,
  756. IPOINT(f->sp), alpha, phi, op);
  757. else
  758. ellipseop(d, IPOINT(f->c), f->a, f->b, f->thick, s,
  759. IPOINT(f->sp), op);
  760. checkflush(f->dst);
  761. if(locked)
  762. unlockdisplay(d->display);
  763. }
  764. void
  765. Image_ellipse(void *fp)
  766. {
  767. drawarcellipse(fp, 0, 0, 0, SoverD);
  768. }
  769. void
  770. Image_ellipseop(void *fp)
  771. {
  772. F_Image_ellipseop *f;
  773. f = fp;
  774. drawarcellipse(fp, 0, 0, 0, f->op);
  775. }
  776. void
  777. Image_arc(void *fp)
  778. {
  779. F_Image_arc *f;
  780. f = fp;
  781. drawarcellipse(fp, 1, f->alpha, f->phi, SoverD);
  782. }
  783. void
  784. Image_arcop(void *fp)
  785. {
  786. F_Image_arcop *f;
  787. f = fp;
  788. drawarcellipse(fp, 1, f->alpha, f->phi, f->op);
  789. }
  790. static void
  791. drawfillarcellipse(void *fp, int isarc, int alpha, int phi, int op)
  792. {
  793. F_Image_fillarc *f;
  794. Image *d, *s;
  795. int locked;
  796. f = fp;
  797. d = checkimage(f->dst);
  798. s = checkimage(f->src);
  799. if(d->display != s->display || f->a<0 || f->b<0)
  800. return;
  801. locked = lockdisplay(d->display);
  802. if(isarc)
  803. fillarcop(d, IPOINT(f->c), f->a, f->b, s, IPOINT(f->sp), alpha, phi, op);
  804. else
  805. fillellipseop(d, IPOINT(f->c), f->a, f->b, s, IPOINT(f->sp), op);
  806. checkflush(f->dst);
  807. if(locked)
  808. unlockdisplay(d->display);
  809. }
  810. void
  811. Image_fillellipse(void *fp)
  812. {
  813. drawfillarcellipse(fp, 0, 0, 0, SoverD);
  814. }
  815. void
  816. Image_fillellipseop(void *fp)
  817. {
  818. F_Image_fillellipseop *f;
  819. f = fp;
  820. drawfillarcellipse(fp, 0, 0, 0, f->op);
  821. }
  822. void
  823. Image_fillarc(void *fp)
  824. {
  825. F_Image_fillarc *f;
  826. f = fp;
  827. drawfillarcellipse(fp, 1, f->alpha, f->phi, SoverD);
  828. }
  829. void
  830. Image_fillarcop(void *fp)
  831. {
  832. F_Image_fillarcop *f;
  833. f = fp;
  834. drawfillarcellipse(fp, 1, f->alpha, f->phi, f->op);
  835. }
  836. static void
  837. drawtext(void *fp, int op)
  838. {
  839. F_Image_text *f;
  840. Font *font;
  841. Point pt;
  842. Image *s, *d;
  843. String *str;
  844. int locked;
  845. f = fp;
  846. if(f->dst == H || f->src == H)
  847. goto Return;
  848. if(f->font == H || f->str == H)
  849. goto Return;
  850. str = f->str;
  851. d = checkimage(f->dst);
  852. s = checkimage(f->src);
  853. font = checkfont(f->font);
  854. if(d->display!=s->display || d->display!=font->display)
  855. return;
  856. locked = lockdisplay(d->display);
  857. if(str->len >= 0)
  858. pt = stringnop(d, IPOINT(f->p), s, IPOINT(f->sp), font, str->Sascii, str->len, op);
  859. else
  860. pt = runestringnop(d, IPOINT(f->p), s, IPOINT(f->sp), font, str->Srune, -str->len, op);
  861. checkflush(f->dst);
  862. if(locked)
  863. unlockdisplay(d->display);
  864. Return:
  865. P2P(*f->ret, pt);
  866. }
  867. void
  868. Image_text(void *fp)
  869. {
  870. drawtext(fp, SoverD);
  871. }
  872. void
  873. Image_textop(void *fp)
  874. {
  875. F_Image_textop *f;
  876. f = fp;
  877. drawtext(fp, f->op);
  878. }
  879. static void
  880. drawtextbg(void *fp, int op)
  881. {
  882. F_Image_textbg *f;
  883. Font *font;
  884. Point pt;
  885. Image *s, *d, *bg;
  886. String *str;
  887. int locked;
  888. f = fp;
  889. if(f->dst == H || f->src == H)
  890. goto Return;
  891. if(f->font == H || f->str == H)
  892. goto Return;
  893. str = f->str;
  894. d = checkimage(f->dst);
  895. s = checkimage(f->src);
  896. bg = checkimage(f->bg);
  897. font = checkfont(f->font);
  898. if(d->display!=s->display || d->display!=font->display)
  899. return;
  900. locked = lockdisplay(d->display);
  901. if(str->len >= 0)
  902. pt = stringnbgop(d, IPOINT(f->p), s, IPOINT(f->sp), font, str->Sascii, str->len, bg, IPOINT(f->bgp), op);
  903. else
  904. pt = runestringnbgop(d, IPOINT(f->p), s, IPOINT(f->sp), font, str->Srune, -str->len, bg, IPOINT(f->bgp), op);
  905. checkflush(f->dst);
  906. if(locked)
  907. unlockdisplay(d->display);
  908. Return:
  909. P2P(*f->ret, pt);
  910. }
  911. void
  912. Image_textbg(void *fp)
  913. {
  914. drawtextbg(fp, SoverD);
  915. }
  916. void
  917. Image_textbgop(void *fp)
  918. {
  919. F_Image_textbgop *f;
  920. f = fp;
  921. drawtextbg(fp, f->op);
  922. }
  923. static void
  924. drawborder(void *fp, int op)
  925. {
  926. F_Image_border *f;
  927. Image *d, *s;
  928. int locked;
  929. f = fp;
  930. d = checkimage(f->dst);
  931. s = checkimage(f->src);
  932. if(d->display != s->display)
  933. return;
  934. locked = lockdisplay(d->display);
  935. borderop(d, IRECT(f->r), f->i, s, IPOINT(f->sp), op);
  936. checkflush(f->dst);
  937. if(locked)
  938. unlockdisplay(d->display);
  939. }
  940. void
  941. Image_border(void *fp)
  942. {
  943. drawborder(fp, SoverD);
  944. }
  945. void
  946. Display_newimage(void *fp)
  947. {
  948. F_Display_newimage *f;
  949. Display *d;
  950. int locked;
  951. f = fp;
  952. d = checkdisplay(f->d);
  953. destroy(*f->ret);
  954. *f->ret = H;
  955. locked = lockdisplay(d);
  956. *f->ret = allocdrawimage((DDisplay*)f->d, f->r, f->chans.desc,
  957. nil, f->repl, f->color);
  958. if(locked)
  959. unlockdisplay(d);
  960. }
  961. void
  962. Display_colormix(void *fp)
  963. {
  964. F_Display_colormix *f;
  965. Display *disp;
  966. Image *i;
  967. int locked;
  968. f = fp;
  969. destroy(*f->ret);
  970. *f->ret = H;
  971. disp = checkdisplay(f->d);
  972. locked = lockdisplay(disp);
  973. i = allocimagemix(disp, f->c1, f->c2);
  974. if(locked)
  975. unlockdisplay(disp);
  976. *f->ret = mkdrawimage(i, H, f->d, nil);
  977. }
  978. void
  979. Image_readpixels(void *fp)
  980. {
  981. F_Image_readpixels *f;
  982. Rectangle r;
  983. Image *i;
  984. int locked;
  985. f = fp;
  986. R2R(r, f->r);
  987. i = checkimage(f->src);
  988. locked = lockdisplay(i->display);
  989. *f->ret = unloadimage(i, r, f->data->data, f->data->len);
  990. if(locked)
  991. unlockdisplay(i->display);
  992. }
  993. void
  994. Image_writepixels(void *fp)
  995. {
  996. Rectangle r;
  997. F_Image_writepixels *f;
  998. Image *i;
  999. int locked;
  1000. f = fp;
  1001. R2R(r, f->r);
  1002. i = checkimage(f->dst);
  1003. locked = lockdisplay(i->display);
  1004. *f->ret = loadimage(i, r, f->data->data, f->data->len);
  1005. checkflush(f->dst);
  1006. if(locked)
  1007. unlockdisplay(i->display);
  1008. }
  1009. void
  1010. Image_arrow(void *fp)
  1011. {
  1012. F_Image_arrow *f;
  1013. f = fp;
  1014. *f->ret = ARROW(f->a, f->b, f->c);
  1015. }
  1016. void
  1017. Image_name(void *fp)
  1018. {
  1019. F_Image_name *f;
  1020. Image *i;
  1021. int locked, ok;
  1022. char *name;
  1023. f = fp;
  1024. *f->ret = -1;
  1025. i = checkimage(f->src);
  1026. name = string2c(f->name);
  1027. locked = lockdisplay(i->display);
  1028. *f->ret = ok = nameimage(i, name, f->in);
  1029. if(locked)
  1030. unlockdisplay(i->display);
  1031. if(ok){
  1032. destroy(f->src->iname);
  1033. if(f->in){
  1034. f->src->iname = f->name;
  1035. D2H(f->name)->ref++;
  1036. }else
  1037. f->src->iname = H;
  1038. }
  1039. }
  1040. Image*
  1041. display_open(Display *disp, char *name)
  1042. {
  1043. Image *i;
  1044. int fd;
  1045. fd = libopen(name, OREAD);
  1046. if(fd < 0)
  1047. return nil;
  1048. i = readimage(disp, fd, 1);
  1049. libclose(fd);
  1050. return i;
  1051. }
  1052. void
  1053. Display_open(void *fp)
  1054. {
  1055. Image *i;
  1056. Display *disp;
  1057. F_Display_open *f;
  1058. f = fp;
  1059. destroy(*f->ret);
  1060. *f->ret = H;
  1061. disp = lookupdisplay(f->d);
  1062. if(disp == nil)
  1063. return;
  1064. i = display_open(disp, string2c(f->name));
  1065. if(i == nil)
  1066. return;
  1067. *f->ret = allocdrawimage((DDisplay*)f->d, DRECT(i->r), i->chan, i, 0, 0);
  1068. }
  1069. void
  1070. Display_namedimage(void *fp)
  1071. {
  1072. F_Display_namedimage *f;
  1073. Display *d;
  1074. Image *i;
  1075. Draw_Image *di;
  1076. int locked;
  1077. f = fp;
  1078. destroy(*f->ret);
  1079. *f->ret = H;
  1080. d = checkdisplay(f->d);
  1081. locked = lockdisplay(d);
  1082. i = namedimage(d, string2c(f->name));
  1083. if(locked)
  1084. unlockdisplay(d);
  1085. if(i == nil)
  1086. return;
  1087. di = allocdrawimage((DDisplay*)f->d, DRECT(i->r), i->chan, i, i->repl, 0);
  1088. *f->ret = di;
  1089. if(di == H){
  1090. locked = lockdisplay(d);
  1091. freeimage(i);
  1092. if(locked)
  1093. unlockdisplay(d);
  1094. }else{
  1095. di->iname = f->name;
  1096. D2H(f->name)->ref++;
  1097. }
  1098. }
  1099. void
  1100. Display_readimage(void *fp)
  1101. {
  1102. Image *i;
  1103. Display *disp;
  1104. F_Display_readimage *f;
  1105. Sys_FD *fd;
  1106. int locked;
  1107. f = fp;
  1108. destroy(*f->ret);
  1109. *f->ret = H;
  1110. fd = f->fd;
  1111. if(fd == H)
  1112. return;
  1113. disp = checkdisplay(f->d);
  1114. i = readimage(disp, fd->fd, 1);
  1115. if(i == nil)
  1116. return;
  1117. *f->ret = allocdrawimage((DDisplay*)f->d, DRECT(i->r), i->chan, i, 0, 0);
  1118. if(*f->ret == H){
  1119. locked = lockdisplay(disp);
  1120. freeimage(i);
  1121. if(locked)
  1122. unlockdisplay(disp);
  1123. }
  1124. }
  1125. void
  1126. Display_writeimage(void *fp)
  1127. {
  1128. Image *i;
  1129. F_Display_writeimage *f;
  1130. Sys_FD *fd;
  1131. f = fp;
  1132. *f->ret = -1;
  1133. fd = f->fd;
  1134. if(fd == H)
  1135. return;
  1136. i = checkimage(f->i);
  1137. if(checkdisplay(f->d) != i->display)
  1138. return;
  1139. *f->ret = writeimage(fd->fd, i, 1); /* TO DO: dolock? */
  1140. }
  1141. Draw_Screen*
  1142. mkdrawscreen(Screen *s, Draw_Display *display)
  1143. {
  1144. Heap *h;
  1145. DScreen *ds;
  1146. Draw_Image *dimage, *dfill;
  1147. dimage = mkdrawimage(s->image, H, display, nil);
  1148. dfill = mkdrawimage(s->fill, H, display, nil);
  1149. h = heap(TScreen);
  1150. if(h == H)
  1151. return nil;
  1152. ds = H2D(DScreen*, h);
  1153. ds->screen = s;
  1154. ds->drawscreen.fill = dfill;
  1155. D2H(dfill)->ref++;
  1156. ds->drawscreen.image = dimage;
  1157. D2H(dimage)->ref++;
  1158. ds->drawscreen.display = dimage->display;
  1159. D2H(dimage->display)->ref++;
  1160. ds->drawscreen.id = s->id;
  1161. ds->dref = s->display->limbo;
  1162. ds->dref->ref++;
  1163. return &ds->drawscreen;
  1164. }
  1165. static DScreen*
  1166. allocdrawscreen(Draw_Image *dimage, Draw_Image *dfill, int public)
  1167. {
  1168. Heap *h;
  1169. Screen *s;
  1170. DScreen *ds;
  1171. Image *image, *fill;
  1172. image = ((DImage*)dimage)->image;
  1173. fill = ((DImage*)dfill)->image;
  1174. s = allocscreen(image, fill, public);
  1175. if(s == 0)
  1176. return nil;
  1177. h = heap(TScreen);
  1178. if(h == H)
  1179. return nil;
  1180. ds = H2D(DScreen*, h);
  1181. ds->screen = s;
  1182. ds->drawscreen.fill = dfill;
  1183. D2H(dfill)->ref++;
  1184. ds->drawscreen.image = dimage;
  1185. D2H(dimage)->ref++;
  1186. ds->drawscreen.display = dimage->display;
  1187. D2H(dimage->display)->ref++;
  1188. ds->drawscreen.id = s->id;
  1189. ds->dref = image->display->limbo;
  1190. ds->dref->ref++;
  1191. return ds;
  1192. }
  1193. void
  1194. Screen_allocate(void *fp)
  1195. {
  1196. F_Screen_allocate *f;
  1197. DScreen *ds;
  1198. Image *image;
  1199. int locked;
  1200. f = fp;
  1201. destroy(*f->ret);
  1202. *f->ret = H;
  1203. image = checkimage(f->image);
  1204. checkimage(f->fill);
  1205. locked = lockdisplay(image->display);
  1206. ds = allocdrawscreen(f->image, f->fill, f->public);
  1207. if(ds != nil)
  1208. *f->ret = &ds->drawscreen;
  1209. if(locked)
  1210. unlockdisplay(image->display);
  1211. }
  1212. void
  1213. Display_publicscreen(void *fp)
  1214. {
  1215. F_Display_publicscreen *f;
  1216. Heap *h;
  1217. Screen *s;
  1218. DScreen *ds;
  1219. Display *disp;
  1220. int locked;
  1221. f = fp;
  1222. destroy(*f->ret);
  1223. *f->ret = H;
  1224. disp = checkdisplay(f->d);
  1225. locked = lockdisplay(disp);
  1226. s = publicscreen(disp, f->id, disp->image->chan);
  1227. if(locked)
  1228. unlockdisplay(disp);
  1229. if(s == nil)
  1230. return;
  1231. h = heap(TScreen);
  1232. if(h == H)
  1233. return;
  1234. ds = H2D(DScreen*, h);
  1235. ds->screen = s;
  1236. ds->drawscreen.fill = H;
  1237. ds->drawscreen.image =H;
  1238. ds->drawscreen.id = s->id;
  1239. ds->drawscreen.display = f->d;
  1240. D2H(f->d)->ref++;
  1241. ds->dref = disp->limbo;
  1242. ds->dref->ref++;
  1243. *f->ret = &ds->drawscreen;
  1244. }
  1245. void
  1246. freedrawscreen(Heap *h, int swept)
  1247. {
  1248. DScreen *ds;
  1249. Screen *s;
  1250. Display *disp;
  1251. int locked;
  1252. ds = H2D(DScreen*, h);
  1253. if(!swept) {
  1254. destroy(ds->drawscreen.image);
  1255. destroy(ds->drawscreen.fill);
  1256. destroy(ds->drawscreen.display);
  1257. }
  1258. s = lookupscreen(&ds->drawscreen);
  1259. if(s == nil){
  1260. if(!swept)
  1261. freeptrs(ds, TScreen);
  1262. return;
  1263. }
  1264. disp = s->display;
  1265. locked = lockdisplay(disp);
  1266. freescreen(s);
  1267. if(locked)
  1268. unlockdisplay(disp);
  1269. display_dec(ds->dref);
  1270. /* screen header will be freed by caller */
  1271. }
  1272. void
  1273. Font_build(void *fp)
  1274. {
  1275. F_Font_build *f;
  1276. Font *font;
  1277. DFont *dfont;
  1278. Heap *h;
  1279. char buf[128];
  1280. char *name, *data;
  1281. Subfont *df;
  1282. Display *disp;
  1283. int locked;
  1284. f = fp;
  1285. destroy(*f->ret);
  1286. *f->ret = H;
  1287. disp = checkdisplay(f->d);
  1288. name = string2c(f->name);
  1289. font = font_open(disp, name);
  1290. if(font == nil) {
  1291. if(strcmp(name, deffontname) == 0) {
  1292. df = disp->defaultsubfont;
  1293. sprint(buf, "%d %d\n0 %d\t%s\n",
  1294. df->height, df->ascent, df->n-1, name);
  1295. data = buf;
  1296. }
  1297. else
  1298. if(f->desc == H)
  1299. return;
  1300. else
  1301. data = string2c(f->desc);
  1302. locked = lockdisplay(disp);
  1303. font = buildfont(disp, data, name);
  1304. if(locked)
  1305. unlockdisplay(disp);
  1306. if(font == nil)
  1307. return;
  1308. }
  1309. h = heap(TFont);
  1310. if(h == H)
  1311. return;
  1312. dfont = H2D(DFont*, h);
  1313. dfont->font = font;
  1314. dfont->drawfont.name = f->name;
  1315. D2H(f->name)->ref++;
  1316. dfont->drawfont.height = font->height;
  1317. dfont->drawfont.ascent = font->ascent;
  1318. dfont->drawfont.display = f->d;
  1319. D2H(f->d)->ref++;
  1320. dfont->dref = disp->limbo;
  1321. dfont->dref->ref++;
  1322. *f->ret = &dfont->drawfont;
  1323. }
  1324. Font*
  1325. font_open(Display *display, char *name)
  1326. {
  1327. Cache *c;
  1328. Font *font;
  1329. int locked;
  1330. c = cachelookup(fcache, display, name);
  1331. if(c)
  1332. font = c->u.f;
  1333. else {
  1334. locked = lockdisplay(display);
  1335. font = openfont(display, name);
  1336. if(locked)
  1337. unlockdisplay(display);
  1338. if(font == nil)
  1339. return nil;
  1340. c = cacheinstall(fcache, display, name, font, "font");
  1341. }
  1342. if(c)
  1343. c->ref++;
  1344. return font;
  1345. }
  1346. void
  1347. font_close(Font *f)
  1348. {
  1349. Cache *c;
  1350. Display *disp;
  1351. int locked;
  1352. disp = f->display;
  1353. if(f->name == nil)
  1354. return;
  1355. /* fonts from Font_build() aren't always in fcache, but we still need to free them */
  1356. c = cachelookup(fcache, disp, f->name);
  1357. if(c != nil && f == c->u.f) {
  1358. if(c->ref <= 0)
  1359. return;
  1360. if(c->ref-- != 1)
  1361. return;
  1362. cacheuninstall(fcache, disp, f->name, "font");
  1363. }
  1364. locked = lockdisplay(disp);
  1365. freefont(f);
  1366. if(locked)
  1367. unlockdisplay(disp);
  1368. }
  1369. void
  1370. freecachedsubfont(Subfont *sf)
  1371. {
  1372. Cache *c;
  1373. Display *disp;
  1374. disp = sf->bits->display;
  1375. c = cachelookup(sfcache, disp, sf->name);
  1376. if(c == nil){
  1377. fprint(2, "subfont %s not cached\n", sf->name);
  1378. return;
  1379. }
  1380. if(c->ref > 0)
  1381. c->ref--;
  1382. /* if ref is zero, we leave it around for later harvesting by freeallsubfonts */
  1383. }
  1384. void
  1385. freeallsubfonts(Display *d)
  1386. {
  1387. int i;
  1388. Cache *c, *prev, *o;
  1389. Subfont *sf;
  1390. int locked;
  1391. if(cacheqlock == nil) /* may not have allocated anything yet */
  1392. return;
  1393. libqlock(cacheqlock);
  1394. for(i=0; i<BIHASH; i++){
  1395. c = sfcache[i];
  1396. prev = 0;
  1397. while(c != nil){
  1398. if(c->ref==0 && (d==nil || c->display==d)){
  1399. if(prev == 0)
  1400. sfcache[i] = c->next;
  1401. else
  1402. prev->next = c->next;
  1403. free(c->name);
  1404. sf = c->u.sf;
  1405. if(--sf->ref==0){
  1406. free(sf->info);
  1407. locked = lockdisplay(c->display);
  1408. freeimage(sf->bits);
  1409. if(locked)
  1410. unlockdisplay(c->display);
  1411. free(sf);
  1412. }
  1413. o = c;
  1414. c = c->next;
  1415. free(o);
  1416. }else{
  1417. prev = c;
  1418. c = c->next;
  1419. }
  1420. }
  1421. }
  1422. libqunlock(cacheqlock);
  1423. }
  1424. void
  1425. subfont_close(Subfont *sf)
  1426. {
  1427. freecachedsubfont(sf);
  1428. }
  1429. void
  1430. freesubfont(Subfont *sf)
  1431. {
  1432. freecachedsubfont(sf);
  1433. }
  1434. void
  1435. Font_open(void *fp)
  1436. {
  1437. Heap *h;
  1438. Font *font;
  1439. Display *disp;
  1440. DFont *df;
  1441. F_Font_open *f;
  1442. f = fp;
  1443. destroy(*f->ret);
  1444. *f->ret = H;
  1445. disp = checkdisplay(f->d);
  1446. font = font_open(disp, string2c(f->name));
  1447. if(font == 0)
  1448. return;
  1449. h = heap(TFont);
  1450. if(h == H)
  1451. return;
  1452. df = H2D(DFont*, h);
  1453. df->font = font;
  1454. df->drawfont.name = f->name;
  1455. D2H(f->name)->ref++;
  1456. df->drawfont.height = font->height;
  1457. df->drawfont.ascent = font->ascent;
  1458. df->drawfont.display = f->d;
  1459. D2H(f->d)->ref++;
  1460. df->dref = disp->limbo;
  1461. df->dref->ref++;
  1462. *f->ret = &df->drawfont;
  1463. }
  1464. void
  1465. Font_width(void *fp)
  1466. {
  1467. F_Font_width *f;
  1468. Font *font;
  1469. char *s;
  1470. int locked;
  1471. f = fp;
  1472. s = string2c(f->str);
  1473. if(f->f == H || s[0]=='\0')
  1474. *f->ret = 0;
  1475. else{
  1476. font = checkfont(f->f);
  1477. locked = lockdisplay(font->display);
  1478. *f->ret = stringwidth(font, s);
  1479. if(locked)
  1480. unlockdisplay(font->display);
  1481. }
  1482. }
  1483. void
  1484. Font_bbox(void *fp)
  1485. {
  1486. F_Font_bbox *f;
  1487. Draw_Rect *ret;
  1488. /* place holder for the real thing */
  1489. f = fp;
  1490. ret = f->ret;
  1491. ret->min.x = ret->min.y = 0;
  1492. ret->max.x = ret->max.y = 0;
  1493. }
  1494. /*
  1495. * BUG: would be nice if this cached the whole font.
  1496. * Instead only the subfonts are cached and the fonts are
  1497. * freed when released.
  1498. */
  1499. void
  1500. freedrawfont(Heap*h, int swept)
  1501. {
  1502. Draw_Font *d;
  1503. Font *f;
  1504. d = H2D(Draw_Font*, h);
  1505. f = lookupfont(d);
  1506. if(!swept) {
  1507. destroy(d->name);
  1508. destroy(d->display);
  1509. }
  1510. font_close(f);
  1511. display_dec(((DFont*)d)->dref);
  1512. }
  1513. void
  1514. Chans_text(void *fp)
  1515. {
  1516. F_Chans_text *f;
  1517. char buf[16];
  1518. f = fp;
  1519. destroy(*f->ret);
  1520. *f->ret = H;
  1521. if(chantostr(buf, f->c.desc) != nil)
  1522. retstr(buf, f->ret);
  1523. }
  1524. void
  1525. Chans_depth(void *fp)
  1526. {
  1527. F_Chans_depth *f;
  1528. f = fp;
  1529. *f->ret = chantodepth(f->c.desc);
  1530. }
  1531. void
  1532. Chans_eq(void *fp)
  1533. {
  1534. F_Chans_eq *f;
  1535. f = fp;
  1536. *f->ret = f->c.desc == f->d.desc;
  1537. }
  1538. void
  1539. Chans_mk(void *fp)
  1540. {
  1541. F_Chans_mk *f;
  1542. f = fp;
  1543. f->ret->desc = strtochan(string2c(f->s));
  1544. }
  1545. void
  1546. Display_rgb(void *fp)
  1547. {
  1548. ulong c;
  1549. Display *disp;
  1550. F_Display_rgb *f;
  1551. int locked;
  1552. void *r;
  1553. f = fp;
  1554. r = *f->ret;
  1555. *f->ret = H;
  1556. destroy(r);
  1557. disp = checkdisplay(f->d);
  1558. c = ((f->r&255)<<24)|((f->g&255)<<16)|((f->b&255)<<8)|0xFF;
  1559. locked = lockdisplay(disp);
  1560. *f->ret = color((DDisplay*)f->d, c);
  1561. if(locked)
  1562. unlockdisplay(disp);
  1563. }
  1564. void
  1565. Display_rgb2cmap(void *fp)
  1566. {
  1567. F_Display_rgb2cmap *f;
  1568. f = fp;
  1569. /* f->display is unused, but someday may have color map */
  1570. *f->ret = rgb2cmap(f->r, f->g, f->b);
  1571. }
  1572. void
  1573. Display_cmap2rgb(void *fp)
  1574. {
  1575. F_Display_cmap2rgb *f;
  1576. ulong c;
  1577. f = fp;
  1578. /* f->display is unused, but someday may have color map */
  1579. c = cmap2rgb(f->c);
  1580. f->ret->t0 = (c>>16)&0xFF;
  1581. f->ret->t1 = (c>>8)&0xFF;
  1582. f->ret->t2 = (c>>0)&0xFF;
  1583. }
  1584. void
  1585. Display_cmap2rgba(void *fp)
  1586. {
  1587. F_Display_cmap2rgba *f;
  1588. f = fp;
  1589. /* f->display is unused, but someday may have color map */
  1590. *f->ret = cmap2rgba(f->c);
  1591. }
  1592. void
  1593. Draw_setalpha(void *fp)
  1594. {
  1595. F_Draw_setalpha *f;
  1596. f = fp;
  1597. *f->ret = setalpha(f->c, f->a);
  1598. }
  1599. void
  1600. Draw_icossin(void *fp)
  1601. {
  1602. F_Draw_icossin *f;
  1603. int s, c;
  1604. f = fp;
  1605. icossin(f->deg, &s, &c);
  1606. f->ret->t0 = s;
  1607. f->ret->t1 = c;
  1608. }
  1609. void
  1610. Draw_icossin2(void *fp)
  1611. {
  1612. F_Draw_icossin2 *f;
  1613. int s, c;
  1614. f = fp;
  1615. icossin2(f->p.x, f->p.y, &s, &c);
  1616. f->ret->t0 = s;
  1617. f->ret->t1 = c;
  1618. }
  1619. void
  1620. Draw_bytesperline(void *fp)
  1621. {
  1622. F_Draw_bytesperline *f;
  1623. f = fp;
  1624. *f->ret = bytesperline(IRECT(f->r), f->d);
  1625. }
  1626. Draw_Image*
  1627. color(DDisplay *dd, ulong color)
  1628. {
  1629. int c;
  1630. Draw_Rect r;
  1631. r.min.x = 0;
  1632. r.min.y = 0;
  1633. r.max.x = 1;
  1634. r.max.y = 1;
  1635. c = (color&0xff) == 0xff ? RGB24: RGBA32;
  1636. return allocdrawimage(dd, r, c, nil, 1, color);
  1637. }
  1638. Draw_Image*
  1639. mkdrawimage(Image *i, Draw_Screen *screen, Draw_Display *display, void *ref)
  1640. {
  1641. Heap *h;
  1642. DImage *di;
  1643. h = heap(TImage);
  1644. if(h == H)
  1645. return H;
  1646. di = H2D(DImage*, h);
  1647. di->image = i;
  1648. di->drawimage.screen = screen;
  1649. if(screen != H)
  1650. D2H(screen)->ref++;
  1651. di->drawimage.display = display;
  1652. if(display != H)
  1653. D2H(display)->ref++;
  1654. di->refreshptr = ref;
  1655. R2R(di->drawimage.r, i->r);
  1656. R2R(di->drawimage.clipr, i->clipr);
  1657. di->drawimage.chans.desc = i->chan;
  1658. di->drawimage.depth = i->depth;
  1659. di->drawimage.repl = i->repl;
  1660. di->flush = 1;
  1661. di->dref = i->display->limbo;
  1662. di->dref->ref++;
  1663. return &di->drawimage;
  1664. }
  1665. void
  1666. Screen_newwindow(void *fp)
  1667. {
  1668. F_Screen_newwindow *f;
  1669. Image *i;
  1670. Screen *s;
  1671. Rectangle r;
  1672. int locked;
  1673. void *v;
  1674. f = fp;
  1675. s = checkscreen(f->screen);
  1676. R2R(r, f->r);
  1677. if(f->backing != Refnone && f->backing != Refbackup)
  1678. f->backing = Refbackup;
  1679. v = *f->ret;
  1680. *f->ret = H;
  1681. destroy(v);
  1682. locked = lockdisplay(s->display);
  1683. i = allocwindow(s, r, f->backing, f->color);
  1684. if(locked)
  1685. unlockdisplay(s->display);
  1686. if(i == nil)
  1687. return;
  1688. *f->ret = mkdrawimage(i, f->screen, f->screen->display, 0);
  1689. }
  1690. static
  1691. void
  1692. screentopbot(Draw_Screen *screen, Array *array, void (*topbot)(Image **, int))
  1693. {
  1694. Screen *s;
  1695. Draw_Image **di;
  1696. Image **ip;
  1697. int i, n, locked;
  1698. s = checkscreen(screen);
  1699. di = (Draw_Image**)array->data;
  1700. ip = malloc(array->len * sizeof(Image*));
  1701. if(ip == nil)
  1702. return;
  1703. n = 0;
  1704. for(i=0; i<array->len; i++)
  1705. if(di[i] != H){
  1706. ip[n] = lookupimage(di[i]);
  1707. if(ip[n]==nil || ip[n]->screen != s){
  1708. free(ip);
  1709. return;
  1710. }
  1711. n++;
  1712. }
  1713. if(n == 0){
  1714. free(ip);
  1715. return;
  1716. }
  1717. locked = lockdisplay(s->display);
  1718. (*topbot)(ip, n);
  1719. free(ip);
  1720. flushimage(s->display, 1);
  1721. if(locked)
  1722. unlockdisplay(s->display);
  1723. }
  1724. void
  1725. Screen_top(void *fp)
  1726. {
  1727. F_Screen_top *f;
  1728. f = fp;
  1729. screentopbot(f->screen, f->wins, topnwindows);
  1730. }
  1731. void
  1732. Screen_bottom(void *fp)
  1733. {
  1734. F_Screen_top *f;
  1735. f = fp;
  1736. screentopbot(f->screen, f->wins, bottomnwindows);
  1737. }
  1738. void
  1739. freedrawimage(Heap *h, int swept)
  1740. {
  1741. Image *i;
  1742. int locked;
  1743. Display *disp;
  1744. Draw_Image *d;
  1745. d = H2D(Draw_Image*, h);
  1746. i = lookupimage(d);
  1747. if(i == nil) {
  1748. if(!swept)
  1749. freeptrs(d, TImage);
  1750. return;
  1751. }
  1752. disp = i->display;
  1753. locked = lockdisplay(disp);
  1754. freeimage(i);
  1755. if(locked)
  1756. unlockdisplay(disp);
  1757. display_dec(((DImage*)d)->dref);
  1758. /* image/layer header will be freed by caller */
  1759. }
  1760. void
  1761. Image_top(void *fp)
  1762. {
  1763. F_Image_top *f;
  1764. Image *i;
  1765. int locked;
  1766. f = fp;
  1767. i = checkimage(f->win);
  1768. locked = lockdisplay(i->display);
  1769. topwindow(i);
  1770. flushimage(i->display, 1);
  1771. if(locked)
  1772. unlockdisplay(i->display);
  1773. }
  1774. void
  1775. Image_origin(void *fp)
  1776. {
  1777. F_Image_origin *f;
  1778. Image *i;
  1779. int locked;
  1780. f = fp;
  1781. i = checkimage(f->win);
  1782. locked = lockdisplay(i->display);
  1783. if(originwindow(i, IPOINT(f->log), IPOINT(f->scr)) < 0)
  1784. *f->ret = -1;
  1785. else{
  1786. f->win->r = DRECT(i->r);
  1787. f->win->clipr = DRECT(i->clipr);
  1788. *f->ret = 1;
  1789. }
  1790. if(locked)
  1791. unlockdisplay(i->display);
  1792. }
  1793. void
  1794. Image_bottom(void *fp)
  1795. {
  1796. F_Image_top *f;
  1797. Image *i;
  1798. int locked;
  1799. f = fp;
  1800. i = checkimage(f->win);
  1801. locked = lockdisplay(i->display);
  1802. bottomwindow(i);
  1803. flushimage(i->display, 1);
  1804. if(locked)
  1805. unlockdisplay(i->display);
  1806. }
  1807. Draw_Image*
  1808. allocdrawimage(DDisplay *ddisplay, Draw_Rect r, ulong chan, Image *iimage, int repl, int color)
  1809. {
  1810. Heap *h;
  1811. DImage *di;
  1812. Rectangle rr;
  1813. Image *image;
  1814. image = iimage;
  1815. if(iimage == nil){
  1816. R2R(rr, r);
  1817. image = allocimage(ddisplay->display, rr, chan, repl, color);
  1818. if(image == nil)
  1819. return H;
  1820. }
  1821. h = heap(TImage);
  1822. if(h == H){
  1823. if(iimage == nil)
  1824. freeimage(image);
  1825. return H;
  1826. }
  1827. di = H2D(DImage*, h);
  1828. di->drawimage.r = r;
  1829. R2R(di->drawimage.clipr, image->clipr);
  1830. di->drawimage.chans.desc = chan;
  1831. di->drawimage.depth = chantodepth(chan);
  1832. di->drawimage.repl = repl;
  1833. di->drawimage.display = (Draw_Display*)ddisplay;
  1834. D2H(di->drawimage.display)->ref++;
  1835. di->drawimage.screen = H;
  1836. di->dref = ddisplay->display->limbo;
  1837. di->dref->ref++;
  1838. di->image = image;
  1839. di->refreshptr = 0;
  1840. di->flush = 1;
  1841. return &di->drawimage;
  1842. }
  1843. /*
  1844. * Entry points called from the draw library
  1845. */
  1846. Subfont*
  1847. lookupsubfont(Display *d, char *name)
  1848. {
  1849. Cache *c;
  1850. c = cachelookup(sfcache, d, name);
  1851. if(c == nil)
  1852. return nil;
  1853. /*c->u.sf->ref++;*/ /* TO DO: need to revisit the reference counting */
  1854. return c->u.sf;
  1855. }
  1856. void
  1857. installsubfont(char *name, Subfont *subfont)
  1858. {
  1859. Cache *c;
  1860. c = cacheinstall(sfcache, subfont->bits->display, name, subfont, "subfont");
  1861. if(c)
  1862. c->ref++;
  1863. }
  1864. /*
  1865. * BUG version
  1866. */
  1867. char*
  1868. subfontname(char *cfname, char *fname, int maxdepth)
  1869. {
  1870. char *t, *u, tmp1[256], tmp2[256];
  1871. int i, fd;
  1872. if(strcmp(cfname, deffontname) == 0)
  1873. return strdup(cfname);
  1874. t = cfname;
  1875. if(t[0] != '/'){
  1876. strcpy(tmp2, fname);
  1877. u = utfrrune(tmp2, '/');
  1878. if(u)
  1879. u[0] = 0;
  1880. else
  1881. strcpy(tmp2, ".");
  1882. snprint(tmp1, sizeof tmp1, "%s/%s", tmp2, t);
  1883. t = tmp1;
  1884. }
  1885. if(maxdepth > 8)
  1886. maxdepth = 8;
  1887. for(i=3; i>=0; i--){
  1888. if((1<<i) > maxdepth)
  1889. continue;
  1890. /* try i-bit grey */
  1891. snprint(tmp2, sizeof tmp2, "%s.%d", t, i);
  1892. fd = libopen(tmp2, OREAD);
  1893. if(fd >= 0){
  1894. libclose(fd);
  1895. return strdup(tmp2);
  1896. }
  1897. }
  1898. return strdup(t);
  1899. }
  1900. void
  1901. refreshslave(Display *d)
  1902. {
  1903. int i, n, id;
  1904. uchar buf[5*(5*4)], *p;
  1905. Rectangle r;
  1906. Image *im;
  1907. int locked;
  1908. for(;;){
  1909. release();
  1910. n = kchanio(d->refchan, buf, sizeof buf, OREAD);
  1911. acquire();
  1912. if(n < 0) /* probably caused by closedisplay() closing refchan */
  1913. return; /* will fall off end of thread and close down */
  1914. locked = lockdisplay(d);
  1915. p = buf;
  1916. for(i=0; i<n; i+=5*4,p+=5*4){
  1917. id = BGLONG(p+0*4);
  1918. r.min.x = BGLONG(p+1*4);
  1919. r.min.y = BGLONG(p+2*4);
  1920. r.max.x = BGLONG(p+3*4);
  1921. r.max.y = BGLONG(p+4*4);
  1922. for(im=d->windows; im; im=im->next)
  1923. if(im->id == id)
  1924. break;
  1925. if(im && im->screen && im->reffn)
  1926. (*im->reffn)(im, r, im->refptr);
  1927. }
  1928. flushimage(d, 1);
  1929. if(locked)
  1930. unlockdisplay(d);
  1931. }
  1932. }
  1933. void
  1934. startrefresh(Display *disp)
  1935. {
  1936. USED(disp);
  1937. }
  1938. static
  1939. int
  1940. doflush(Display *d)
  1941. {
  1942. int m, n;
  1943. char err[ERRMAX];
  1944. uchar *tp;
  1945. n = d->bufp-d->buf;
  1946. if(n <= 0)
  1947. return 1;
  1948. if(d->local == 0)
  1949. release();
  1950. if((m = kchanio(d->datachan, d->buf, n, OWRITE)) != n){
  1951. if(d->local == 0)
  1952. acquire();
  1953. kgerrstr(err, sizeof err);
  1954. if(_drawdebug || strcmp(err, "screen id in use") != 0 && strcmp(err, exImage) != 0){
  1955. print("flushimage fail: (%d not %d) d=%lux: %s\nbuffer: ", m, n, (ulong)d, err);
  1956. for(tp = d->buf; tp < d->bufp; tp++)
  1957. print("%.2x ", (int)*tp);
  1958. print("\n");
  1959. }
  1960. d->bufp = d->buf; /* might as well; chance of continuing */
  1961. return -1;
  1962. }
  1963. d->bufp = d->buf;
  1964. if(d->local == 0)
  1965. acquire();
  1966. return 1;
  1967. }
  1968. int
  1969. flushimage(Display *d, int visible)
  1970. {
  1971. int ret;
  1972. Refreshq *r;
  1973. for(;;){
  1974. if(visible)
  1975. *d->bufp++ = 'v'; /* one byte always reserved for this */
  1976. ret = doflush(d);
  1977. if(d->refhead == nil)
  1978. break;
  1979. while(r = d->refhead){ /* assign = */
  1980. d->refhead = r->next;
  1981. if(d->refhead == nil)
  1982. d->reftail = nil;
  1983. r->reffn(nil, r->r, r->refptr);
  1984. free(r);
  1985. }
  1986. }
  1987. return ret;
  1988. }
  1989. /*
  1990. * Turn off refresh for this window and remove any pending refresh events for it.
  1991. */
  1992. void
  1993. delrefresh(Image *i)
  1994. {
  1995. Refreshq *r, *prev, *next;
  1996. int locked;
  1997. Display *d;
  1998. void *refptr;
  1999. d = i->display;
  2000. /*
  2001. * Any refresh function will do, because the data pointer is nil.
  2002. * Can't use nil, though, because that turns backing store back on.
  2003. */
  2004. if(d->local)
  2005. drawlsetrefresh(d->dataqid, i->id, memlnorefresh, nil);
  2006. refptr = i->refptr;
  2007. i->refptr = nil;
  2008. if(d->refhead==nil || refptr==nil)
  2009. return;
  2010. locked = lockdisplay(d);
  2011. prev = nil;
  2012. for(r=d->refhead; r; r=next){
  2013. next = r->next;
  2014. if(r->refptr == refptr){
  2015. if(prev)
  2016. prev->next = next;
  2017. else
  2018. d->refhead = next;
  2019. if(d->reftail == r)
  2020. d->reftail = prev;
  2021. free(r);
  2022. }else
  2023. prev = r;
  2024. }
  2025. if(locked)
  2026. unlockdisplay(d);
  2027. }
  2028. void
  2029. queuerefresh(Image *i, Rectangle r, Reffn reffn, void *refptr)
  2030. {
  2031. Display *d;
  2032. Refreshq *rq;
  2033. d = i->display;
  2034. rq = malloc(sizeof(Refreshq));
  2035. if(rq == nil)
  2036. return;
  2037. if(d->reftail)
  2038. d->reftail->next = rq;
  2039. else
  2040. d->refhead = rq;
  2041. d->reftail = rq;
  2042. rq->reffn = reffn;
  2043. rq->refptr = refptr;
  2044. rq->r = r;
  2045. }
  2046. uchar*
  2047. bufimage(Display *d, int n)
  2048. {
  2049. uchar *p;
  2050. if(n<0 || n>Displaybufsize){
  2051. kwerrstr("bad count in bufimage");
  2052. return 0;
  2053. }
  2054. if(d->bufp+n > d->buf+Displaybufsize){
  2055. if(d->local==0 && currun()!=libqlowner(d->qlock)) {
  2056. print("bufimage: %lux %lux\n", (ulong)libqlowner(d->qlock), (ulong)currun());
  2057. abort();
  2058. }
  2059. if(doflush(d) < 0)
  2060. return 0;
  2061. }
  2062. p = d->bufp;
  2063. d->bufp += n;
  2064. /* return with buffer locked */
  2065. return p;
  2066. }
  2067. void
  2068. drawerror(Display *d, char *s)
  2069. {
  2070. USED(d);
  2071. fprint(2, "draw: %s: %r\n", s);
  2072. }