I386.Raster.Mod 112 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623
  1. MODULE Raster; (** non-portable *) (* eos, TF **)
  2. (** AUTHOR "eos"; PURPOSE "Raster operations"; *)
  3. (**
  4. Raster image bitmaps and basic image processing
  5. **)
  6. (*
  7. 19.9.1999 - spawned from GfxMaps
  8. 25.10.1999 - fixed bytes-per-row calculation in Create (need to make arguments LONG)
  9. 17.11.1999 - eliminated F8 format, replaced by D8 (implemented with module Colors)
  10. 19.11.1999 - fixed missing alpha component in computed palettes
  11. 16.05.2000 - module Raster as Oberon-independent part of Images
  12. 19.06.2000 - replaced DisplayFormat and InitDisplay by DisplayFormat()
  13. 25.02.2006 - raster operations with SSE2 added (student project by Myrto Zehnder)
  14. 28.02.2008 - added capabilities for 16-bit palette & grayscale images often used in scientific,medical imaging and professional photography (Patrick Hunziker)
  15. To do:
  16. - store in compressed format
  17. - add capabilities for RGB and multiplane images with >8 bits per color as used in scientific imaging and professional photography
  18. *)
  19. IMPORT
  20. SYSTEM, KernelLog, Machine, Streams, CLUTs, Displays;
  21. (*
  22. Interfacing with display hardware and foreign framebuffers may suffer a performance hit if their
  23. bit or byte ordering can't be made compatible with that of a built-in format and has to be converted
  24. manually. Predefined format A1 has the leftmost pixel in the least significant bit of a byte, and
  25. all hi/true color formats have their blue component at the lowest address, followed by green,
  26. red, and possibly alpha (which conforms to the specification of the transfer formats in Displays).
  27. As SYSTEM is imported, the module is not portable and has always to be compiled to native code.
  28. However, it should usually suffice to recompile the module on other platforms without changing
  29. any code.
  30. Assumptions:
  31. * CHR(l) = CHR(l MOD 100H) for all l: LONGINT
  32. * SIZEOF(LONGINT)=4
  33. *)
  34. CONST
  35. b* = 0; g* = 1; r* = 2; a* = 3; (** index of blue, green, red, and alpha components in a Pixel **)
  36. (** format codes **)
  37. custom* = 0; a1* = 1; a8* = 2; d8* = 3; p8* = 4; bgr555* = 5; bgr565* = 6; bgr466* = 7; bgr888* = 8; bgra8888* = 9; p16* =10;
  38. (** components **)
  39. color* = 0; alpha* = 1; index* = 2;
  40. (** compositing operations (srcCopy = replace, srcOverDst = paint **)
  41. clear* = 0; srcCopy* = 1; dstCopy* = 2; srcOverDst* = 3; dstOverSrc* = 4; srcInDst* = 5; dstInSrc* = 6;
  42. srcWithoutDst* = 7; dstWithoutSrc* = 8; srcAtopDst* = 9; dstAtopSrc* = 10; srcXorDst* = 11; InvDst*=12;
  43. InvOverDst*=13;
  44. MAXCOL = 10000H; (*current implementation limitation for number of color indexes *)
  45. TYPE
  46. (** general pixels with red, green, blue, and alpha information in range 0..255; alpha is pre-multiplied into RGB **)
  47. Pixel* = ARRAY 4 OF CHAR;
  48. (** palette structure for indexed formats **)
  49. Palette* = OBJECT
  50. VAR
  51. col*: POINTER TO ARRAY OF Pixel; (** color table **)
  52. used*: LONGINT; (** number of valid entries in color table **)
  53. clut: CLUTs.CLUT; (* reverse color lookup structure *)
  54. PROCEDURE &New*; BEGIN NEW(col,256); used:=256 END New; (*initialized to 256 colors; for backwards compatibility*)
  55. PROCEDURE Init*(used:LONGINT); BEGIN SELF.used:=used; IF LEN(col,0)#used THEN NEW(col,used) END END Init; (*initialize to size # 256*) (*bugfix PH090122*)
  56. END Palette;
  57. (** image format **)
  58. Format0* = RECORD
  59. code*: SHORTINT; (** format code for quick format checks **)
  60. bpp*: SHORTINT; (** number of bits per pixel **)
  61. align*: SHORTINT; (** bytes per row must be multiple of this **)
  62. components*: SET; (** components that are stored in a pixel **)
  63. pal*: Palette; (** optional palette for indexed formats **)
  64. END;
  65. PackProc* = PROCEDURE (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  66. Format* = RECORD (Format0)
  67. pack*: PackProc; (** store supported pixel components at given address **)
  68. unpack*: PackProc; (** load supported pixel components from given address **)
  69. END;
  70. (** raster image **)
  71. Image* = OBJECT (* POINTER TO ImageDesc;
  72. ImageDesc* = RECORD *)
  73. VAR
  74. width*, height*: LONGINT; (** image dimensions **)
  75. fmt*: Format; (** pixel format **)
  76. bpr*: LONGINT; (** number of bytes per row (may be negative) **)
  77. adr*: ADDRESS; (** address of lower left pixel **)
  78. mem*: POINTER TO ARRAY OF CHAR; (** block where pixels are stored; mem#NIL implies adr=ADR(mem[0]) **)
  79. END Image;
  80. (** transfer mode **)
  81. Mode0* = RECORD
  82. src*, dst*: Format; (** source and destination format **)
  83. op*: LONGINT; (** compositing operation **)
  84. col*: Pixel; (** substitute color used when transfering from pure alpha formats to colored ones **)
  85. buf: Pixel; (* constant area for special-case moving *)
  86. map: POINTER TO ARRAY OF INTEGER; (* color map for transfer between indexed formats *)
  87. END;
  88. TransferProc* = PROCEDURE (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  89. Mode* = RECORD (Mode0)
  90. transfer*: TransferProc; (** procedure transfering pixels from source to destination **)
  91. END;
  92. PictureTransferParameters* = POINTER TO RECORD
  93. img* : Image;
  94. name* : ARRAY 128 OF CHAR;
  95. done* : BOOLEAN
  96. END;
  97. VAR
  98. A1*, A8*, D8*, BGR555*, BGR565*, BGR466*, BGR888*, BGRA8888*: Format; (** predefined formats **)
  99. PixelFormat*: Format; (** special formats **)
  100. Clamp*: ARRAY 500H OF CHAR; (** Clamp[200H+i] = CHR(min(max(i, 0), 0FFH)) **)
  101. Zero: Pixel; (* pixel with all components cleared *)
  102. Bit: ARRAY 100H, 8 OF BOOLEAN; (* Bit[b, i] means bit i in byte b is set *)
  103. Set, Clr: ARRAY 100H, 8 OF CHAR; (* Set/Clr[b, i] is byte b with bit i set/cleared *)
  104. (* d8display: Displays.Display; (* only one system-wide D8 display supported *)
  105. plugin: Plugins.Plugin; *)
  106. MMXenabled*,SSE2enabled* : BOOLEAN;
  107. (**--- Color/Pixel conversions ---**)
  108. (** set pixel to opaque RGB value **)
  109. PROCEDURE SetRGB* (VAR pix: Pixel; red, green, blue: LONGINT);
  110. BEGIN
  111. pix[b] := CHR(blue); pix[g] := CHR(green); pix[r] := CHR(red); pix[a] := 0FFX
  112. END SetRGB;
  113. (** set pixel to partly transparent RGB value **)
  114. PROCEDURE SetRGBA* (VAR pix: Pixel; red, green, blue, alpha: LONGINT);
  115. BEGIN
  116. pix[b] := CHR(blue * alpha DIV 255);
  117. pix[g] := CHR(green * alpha DIV 255);
  118. pix[r] := CHR(red * alpha DIV 255);
  119. pix[a] := CHR(alpha)
  120. END SetRGBA;
  121. (** retrieve RGB and alpha values from pixel **)
  122. PROCEDURE GetRGBA* (pix: Pixel; VAR red, green, blue, alpha: LONGINT);
  123. BEGIN
  124. alpha := ORD(pix[a]);
  125. IF alpha = 0 THEN (* color has disappeared *)
  126. red := 255; green := 255; blue := 255
  127. ELSE
  128. red := ORD(pix[r]); green := ORD(pix[g]); blue := ORD(pix[b]);
  129. IF alpha # 255 THEN (* un-multiply alpha *)
  130. red := 255 * red DIV alpha; IF red > 255 THEN red := 255 END;
  131. green := 255 * green DIV alpha; IF green > 255 THEN green := 255 END;
  132. blue := 255 * blue DIV alpha; IF blue > 255 THEN blue := 255 END
  133. END
  134. END
  135. END GetRGBA;
  136. (**--- Palettes ---**)
  137. (** return index of color in palette which approximates the requested color reasonably well **)
  138. PROCEDURE PaletteIndex* (pal: Palette; red, green, blue: LONGINT): LONGINT;
  139. BEGIN
  140. IF pal.used>256 THEN
  141. RETURN CLUTs.Match(pal.clut, ASH(red, 16) + ASH(green, 8) + blue) *pal.used DIV 256 (*PH090122*)
  142. ELSE RETURN CLUTs.Match(pal.clut, ASH(red, 16) + ASH(green, 8) + blue)
  143. END;
  144. END PaletteIndex;
  145. (** compute internal palette structures whenever palette colors have been modified **)
  146. PROCEDURE InitPalette* (pal: Palette; used, bits: LONGINT);
  147. VAR n, red, green, blue, alpha: LONGINT;
  148. BEGIN
  149. n := 0;
  150. IF used>pal.used THEN NEW(pal.col,used);END;
  151. pal.used:=used;
  152. WHILE n < used DO
  153. GetRGBA(pal.col[n], red, green, blue, alpha);
  154. CLUTs.Set(pal.clut, (*n*) n*255 DIV used, ASH(red, 16) + ASH(green, 8) + blue);
  155. INC(n)
  156. END;
  157. CLUTs.Init(pal.clut, MIN (used,256), bits);
  158. END InitPalette;
  159. (** (re)compute grayscale palette, typically used for pictures with >256 gray scale values**)
  160. PROCEDURE InitGrayPalette* (pal: Palette; used, bits: LONGINT);
  161. VAR n, gray: LONGINT;
  162. BEGIN
  163. n := 0;
  164. IF used>pal.used THEN NEW(pal.col,used); END;
  165. pal.used := used;
  166. WHILE n < used DO
  167. gray:= n*255 DIV used;
  168. SetRGBA(pal.col[n],gray,gray,gray,255); (*PH 090122*)
  169. CLUTs.Set(pal.clut, gray, ASH(gray, 16) + ASH(gray, 8) + gray);
  170. INC(n)
  171. END;
  172. CLUTs.Init(pal.clut, MIN(used,256), bits);
  173. END InitGrayPalette;
  174. (** copy palette contents **)
  175. PROCEDURE CopyPalette* (from, to: Palette);
  176. VAR n: LONGINT;
  177. BEGIN
  178. n := 0;
  179. IF to.used<from.used THEN NEW(to.col,from.used) END;
  180. to.used:=from.used;
  181. WHILE n < from.used DO
  182. to.col[n] := from.col[n]; INC(n)
  183. END;
  184. CLUTs.Copy(from.clut, to.clut)
  185. END CopyPalette;
  186. (** compute and initialize a pseudo-optimal palette for an image (in hi-color or true-color format) **)
  187. PROCEDURE ComputePalette* (img: Image; pal: Palette; reservedcols, maxcols, bits: LONGINT);
  188. (*
  189. uses octree-quantization
  190. *)
  191. TYPE
  192. Node = POINTER TO RECORD (* octree node *)
  193. dsc: ARRAY 8 OF Node; (* descendants *)
  194. link: Node; (* next reducible node on same level *)
  195. leaf: BOOLEAN;
  196. weight: LONGINT; (* accumulated number of pixels represented by this node *)
  197. r, g, b: LONGINT; (* accumulated color values *)
  198. END;
  199. VAR
  200. sent, root: Node; reducible: ARRAY 8 OF Node; colors, maxDepth, y, x, bb, used: LONGINT; adr, aa: ADDRESS; pix: Pixel;
  201. PROCEDURE insert (VAR node: Node; depth: LONGINT; pix: Pixel);
  202. VAR idx, bit: LONGINT;
  203. BEGIN
  204. IF node = NIL THEN
  205. NEW(node);
  206. IF depth = maxDepth THEN
  207. node.leaf := TRUE;
  208. INC(colors)
  209. ELSE
  210. node.leaf := FALSE;
  211. node.link := reducible[depth]; reducible[depth] := node
  212. END
  213. END;
  214. INC(node.weight); (* node represents more pixels *)
  215. IF node.leaf THEN
  216. INC(node.r, LONG(ORD(pix[r])));
  217. INC(node.g, LONG(ORD(pix[g])));
  218. INC(node.b, LONG(ORD(pix[b])))
  219. ELSE
  220. idx := 0; bit := 7-depth;
  221. IF ODD(ASH(ORD(pix[r]), -bit)) THEN INC(idx, 4) END;
  222. IF ODD(ASH(ORD(pix[g]), -bit)) THEN INC(idx, 2) END;
  223. IF ODD(ASH(ORD(pix[b]), -bit)) THEN INC(idx) END;
  224. insert(node.dsc[idx], depth+1, pix)
  225. END
  226. END insert;
  227. PROCEDURE reduce;
  228. VAR d, min, n, i: LONGINT; node, prev, dsc: Node;
  229. BEGIN
  230. d := maxDepth-1;
  231. WHILE reducible[d] = NIL DO
  232. DEC(d); DEC(maxDepth)
  233. END;
  234. sent.link := reducible[d];
  235. node := sent; min := MAX(LONGINT);
  236. WHILE node.link # NIL DO
  237. IF node.link.weight < min THEN
  238. min := node.link.weight; prev := node
  239. END;
  240. node := node.link
  241. END;
  242. node := prev.link; prev.link := node.link;
  243. reducible[d] := sent.link;
  244. n := 1; (* number of colors is initially one for the node itself *)
  245. FOR i := 0 TO 7 DO
  246. dsc := node.dsc[i];
  247. IF dsc # NIL THEN
  248. DEC(n); (* reducing one color *)
  249. INC(node.r, dsc.r); INC(node.g, dsc.g); INC(node.b, dsc.b);
  250. node.dsc[i] := NIL
  251. END
  252. END;
  253. node.leaf := TRUE;
  254. INC(colors, n)
  255. END reduce;
  256. PROCEDURE traverse (node: Node);
  257. VAR i: LONGINT;
  258. BEGIN
  259. IF node # NIL THEN
  260. IF node.leaf THEN
  261. pal.col[used, r] := CHR(node.r DIV node.weight);
  262. pal.col[used, g] := CHR(node.g DIV node.weight);
  263. pal.col[used, b] := CHR(node.b DIV node.weight);
  264. pal.col[used, a] := 0FFX;
  265. INC(used)
  266. ELSE
  267. FOR i := 0 TO 7 DO
  268. traverse(node.dsc[i])
  269. END
  270. END
  271. END
  272. END traverse;
  273. BEGIN (* ComputePalette *)
  274. ASSERT(reservedcols + maxcols <= MAXCOL, 100);
  275. NEW(sent);
  276. root := NIL; colors := 0; maxDepth := 8;
  277. y := 0; adr := img.adr;
  278. WHILE y < img.height DO
  279. IF img.fmt.bpp < 8 THEN
  280. x := 0; aa := adr; bb := 0;
  281. WHILE x < img.width DO
  282. img.fmt.unpack(img.fmt, aa, bb, pix);
  283. insert(root, 0, pix);
  284. WHILE colors > maxcols DO
  285. reduce()
  286. END;
  287. INC(x); bb := bb + img.fmt.bpp; INC(aa, bb DIV 8); bb := bb MOD 8
  288. END
  289. ELSE
  290. x := 0; aa := adr; bb := img.fmt.bpp DIV 8;
  291. WHILE x < img.width DO
  292. img.fmt.unpack(img.fmt, aa, 0, pix);
  293. insert(root, 0, pix);
  294. WHILE colors > maxcols DO
  295. reduce()
  296. END;
  297. INC(x); INC(aa, bb)
  298. END
  299. END;
  300. INC(y); INC(adr, img.bpr)
  301. END;
  302. used := reservedcols;
  303. traverse(root);
  304. InitPalette(pal, used, bits)
  305. END ComputePalette;
  306. (**--- Formats ---**)
  307. (* A1 - one bit alpha, MSB leftmost *)
  308. PROCEDURE PackA1 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  309. VAR b: CHAR;
  310. BEGIN
  311. SYSTEM.GET(adr, b);
  312. IF pix[a] >= 80X THEN SYSTEM.PUT(adr, Set[ORD(b), bit])
  313. ELSE SYSTEM.PUT(adr, Clr[ORD(b), bit])
  314. END
  315. END PackA1;
  316. PROCEDURE UnpackA1 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  317. VAR b: CHAR;
  318. BEGIN
  319. SYSTEM.GET(adr, b);
  320. IF Bit[ORD(b), bit] THEN pix[a] := 0FFX
  321. ELSE pix := Zero
  322. END
  323. END UnpackA1;
  324. (* A8 - 8 bit alpha *)
  325. PROCEDURE PackA8 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  326. BEGIN
  327. SYSTEM.PUT(adr, pix[a])
  328. END PackA8;
  329. PROCEDURE UnpackA8 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  330. VAR alpha: LONGINT;
  331. BEGIN
  332. SYSTEM.GET(adr, pix[a]);
  333. IF pix[a] = 0X THEN
  334. pix := Zero
  335. ELSIF pix[a] # 0FFX THEN
  336. alpha := ORD(pix[a]);
  337. pix[r] := CHR(ORD(pix[r]) * alpha DIV 255);
  338. pix[g] := CHR(ORD(pix[g]) * alpha DIV 255);
  339. pix[b] := CHR(ORD(pix[b]) * alpha DIV 255)
  340. END
  341. END UnpackA8;
  342. (* P8 - 8 bit indexed format with custom palette *)
  343. PROCEDURE PackP8 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  344. BEGIN
  345. IF pix[a] # 0X THEN (* model alpha as brightness *)
  346. SYSTEM.PUT(adr, CHR(CLUTs.Match(fmt.pal.clut, ORD(pix[b]) + ASH(ORD(pix[g]), 8) + ASH(ORD(pix[r]), 16))))
  347. END
  348. END PackP8;
  349. PROCEDURE UnpackP8 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  350. VAR idx: CHAR;
  351. BEGIN
  352. SYSTEM.GET(adr, idx); pix := fmt.pal.col[ORD(idx)]
  353. END UnpackP8;
  354. (* D8 - 8 bit indexed format with display palette *)
  355. PROCEDURE PackD8 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  356. BEGIN
  357. IF pix[a] # 0X THEN (* model alpha as brightness *)
  358. SYSTEM.PUT(adr, CHR(ColorToIndex(ORD(pix[b]) + ASH(ORD(pix[g]), 8) + ASH(ORD(pix[r]), 16))))
  359. END
  360. END PackD8;
  361. PROCEDURE UnpackD8 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  362. VAR idx: CHAR; col: LONGINT;
  363. BEGIN
  364. SYSTEM.GET(adr, idx); col := IndexToColor(ORD(idx));
  365. pix[b] := CHR(col MOD 100H); pix[g] := CHR(ASH(col, -8) MOD 100H); pix[r] := CHR(ASH(col, -16) MOD 100H)
  366. END UnpackD8;
  367. (* P16 - 16 bit indexed format with custom palette *)
  368. PROCEDURE PackP16 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  369. VAR val:LONGINT;
  370. BEGIN
  371. IF pix[a] # 0X THEN (* model alpha as brightness *)
  372. (*SYSTEM.PUT16(adr, PaletteIndex(fmt.pal, ORD(pix[r]), ORD(pix[g]), ORD(pix[b])))*)
  373. val:=CLUTs.Match(fmt.pal.clut, ORD(pix[b]) + ASH(ORD(pix[g]), 8) + ASH(ORD(pix[r]),16));
  374. IF fmt.pal.used>256 THEN val:=val*fmt.pal.used DIV 256 END;
  375. SYSTEM.PUT16(adr, SHORT(val))
  376. END
  377. END PackP16;
  378. PROCEDURE UnpackP16 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  379. BEGIN
  380. pix := fmt.pal.col[SYSTEM.GET16(adr) MOD 1000H] (*unsigned 16 bit entity*)
  381. END UnpackP16;
  382. (* BGR555 - 16 hi-color with 5 bit blue, 5 bit green and 5 bit red in ascending order *)
  383. PROCEDURE PackBGR555 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  384. VAR int: LONGINT;
  385. BEGIN
  386. IF pix[a] # 0X THEN (* model alpha as brightness *)
  387. int := ASH(ORD(pix[b]), -3) + ASH(ASH(ORD(pix[g]), -3), 5) + ASH(ASH(ORD(pix[r]), -3), 10);
  388. SYSTEM.PUT(adr, CHR(int)); SYSTEM.PUT(adr+1, CHR(ASH(int, -8)))
  389. END
  390. END PackBGR555;
  391. PROCEDURE UnpackBGR555 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  392. VAR lo, hi: CHAR; int: LONGINT;
  393. BEGIN
  394. SYSTEM.GET(adr, lo); SYSTEM.GET(adr+1, hi); int := ASH(ORD(hi), 8) + ORD(lo);
  395. pix[b] := CHR(ASH(int MOD 20H, 3) + 4);
  396. pix[g] := CHR(ASH(ASH(int, -5) MOD 20H, 3) + 4);
  397. pix[r] := CHR(ASH(ASH(int, -10) MOD 20H, 3) + 4);
  398. pix[a] := 0FFX
  399. END UnpackBGR555;
  400. (* BGR565 - 16 hi-color with 5 bit blue, 6 bit green and 5 bit red in ascending order *)
  401. PROCEDURE PackBGR565 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  402. VAR int: LONGINT;
  403. BEGIN
  404. IF pix[a] # 0X THEN (* model alpha as brightness *)
  405. int := ASH(ORD(pix[b]), -3) + ASH(ASH(ORD(pix[g]), -2), 5) + ASH(ASH(ORD(pix[r]), -3), 11);
  406. SYSTEM.PUT(adr, CHR(int)); SYSTEM.PUT(adr+1, CHR(ASH(int, -8)))
  407. END
  408. END PackBGR565;
  409. PROCEDURE UnpackBGR565 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  410. VAR lo, hi: CHAR; int: LONGINT;
  411. BEGIN
  412. SYSTEM.GET(adr, lo); SYSTEM.GET(adr+1, hi); int := ASH(ORD(hi), 8) + ORD(lo);
  413. pix[b] := CHR(ASH(int MOD 20H, 3) + 4);
  414. pix[g] := CHR(ASH(ASH(int, -5) MOD 40H, 2) + 2);
  415. pix[r] := CHR(ASH(ASH(int, -11) MOD 20H, 3) + 4);
  416. pix[a] := 0FFX
  417. END UnpackBGR565;
  418. (* BGR466 - 16 hi-color with 4 bit blue, 6 bit green and 6 bit red in ascending order *)
  419. PROCEDURE PackBGR466 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  420. VAR int: LONGINT;
  421. BEGIN
  422. IF pix[a] # 0X THEN (* model alpha as brightness *)
  423. int := ASH(ORD(pix[b]), -4) + ASH(ASH(ORD(pix[g]), -2), 4) + ASH(ASH(ORD(pix[r]), -2), 10);
  424. SYSTEM.PUT(adr, CHR(int)); SYSTEM.PUT(adr+1, CHR(ASH(int, -8)))
  425. END
  426. END PackBGR466;
  427. PROCEDURE UnpackBGR466 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  428. VAR lo, hi: CHAR; int: LONGINT;
  429. BEGIN
  430. SYSTEM.GET(adr, lo); SYSTEM.GET(adr+1, hi); int := ASH(ORD(hi), 8) + ORD(lo);
  431. pix[b] := CHR(ASH(int MOD 10H, 4) + 8);
  432. pix[g] := CHR(ASH(ASH(int, -4) MOD 40H, 2) + 2);
  433. pix[r] := CHR(ASH(ASH(int, -10) MOD 40H, 2) + 2);
  434. pix[a] := 0FFX
  435. END UnpackBGR466;
  436. (* BGR888 - 24 bit true color with blue in lower, green in middle, and red in upper byte *)
  437. PROCEDURE PackBGR888 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  438. BEGIN
  439. IF pix[a] # 0X THEN (* model alpha as brightness *)
  440. SYSTEM.MOVE(ADDRESSOF(pix[0]), adr, 3)
  441. END
  442. END PackBGR888;
  443. PROCEDURE UnpackBGR888 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  444. BEGIN
  445. SYSTEM.MOVE(adr, ADDRESSOF(pix[0]), 3); pix[a] := 0FFX
  446. END UnpackBGR888;
  447. (* BGRA8888 - 32 bit true color with blue in lowest, green in lower middle, red in upper middle, and alpha in top byte *)
  448. PROCEDURE PackBGRA8888 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  449. BEGIN
  450. SYSTEM.MOVE(ADDRESSOF(pix[0]), adr, 4)
  451. END PackBGRA8888;
  452. PROCEDURE UnpackBGRA8888 (VAR fmt: Format0; adr: ADDRESS; bit: LONGINT; VAR pix: Pixel);
  453. BEGIN
  454. SYSTEM.MOVE(adr, ADDRESSOF(pix[0]), 4)
  455. END UnpackBGRA8888;
  456. (** return image format for given Displays transfer format **)
  457. PROCEDURE DisplayFormat* (format: LONGINT): Format;
  458. BEGIN
  459. CASE format OF
  460. | Displays.index8: RETURN D8
  461. | Displays.color565: RETURN BGR565
  462. | Displays.color888: RETURN BGR888
  463. | Displays.color8888: RETURN BGRA8888
  464. END
  465. END DisplayFormat;
  466. (** initialize format **)
  467. PROCEDURE InitFormat* (VAR fmt: Format; code, bpp, align: SHORTINT; comps: SET; pal: Palette; pack, unpack: PackProc);
  468. BEGIN
  469. fmt.code := code; fmt.bpp := bpp; fmt.align := align; fmt.components := comps; fmt.pal := pal;
  470. fmt.pack := pack; fmt.unpack := unpack
  471. END InitFormat;
  472. (** initialize index formats with custom palette **)
  473. PROCEDURE InitPaletteFormat* (VAR fmt: Format; pal: Palette);
  474. BEGIN
  475. fmt.components := {index}; fmt.pal := pal;
  476. IF pal.used<=256 THEN
  477. fmt.align := 1;
  478. fmt.code := p8; fmt.bpp := 8;
  479. fmt.pack := PackP8; fmt.unpack := UnpackP8
  480. ELSIF pal.used <= 10000H THEN
  481. fmt.align := 2;
  482. fmt.code := p16; fmt.bpp := 16;
  483. fmt.pack := PackP16; fmt.unpack := UnpackP16
  484. ELSE HALT(199)
  485. END
  486. END InitPaletteFormat;
  487. (** return if two formats are the same **)
  488. PROCEDURE Same* (VAR fmt0, fmt1: Format): BOOLEAN;
  489. BEGIN
  490. RETURN
  491. (fmt0.pack = fmt1.pack) & (fmt0.unpack = fmt1.unpack) &
  492. (~(index IN fmt0.components) OR (fmt0.pal = fmt1.pal)) (* doesn't work if palette has been re-initialized *)
  493. END Same;
  494. (**--- Images ---**)
  495. (** initialize custom image **)
  496. PROCEDURE Init* (img: Image; width, height: LONGINT; VAR fmt: Format; bpr: LONGINT; adr: ADDRESS);
  497. BEGIN
  498. ASSERT((width > 0) & (height > 0), 100);
  499. img.width := width; img.height := height; img.fmt := fmt; img.bpr := bpr; img.adr := adr
  500. END Init;
  501. (** initialize custom image on byte buffer **)
  502. PROCEDURE InitBuf* (img: Image; width, height: LONGINT; VAR fmt: Format; bpr, offset: LONGINT; VAR buf: ARRAY OF CHAR);
  503. BEGIN
  504. ASSERT((0 <= offset) & (offset + height * ABS(bpr) <= LEN(buf)), 100);
  505. IF bpr >= 0 THEN Init(img, width, height, fmt, bpr, ADDRESSOF(buf[0]))
  506. ELSE Init(img, width, height, fmt, bpr, ADDRESSOF(buf[offset]) + LEN(buf) - bpr)
  507. END
  508. END InitBuf;
  509. (** initialize image on rectangular area within existing image (lower left corner must fall on byte boundary) **)
  510. PROCEDURE InitRect* (img, base: Image; x, y, w, h: LONGINT);
  511. BEGIN
  512. ASSERT((0 <= x) & (x + w <= base.width) & (0 <= y) & (y + h <= base.height), 100);
  513. ASSERT(x * base.fmt.bpp MOD 8 = 0, 101);
  514. Init(img, w, h, base.fmt, base.bpr, base.adr + y * base.bpr + x * base.fmt.bpp DIV 8)
  515. END InitRect;
  516. (** create image in requested format (allocating or reusing necessary memory) **)
  517. PROCEDURE Create* (img: Image; width, height: LONGINT; fmt: Format);
  518. VAR size: LONGINT; a0, a1: ADDRESS;
  519. BEGIN
  520. ASSERT((width > 0) & (height > 0), 100);
  521. img.width := width; img.height := height;
  522. img.fmt := fmt;
  523. img.bpr := (width * fmt.bpp + 7) DIV 8;
  524. IF fmt.align > 1 THEN
  525. img.bpr := (img.bpr + fmt.align - 1) DIV fmt.align * fmt.align
  526. END;
  527. size := height * img.bpr; INC(size, (-size) MOD 4);
  528. IF (img.mem = NIL) OR (size < LEN(img.mem^) DIV 2) OR (LEN(img.mem^) < size) THEN
  529. NEW(img.mem, size)
  530. ELSE
  531. a0 := ADDRESSOF(img.mem[0]); a1 := a0 + size;
  532. WHILE a0 # a1 DO
  533. SYSTEM.PUT32(a0,0); INC(a0, SIZEOF(LONGINT))
  534. END
  535. END;
  536. img.adr := ADDRESSOF(img.mem[0])
  537. END Create;
  538. PROCEDURE CreateWithBuffer*(img: Image; width, height: LONGINT; fmt: Format; mem: POINTER TO ARRAY OF CHAR; VAR adr: LONGINT);
  539. VAR size: LONGINT; a0, a1: ADDRESS;
  540. BEGIN
  541. ASSERT((width > 0) & (height > 0), 100);
  542. img.width := width; img.height := height;
  543. img.fmt := fmt;
  544. img.bpr := (width * fmt.bpp + 7) DIV 8;
  545. IF fmt.align > 1 THEN
  546. img.bpr := (img.bpr + fmt.align - 1) DIV fmt.align * fmt.align
  547. END;
  548. size := height * img.bpr; INC(size, (-size) MOD 4);
  549. a0 := adr; a1 := adr + size;
  550. ASSERT(ADDRESSOF(mem[0]) <= a0);
  551. ASSERT(a1 <= ADDRESSOF(mem[LEN(mem)-1]));
  552. WHILE a0 # a1 DO
  553. SYSTEM.PUT32(a0,0); INC(a0, SIZEOF(LONGINT))
  554. END;
  555. img.adr := adr;
  556. img.mem := mem;
  557. adr := a1;
  558. END CreateWithBuffer;
  559. (**--- Transfer Modes ---**)
  560. (** initialize transfer mode **)
  561. PROCEDURE InitMode* (VAR mode: Mode; op: SHORTINT);
  562. BEGIN
  563. mode.op := op;
  564. IF (mode.src.pal # NIL) & ((mode.map = NIL) OR (LEN(mode.map^) # mode.src.pal.used)) THEN
  565. NEW(mode.map, mode.src.pal.used)
  566. END;
  567. SetRGB(mode.col, 255, 255, 255);
  568. (*
  569. mode.col := SYSTEM.VAL(Pixel, -1);
  570. *)
  571. mode.src.pack := NIL; mode.dst.pack := NIL (* force re-evaluation of transfer procedure *)
  572. END InitMode;
  573. (** initialize transfer mode with color components for pure alpha sources **)
  574. PROCEDURE InitModeColor* (VAR mode: Mode; op: SHORTINT; red, green, blue: LONGINT);
  575. BEGIN
  576. mode.op := op;
  577. IF (mode.src.pal # NIL) & ((mode.map = NIL) OR (LEN(mode.map^) # mode.src.pal.used)) THEN
  578. NEW(mode.map, mode.src.pal.used)
  579. END;
  580. SetRGB(mode.col, red, green, blue);
  581. mode.src.pack := NIL; mode.dst.pack := NIL
  582. END InitModeColor;
  583. (** set new source color for transfer mode **)
  584. PROCEDURE SetModeColor* (VAR mode: Mode; red, green, blue: LONGINT);
  585. BEGIN
  586. SetRGB(mode.col, red, green, blue);
  587. IF (mode.src.pal # NIL) & ((mode.map = NIL) OR (LEN(mode.map^) # mode.src.pal.used)) THEN
  588. NEW(mode.map, mode.src.pal.used)
  589. END;
  590. mode.src.pack := NIL; mode.dst.pack := NIL
  591. END SetModeColor;
  592. (** blend source pixel into destination pixel according to compositing operation **)
  593. PROCEDURE Blend* (op: LONGINT; VAR src, dst: Pixel);
  594. VAR fs, fd, i: LONGINT;
  595. BEGIN
  596. CASE op OF
  597. | clear: fs := 0; fd := 0
  598. | srcCopy: fs := 255; fd := 0
  599. | dstCopy: fs := 0; fd := 255
  600. | srcOverDst: fs := 255; fd := 255-ORD(src[a])
  601. | dstOverSrc: fs := 255-ORD(dst[a]); fd := 255
  602. | srcInDst: fs := ORD(dst[a]); fd := 0
  603. | dstInSrc: fs := 0; fd := ORD(src[a])
  604. | srcWithoutDst: fs := 255-ORD(dst[a]); fd := 0
  605. | dstWithoutSrc: fs := 0; fd := 255-ORD(src[a])
  606. | srcAtopDst: fs := ORD(dst[a]); fd := 255-ORD(src[a])
  607. | dstAtopSrc: fs := 255-ORD(dst[a]); fd := ORD(src[a])
  608. | srcXorDst: fs := 255-ORD(dst[a]); fd := 255-ORD(src[a])
  609. END;
  610. IF fs + fd = 0 THEN
  611. FOR i := 0 TO 3 DO dst[i] := 0X END
  612. ELSIF fs = 0 THEN
  613. IF fd # 255 THEN
  614. FOR i := 0 TO 3 DO
  615. dst[i] := Clamp[200H + fd * ORD(dst[i]) DIV 255]
  616. END
  617. END
  618. ELSIF fd = 0 THEN
  619. IF fs = 255 THEN
  620. dst := src
  621. ELSE
  622. FOR i := 0 TO 3 DO
  623. dst[i] := Clamp[200H + fs * ORD(src[i]) DIV 255]
  624. END
  625. END
  626. ELSE
  627. dst[0] := Clamp[200H + (fs * ORD(src[0]) + fd * ORD(dst[0])) DIV 255];
  628. dst[1] := Clamp[200H + (fs * ORD(src[1]) + fd * ORD(dst[1])) DIV 255];
  629. dst[2] := Clamp[200H + (fs * ORD(src[2]) + fd * ORD(dst[2])) DIV 255];
  630. dst[3] := Clamp[200H + (fs * ORD(src[3]) + fd * ORD(dst[3])) DIV 255]
  631. END
  632. END Blend;
  633. (*--- General Transfer ---*)
  634. PROCEDURE AnyBlendAny (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  635. VAR spix, dpix: Pixel;
  636. BEGIN
  637. WHILE len > 0 DO
  638. spix := mode.col; dpix := mode.col;
  639. mode.src.unpack(mode.src, sadr, sbit, spix);
  640. mode.dst.unpack(mode.dst, dadr, dbit, dpix);
  641. Blend(mode.op, spix, dpix);
  642. mode.dst.pack(mode.dst, dadr, dbit, dpix);
  643. sbit := sbit + mode.src.bpp; INC(sadr, sbit DIV 8); sbit := sbit MOD 8;
  644. dbit := dbit + mode.dst.bpp; INC(dadr, dbit DIV 8); dbit := dbit MOD 8;
  645. DEC(len)
  646. END
  647. END AnyBlendAny;
  648. (* --- invert --- *)
  649. PROCEDURE InvAny (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  650. BEGIN
  651. WHILE len > 0 DO
  652. mode.dst.unpack(mode.dst, dadr, dbit, mode.buf);
  653. mode.buf[r]:=CHR(255-ORD(mode.buf[r]));
  654. mode.buf[g]:=CHR(255-ORD(mode.buf[g]));
  655. mode.buf[b]:=CHR(255-ORD(mode.buf[b]));
  656. mode.dst.pack(mode.dst, dadr, dbit, mode.buf);
  657. sbit := sbit + mode.src.bpp; INC(sadr, sbit DIV 8); sbit := sbit MOD 8;
  658. dbit := dbit + mode.dst.bpp; INC(dadr, dbit DIV 8); dbit := dbit MOD 8;
  659. DEC(len)
  660. END
  661. END InvAny;
  662. (* --- alpha invert --- *)
  663. PROCEDURE InvOverAny (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  664. VAR pix:Pixel;
  665. BEGIN
  666. WHILE len > 0 DO
  667. mode.src.unpack(mode.src, sadr, sbit, pix);
  668. IF pix[a]>=80X THEN
  669. mode.dst.unpack(mode.dst, dadr, dbit, mode.buf);
  670. mode.buf[r]:=CHR(255-ORD(mode.buf[r]));
  671. mode.buf[g]:=CHR(255-ORD(mode.buf[g]));
  672. mode.buf[b]:=CHR(255-ORD(mode.buf[b]));
  673. mode.dst.pack(mode.dst, dadr, dbit, mode.buf)
  674. END;
  675. sbit := sbit + mode.src.bpp; INC(sadr, sbit DIV 8); sbit := sbit MOD 8;
  676. dbit := dbit + mode.dst.bpp; INC(dadr, dbit DIV 8); dbit := dbit MOD 8;
  677. DEC(len)
  678. END
  679. END InvOverAny;
  680. (*--- clear ---*)
  681. PROCEDURE ClearAny (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  682. VAR inc: LONGINT;
  683. BEGIN
  684. IF mode.dst.bpp MOD 8 = 0 THEN
  685. inc := mode.dst.bpp DIV 8;
  686. WHILE len > 0 DO
  687. mode.dst.pack(mode.dst, dadr, 0, Zero);
  688. INC(dadr, inc); DEC(len)
  689. END
  690. ELSE
  691. WHILE len > 0 DO
  692. mode.dst.pack(mode.dst, dadr, dbit, Zero);
  693. dbit := dbit + mode.dst.bpp; INC(dadr, dbit DIV 8); dbit := dbit MOD 8;
  694. DEC(len)
  695. END
  696. END
  697. END ClearAny;
  698. PROCEDURE Clear1 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  699. VAR out: CHAR;
  700. BEGIN
  701. IF (dbit > 0) OR (len < 8) THEN
  702. SYSTEM.GET(dadr, out);
  703. WHILE (dbit < 8) & (len > 0) DO
  704. out := Clr[ORD(out), dbit];
  705. INC(dbit); DEC(len)
  706. END;
  707. SYSTEM.PUT(dadr, out)
  708. END;
  709. WHILE len >= 32 DO
  710. SYSTEM.PUT(dadr, LONG(LONG(0))); INC(dadr, 4); DEC(len, 32)
  711. END;
  712. WHILE len >= 8 DO
  713. SYSTEM.PUT(dadr, 0X); INC(dadr); DEC(len, 8)
  714. END;
  715. IF len > 0 THEN
  716. SYSTEM.GET(dadr, out); dbit := 0;
  717. REPEAT
  718. out := Clr[ORD(out), dbit];
  719. INC(dbit); DEC(len)
  720. UNTIL len = 0;
  721. SYSTEM.PUT(dadr, out)
  722. END
  723. END Clear1;
  724. (*
  725. PROCEDURE ClearBytes (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  726. BEGIN
  727. len := len * mode.dst.bpp DIV 8;
  728. WHILE len >= 4 DO
  729. SYSTEM.PUT(dadr, LONG(LONG(0))); INC(dadr, 4); DEC(len)
  730. END;
  731. WHILE len > 0 DO
  732. SYSTEM.PUT(dadr, 0X); INC(dadr); DEC(len)
  733. END
  734. END ClearBytes;
  735. *)
  736. PROCEDURE ClearBytes (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  737. CODE {SYSTEM.i386}
  738. PUSH ECX
  739. MOV EDI, [EBP+dadr]
  740. MOV ECX, [EBP+len]
  741. MOV EAX, 0
  742. CLD
  743. REP STOSB
  744. POP ECX
  745. END ClearBytes;
  746. (* len is nr of DWords*)
  747. PROCEDURE Clear32 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  748. CODE {SYSTEM.i386}
  749. PUSH ECX
  750. MOV EDI, [EBP+dadr]
  751. MOV ECX, [EBP+len]
  752. MOV EAX, 0
  753. CLD
  754. REP STOSD
  755. POP ECX
  756. END Clear32;
  757. (*---- fill --------------*)
  758. PROCEDURE Fill8(destAdr: ADDRESS; size: SIZE; filler: LONGINT);
  759. CODE {SYSTEM.i386}
  760. PUSH ECX
  761. MOV EDI, [EBP+destAdr]
  762. MOV ECX, [EBP+size]
  763. MOV EAX, [EBP+filler]
  764. CLD
  765. REP STOSB
  766. POP ECX
  767. END Fill8;
  768. (* size in 16bit words*)
  769. PROCEDURE Fill16(destAdr: ADDRESS; size: SIZE; filler: LONGINT);
  770. CODE {SYSTEM.i386}
  771. PUSH ECX
  772. MOV EDI, [EBP+destAdr]
  773. MOV ECX, [EBP+size]
  774. MOV EAX, [EBP+filler]
  775. CLD
  776. REP STOSW
  777. POP ECX
  778. END Fill16;
  779. (* size in 24bit entities*)
  780. PROCEDURE Fill24(destAdr: ADDRESS; size: SIZE; filler: LONGINT);
  781. CODE {SYSTEM.i386}
  782. PUSH ECX
  783. MOV EDI, [EBP+destAdr]
  784. IMUL ECX, [EBP+size],3 ; because bytes are used below
  785. MOV EAX, [EBP+filler]
  786. CLD
  787. REP STOSB
  788. POP ECX
  789. END Fill24;
  790. (* size in DWords*)
  791. PROCEDURE Fill32(destAdr: ADDRESS; size: SIZE; filler: LONGINT); (*! to do: change interface, introduce in Blend()*)
  792. CODE {SYSTEM.i386}
  793. PUSH ECX
  794. MOV EDI, [EBP+destAdr]
  795. MOV ECX, [EBP+size]
  796. MOV EAX, [EBP+filler]
  797. CLD
  798. REP STOSD
  799. POP ECX
  800. END Fill32;
  801. (* len in DWords*)
  802. PROCEDURE Fill32A(VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT); (*! to do: change interface, introduce in Blend()*)
  803. CODE {SYSTEM.i386}
  804. PUSH ECX
  805. MOV EDI, [EBP+dadr]
  806. MOV ECX, [EBP+len]
  807. MOV EAX, [EBP+sadr]
  808. CLD
  809. REP STOSD
  810. POP ECX
  811. END Fill32A;
  812. (*--- srcCopy Transfer ---*)
  813. (* constant values *)
  814. PROCEDURE Set1 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  815. VAR out: CHAR;
  816. BEGIN
  817. IF (dbit > 0) OR (len < 8) THEN
  818. SYSTEM.GET(dadr, out);
  819. WHILE (dbit < 8) & (len > 0) DO
  820. out := Set[ORD(out), dbit];
  821. INC(dbit); DEC(len)
  822. END;
  823. SYSTEM.PUT(dadr, out)
  824. END;
  825. WHILE len >= 8 DO
  826. SYSTEM.PUT(dadr, 0FFX);
  827. INC(dadr); DEC(len, 8)
  828. END;
  829. IF len > 0 THEN
  830. SYSTEM.GET(dadr, out); dbit := 0;
  831. REPEAT
  832. out := Set[ORD(out), dbit];
  833. INC(dbit); DEC(len)
  834. UNTIL len = 0;
  835. SYSTEM.PUT(dadr, out)
  836. END
  837. END Set1;
  838. PROCEDURE ConstCopy8 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  839. BEGIN
  840. Fill8(dadr, len, ORD(mode.buf[0]))
  841. (*WHILE len > 0 DO SYSTEM.PUT(dadr, mode.buf[0]); INC(dadr); DEC(len) END*)
  842. END ConstCopy8;
  843. PROCEDURE ConstCopy16 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  844. BEGIN
  845. Fill16(dadr, len, ORD(mode.buf[0])+ASH(ORD(mode.buf[1]),8))
  846. (*WHILE len > 0 DO SYSTEM.MOVE(ADDRESSOF(mode.buf[0]), dadr, 2); INC(dadr, 2); DEC(len) END*)
  847. END ConstCopy16;
  848. PROCEDURE ConstCopy24 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  849. BEGIN
  850. Fill24(dadr, len, ORD(mode.buf[0])+ASH(ORD(mode.buf[1]),8)+ASH(ORD(mode.buf[2]),16));
  851. (*WHILE len > 0 DO SYSTEM.MOVE(ADDRESSOF(mode.buf[0]), dadr, 3); INC(dadr, 3); DEC(len) END*)
  852. END ConstCopy24;
  853. (* identical formats *)
  854. PROCEDURE Copy1 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  855. VAR in, out: CHAR;
  856. BEGIN
  857. SYSTEM.GET(sadr, in);
  858. WHILE (sbit = 0) & (dbit = 0) & (len >= 8) DO
  859. SYSTEM.PUT(dadr, in);
  860. INC(sadr); INC(dadr); DEC(len, 8);
  861. SYSTEM.GET(sadr, in)
  862. END;
  863. IF (dbit > 0) OR (len < 8) THEN
  864. SYSTEM.GET(dadr, out)
  865. END;
  866. WHILE len > 0 DO
  867. IF Bit[ORD(in), sbit] THEN out := Set[ORD(out), dbit]
  868. ELSE out := Clr[ORD(out), dbit]
  869. END;
  870. INC(sbit); INC(dbit); DEC(len);
  871. IF sbit = 8 THEN
  872. INC(sadr); sbit := 0;
  873. SYSTEM.GET(sadr, in)
  874. END;
  875. IF dbit = 8 THEN
  876. SYSTEM.PUT(dadr, out);
  877. INC(dadr); dbit := 0;
  878. IF len < 8 THEN
  879. SYSTEM.GET(dadr, out)
  880. END
  881. END
  882. END;
  883. IF dbit > 0 THEN
  884. SYSTEM.PUT(dadr, out)
  885. END
  886. END Copy1;
  887. PROCEDURE Copy8 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  888. BEGIN
  889. SYSTEM.MOVE(sadr, dadr, len)
  890. END Copy8;
  891. PROCEDURE I8CopyI8 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  892. VAR byte: CHAR;
  893. BEGIN
  894. WHILE len > 0 DO
  895. SYSTEM.GET(sadr, byte); SYSTEM.PUT(dadr, mode.map[ORD(byte)]);
  896. INC(sadr); INC(dadr); DEC(len)
  897. END
  898. END I8CopyI8;
  899. PROCEDURE Copy16 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  900. BEGIN
  901. SYSTEM.MOVE(sadr, dadr, 2*len)
  902. END Copy16;
  903. (*
  904. PROCEDURE Copy16(VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  905. CODE {SYSTEM.i386}
  906. PUSH ECX
  907. MOV ESI, [EBP+sadr]
  908. MOV EDI, [EBP+dadr]
  909. CLD
  910. MOV ECX, [EBP+len]
  911. REP MOVSW
  912. POP ECX
  913. END Copy16;
  914. *)
  915. PROCEDURE I16CopyI16 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  916. VAR val: INTEGER;
  917. BEGIN
  918. WHILE len > 0 DO
  919. val:=SYSTEM.GET16(sadr); SYSTEM.PUT16(dadr, mode.map[val MOD 10000H]);
  920. INC(sadr); INC(dadr); DEC(len)
  921. END
  922. END I16CopyI16;
  923. PROCEDURE Copy24 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  924. BEGIN
  925. SYSTEM.MOVE(sadr, dadr, 3*len)
  926. END Copy24;
  927. PROCEDURE Copy32 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  928. BEGIN
  929. SYSTEM.MOVE(sadr, dadr, 4*len)
  930. END Copy32;
  931. (* (*produces only slightly more compact assembler code as prior procedure*)
  932. PROCEDURE Copy32(VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  933. CODE {SYSTEM.i386}
  934. PUSH ECX
  935. MOV ESI, [EBP+sadr]
  936. MOV EDI, [EBP+dadr]
  937. CLD
  938. MOV ECX, [EBP+len]
  939. REP MOVSD
  940. POP ECX
  941. END Copy32;
  942. *)
  943. (* general methods *)
  944. PROCEDURE AnyCopyAny (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  945. VAR pix: Pixel;
  946. BEGIN
  947. WHILE len > 0 DO
  948. pix := mode.buf;
  949. mode.src.unpack(mode.src, sadr, sbit, mode.buf);
  950. mode.dst.pack(mode.dst, dadr, dbit, mode.buf);
  951. sbit := sbit + mode.src.bpp; INC(sadr, sbit DIV 8); sbit := sbit MOD 8;
  952. dbit := dbit + mode.dst.bpp; INC(dadr, dbit DIV 8); dbit := dbit MOD 8;
  953. DEC(len)
  954. END
  955. END AnyCopyAny;
  956. PROCEDURE AnyBytesCopyAnyBytes (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  957. VAR sinc, dinc: LONGINT; pix: Pixel;
  958. BEGIN
  959. sinc := mode.src.bpp DIV 8; dinc := mode.dst.bpp DIV 8;
  960. WHILE len > 0 DO
  961. pix := mode.buf;
  962. mode.src.unpack(mode.src, sadr, sbit, mode.buf);
  963. mode.dst.pack(mode.dst, dadr, dbit, mode.buf);
  964. INC(sadr, sinc); INC(dadr, dinc); DEC(len)
  965. END
  966. END AnyBytesCopyAnyBytes;
  967. (* A1 *)
  968. PROCEDURE AnyCopyA1 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  969. VAR out: CHAR; pix: Pixel;
  970. BEGIN
  971. SYSTEM.GET(dadr, out); pix[a] := 0FFX;
  972. WHILE len > 0 DO
  973. mode.src.unpack(mode.src, sadr, sbit, pix);
  974. sbit := sbit + mode.src.bpp; INC(sadr, sbit MOD 8); sbit := sbit MOD 8;
  975. IF pix[a] >= 80X THEN out := Set[ORD(out), dbit]
  976. ELSE out := Clr[ORD(out), dbit]
  977. END;
  978. INC(dbit); DEC(len);
  979. IF dbit = 8 THEN
  980. SYSTEM.PUT(dadr, out); INC(dadr); SYSTEM.GET(dadr, out); dbit := 0
  981. END
  982. END;
  983. SYSTEM.PUT(dadr, out)
  984. END AnyCopyA1;
  985. PROCEDURE A8CopyA1 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  986. VAR out, in: CHAR;
  987. BEGIN
  988. IF (dbit > 0) OR (len < 8) THEN
  989. SYSTEM.GET(dadr, out)
  990. END;
  991. WHILE len > 0 DO
  992. SYSTEM.GET(sadr, in);
  993. IF in >= 80X THEN out := Set[ORD(out), dbit]
  994. ELSE out := Clr[ORD(out), dbit]
  995. END;
  996. INC(sadr); INC(dbit); DEC(len);
  997. IF dbit = 8 THEN
  998. SYSTEM.PUT(dadr, out);
  999. INC(dadr); dbit := 0;
  1000. IF len < 8 THEN
  1001. SYSTEM.GET(dadr, out)
  1002. END
  1003. END
  1004. END;
  1005. IF dbit > 0 THEN
  1006. SYSTEM.PUT(dadr, out)
  1007. END
  1008. END A8CopyA1;
  1009. PROCEDURE BGRA8888CopyA1 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1010. VAR out, in: CHAR;
  1011. BEGIN
  1012. INC(sadr, a); (* only look at alpha component *)
  1013. IF (dbit > 0) OR (len < 8) THEN
  1014. SYSTEM.GET(dadr, out)
  1015. END;
  1016. WHILE len > 0 DO
  1017. SYSTEM.GET(sadr, in);
  1018. IF in >= 80X THEN out := Set[ORD(out), dbit]
  1019. ELSE out := Clr[ORD(out), dbit]
  1020. END;
  1021. INC(sadr, 4); INC(dbit); DEC(len);
  1022. IF dbit = 8 THEN
  1023. SYSTEM.PUT(dadr, out);
  1024. INC(dadr); dbit := 0;
  1025. IF len < 8 THEN
  1026. SYSTEM.GET(dadr, out)
  1027. END
  1028. END
  1029. END;
  1030. IF dbit > 0 THEN
  1031. SYSTEM.PUT(dadr, out)
  1032. END
  1033. END BGRA8888CopyA1;
  1034. PROCEDURE A1CopyAny (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1035. VAR in: CHAR;
  1036. BEGIN
  1037. SYSTEM.GET(sadr, in);
  1038. WHILE len > 0 DO
  1039. IF Bit[ORD(in), sbit] THEN mode.dst.pack(mode.dst, dadr, dbit, mode.buf)
  1040. ELSE mode.dst.pack(mode.dst, dadr, dbit, Zero)
  1041. END;
  1042. INC(sbit); dbit := dbit + mode.dst.bpp; INC(dadr, dbit DIV 8); dbit := dbit MOD 8; DEC(len);
  1043. IF sbit = 8 THEN
  1044. INC(sadr); sbit := 0;
  1045. SYSTEM.GET(sadr, in)
  1046. END
  1047. END
  1048. END A1CopyAny;
  1049. PROCEDURE A1CopyA8 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1050. VAR in: CHAR;
  1051. BEGIN
  1052. SYSTEM.GET(sadr, in);
  1053. WHILE len > 0 DO
  1054. IF Bit[ORD(in), sbit] THEN SYSTEM.PUT(dadr, 0FFX)
  1055. ELSE SYSTEM.PUT(dadr, 0X)
  1056. END;
  1057. INC(sbit); INC(dadr); DEC(len);
  1058. IF sbit = 8 THEN
  1059. INC(sadr); sbit := 0;
  1060. SYSTEM.GET(sadr, in)
  1061. END
  1062. END
  1063. END A1CopyA8;
  1064. PROCEDURE A1CopyBGRA8888 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1065. VAR pix: Pixel; in: CHAR;
  1066. BEGIN
  1067. pix := mode.buf;
  1068. SYSTEM.GET(sadr, in);
  1069. WHILE len > 0 DO
  1070. IF Bit[ORD(in), sbit] THEN pix[a] := 0FFX
  1071. ELSE pix[a] := 0X
  1072. END;
  1073. SYSTEM.MOVE(ADDRESSOF(pix), dadr, 4);
  1074. INC(sbit); INC(dadr, 4); DEC(len);
  1075. IF sbit = 8 THEN
  1076. INC(sadr); sbit := 0;
  1077. SYSTEM.GET(sadr, in)
  1078. END
  1079. END
  1080. END A1CopyBGRA8888;
  1081. (* A8 *)
  1082. PROCEDURE AnyCopyA8 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1083. VAR pix: Pixel;
  1084. BEGIN
  1085. pix[a] := 0FFX;
  1086. WHILE len > 0 DO
  1087. mode.src.unpack(mode.src, sadr, sbit, pix);
  1088. SYSTEM.PUT(dadr, pix[a]);
  1089. INC(dadr); sbit := sbit + mode.src.bpp; INC(sadr, sbit DIV 8); sbit := sbit MOD 8; DEC(len)
  1090. END
  1091. END AnyCopyA8;
  1092. PROCEDURE BGRA8888CopyA8 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1093. VAR byte: CHAR;
  1094. BEGIN
  1095. INC(sadr, 3);
  1096. WHILE len > 0 DO
  1097. SYSTEM.GET(sadr, byte);
  1098. SYSTEM.PUT(dadr, byte);
  1099. INC(sadr, 4); INC(dadr); DEC(len)
  1100. END
  1101. END BGRA8888CopyA8;
  1102. PROCEDURE A8CopyBGRA8888 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1103. VAR pix: Pixel;
  1104. BEGIN
  1105. pix := mode.buf;
  1106. WHILE len > 0 DO
  1107. SYSTEM.GET(sadr, pix[a]);
  1108. SYSTEM.MOVE(ADDRESSOF(pix), dadr, 4);
  1109. INC(sadr); INC(dadr, 4); DEC(len)
  1110. END
  1111. END A8CopyBGRA8888;
  1112. (* P8 *)
  1113. PROCEDURE AnyCopyP8 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1114. VAR pix: Pixel;
  1115. BEGIN
  1116. WHILE len > 0 DO
  1117. pix := mode.buf;
  1118. mode.src.unpack(mode.src, sadr, sbit, pix);
  1119. SYSTEM.PUT(dadr, CHR(CLUTs.Match(mode.dst.pal.clut, ORD(pix[b]) + ASH(ORD(pix[g]), 8) + ASH(ORD(pix[r]), 16))));
  1120. INC(dadr); sbit := sbit + mode.src.bpp; INC(sadr, sbit DIV 8); sbit := sbit MOD 8; DEC(len)
  1121. END
  1122. END AnyCopyP8;
  1123. PROCEDURE Any16CopyP8 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1124. VAR pix: Pixel;
  1125. BEGIN
  1126. WHILE len > 0 DO
  1127. mode.src.unpack(mode.src, sadr, 0, pix);
  1128. SYSTEM.PUT(dadr, CHR(CLUTs.Match(mode.dst.pal.clut, ORD(pix[b]) + ASH(ORD(pix[g]), 8) + ASH(ORD(pix[r]), 16))));
  1129. INC(sadr, 2); INC(dadr); DEC(len)
  1130. END
  1131. END Any16CopyP8;
  1132. PROCEDURE BGR888CopyP8 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1133. VAR pix: Pixel;
  1134. BEGIN
  1135. WHILE len > 0 DO
  1136. SYSTEM.MOVE(sadr, ADDRESSOF(pix[0]), 3);
  1137. SYSTEM.PUT(dadr, CHR(CLUTs.Match(mode.dst.pal.clut, ORD(pix[b]) + ASH(ORD(pix[g]), 8) + ASH(ORD(pix[r]), 16))));
  1138. INC(sadr, 3); INC(dadr); DEC(len)
  1139. END
  1140. END BGR888CopyP8;
  1141. PROCEDURE BGRA8888CopyP8 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1142. VAR pix: Pixel;
  1143. BEGIN
  1144. WHILE len > 0 DO
  1145. SYSTEM.MOVE(sadr, ADDRESSOF(pix[0]), 4);
  1146. SYSTEM.PUT(dadr, CHR(CLUTs.Match(mode.dst.pal.clut, ORD(pix[b]) + ASH(ORD(pix[g]), 8) + ASH(ORD(pix[r]), 16))));
  1147. INC(sadr, 4); INC(dadr); DEC(len)
  1148. END
  1149. END BGRA8888CopyP8;
  1150. PROCEDURE P8CopyAny (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1151. VAR b: CHAR;
  1152. BEGIN
  1153. WHILE len > 0 DO
  1154. SYSTEM.GET(sadr, b);
  1155. mode.dst.pack(mode.dst, dadr, dbit, mode.src.pal.col[ORD(b)]);
  1156. INC(sadr); dbit := dbit + mode.dst.bpp; INC(dadr, dbit DIV 8); dbit := dbit MOD 8; DEC(len)
  1157. END
  1158. END P8CopyAny;
  1159. PROCEDURE P8CopyAny16 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1160. VAR b: CHAR;
  1161. BEGIN
  1162. WHILE len > 0 DO
  1163. SYSTEM.GET(sadr, b);
  1164. mode.dst.pack(mode.dst, dadr, 0, mode.src.pal.col[ORD(b)]);
  1165. INC(sadr); INC(dadr, 2); DEC(len)
  1166. END
  1167. END P8CopyAny16;
  1168. PROCEDURE P8CopyBGR888 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1169. VAR b: CHAR;
  1170. BEGIN
  1171. WHILE len > 0 DO
  1172. SYSTEM.GET(sadr, b);
  1173. SYSTEM.MOVE(ADDRESSOF(mode.src.pal.col[ORD(b)]), dadr, 3);
  1174. INC(sadr); INC(dadr, 3); DEC(len)
  1175. END
  1176. END P8CopyBGR888;
  1177. PROCEDURE P8CopyBGRA8888 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1178. VAR b: CHAR;
  1179. BEGIN
  1180. WHILE len > 0 DO
  1181. SYSTEM.GET(sadr, b);
  1182. SYSTEM.MOVE(ADDRESSOF(mode.src.pal.col[ORD(b)]), dadr, 4);
  1183. INC(sadr); INC(dadr, 4); DEC(len)
  1184. END
  1185. END P8CopyBGRA8888;
  1186. (* D8 *)
  1187. PROCEDURE AnyCopyD8 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1188. VAR pix: Pixel;
  1189. BEGIN
  1190. WHILE len > 0 DO
  1191. pix := mode.buf;
  1192. mode.src.unpack(mode.src, sadr, sbit, pix);
  1193. SYSTEM.PUT(dadr, CHR(ColorToIndex(ORD(pix[b]) + ASH(ORD(pix[g]), 8) + ASH(ORD(pix[r]), 16))));
  1194. INC(dadr); sbit := sbit + mode.src.bpp; INC(sadr, sbit DIV 8); sbit := sbit MOD 8; DEC(len)
  1195. END
  1196. END AnyCopyD8;
  1197. PROCEDURE Any16CopyD8 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1198. VAR pix: Pixel;
  1199. BEGIN
  1200. WHILE len > 0 DO
  1201. mode.src.unpack(mode.src, sadr, 0, pix);
  1202. SYSTEM.PUT(dadr, CHR(ColorToIndex(ORD(pix[b]) + ASH(ORD(pix[g]), 8) + ASH(ORD(pix[r]), 16))));
  1203. INC(sadr, 2); INC(dadr); DEC(len)
  1204. END
  1205. END Any16CopyD8;
  1206. PROCEDURE BGR888CopyD8 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1207. VAR pix: Pixel;
  1208. BEGIN
  1209. WHILE len > 0 DO
  1210. SYSTEM.MOVE(sadr, ADDRESSOF(pix[0]), 3);
  1211. SYSTEM.PUT(dadr, CHR(ColorToIndex(ORD(pix[b]) + ASH(ORD(pix[g]), 8) + ASH(ORD(pix[r]), 16))));
  1212. INC(sadr, 3); INC(dadr); DEC(len)
  1213. END
  1214. END BGR888CopyD8;
  1215. PROCEDURE BGRA8888CopyD8 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1216. VAR pix: Pixel;
  1217. BEGIN
  1218. WHILE len > 0 DO
  1219. SYSTEM.MOVE(sadr, ADDRESSOF(pix[0]), 4);
  1220. SYSTEM.PUT(dadr, CHR(ColorToIndex(ORD(pix[b]) + ASH(ORD(pix[g]), 8) + ASH(ORD(pix[r]), 16))));
  1221. INC(sadr, 4); INC(dadr); DEC(len)
  1222. END
  1223. END BGRA8888CopyD8;
  1224. PROCEDURE D8CopyAny (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1225. VAR pix: Pixel; byte: CHAR; col: LONGINT;
  1226. BEGIN
  1227. pix[a] := 0FFX;
  1228. WHILE len > 0 DO
  1229. SYSTEM.GET(sadr, byte); col := IndexToColor(ORD(byte));
  1230. pix[b] := CHR(col MOD 100H); pix[g] := CHR(ASH(col, -8) MOD 100H); pix[r] := CHR(ASH(col, -16) MOD 100H);
  1231. mode.dst.pack(mode.dst, dadr, dbit, pix);
  1232. INC(sadr); dbit := dbit + mode.dst.bpp; INC(dadr, dbit DIV 8); dbit := dbit MOD 8; DEC(len)
  1233. END
  1234. END D8CopyAny;
  1235. PROCEDURE D8CopyAny16 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1236. VAR pix: Pixel; byte: CHAR; col: LONGINT;
  1237. BEGIN
  1238. pix[a] := 0FFX;
  1239. WHILE len > 0 DO
  1240. SYSTEM.GET(sadr, byte); col := IndexToColor(ORD(byte));
  1241. pix[b] := CHR(col MOD 100H); pix[g] := CHR(ASH(col, -8) MOD 100H); pix[r] := CHR(ASH(col, -16) MOD 100H);
  1242. mode.dst.pack(mode.dst, dadr, 0, pix);
  1243. INC(sadr); INC(dadr, 2); DEC(len)
  1244. END
  1245. END D8CopyAny16;
  1246. PROCEDURE D8CopyBGR888 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1247. VAR byte: CHAR; col: LONGINT; pix: Pixel;
  1248. BEGIN
  1249. WHILE len > 0 DO
  1250. SYSTEM.GET(sadr, byte); col := IndexToColor(ORD(byte));
  1251. pix[b] := CHR(col MOD 100H); pix[g] := CHR(ASH(col, -8) MOD 100H); pix[r] := CHR(ASH(col, -16) MOD 100H);
  1252. SYSTEM.MOVE(ADDRESSOF(pix[0]), dadr, 3);
  1253. INC(sadr); INC(dadr, 3); DEC(len)
  1254. END
  1255. END D8CopyBGR888;
  1256. PROCEDURE D8CopyBGRA8888 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1257. VAR pix: Pixel; byte: CHAR; col: LONGINT;
  1258. BEGIN
  1259. pix[a] := 0FFX;
  1260. WHILE len > 0 DO
  1261. SYSTEM.GET(sadr, byte); col := IndexToColor(ORD(byte));
  1262. pix[b] := CHR(col MOD 100H); pix[g] := CHR(ASH(col, -8) MOD 100H); pix[r] := CHR(ASH(col, -16) MOD 100H);
  1263. SYSTEM.MOVE(ADDRESSOF(pix[0]), dadr, 4);
  1264. INC(sadr); INC(dadr, 4); DEC(len)
  1265. END
  1266. END D8CopyBGRA8888;
  1267. (*
  1268. (* P816*)
  1269. PROCEDURE AnyCopyP16 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1270. VAR pix: Pixel;
  1271. BEGIN
  1272. WHILE len > 0 DO
  1273. pix := mode.buf;
  1274. mode.src.unpack(mode.src, sadr, sbit, pix);
  1275. SYSTEM.PUT16(dadr, PaletteIndex(mode.dst.pal, ORD(pix[r]), ORD(pix[g]), ORD(pix[b])));
  1276. INC(dadr,2); sbit := sbit + mode.src.bpp; INC(sadr, sbit DIV 8); sbit := sbit MOD 8; DEC(len)
  1277. END
  1278. END AnyCopyP16;
  1279. PROCEDURE Any16CopyP16 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1280. VAR pix: Pixel;
  1281. BEGIN
  1282. WHILE len > 0 DO
  1283. mode.src.unpack(mode.src, sadr, 0, pix);
  1284. SYSTEM.PUT16(dadr, PaletteIndex(mode.dst.pal, ORD(pix[r]), ORD(pix[g]), ORD(pix[b])));
  1285. INC(sadr, 2); INC(dadr,2); DEC(len)
  1286. END
  1287. END Any16CopyP16;
  1288. PROCEDURE BGR888CopyP16 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1289. VAR pix: Pixel;
  1290. BEGIN
  1291. WHILE len > 0 DO
  1292. SYSTEM.MOVE(sadr, ADDRESSOF(pix[0]), 3);
  1293. SYSTEM.PUT16(dadr, PaletteIndex(mode.dst.pal, ORD(pix[r]), ORD(pix[g]), ORD(pix[b])));
  1294. INC(sadr, 3); INC(dadr,2); DEC(len)
  1295. END
  1296. END BGR888CopyP16;
  1297. PROCEDURE BGRA8888CopyP16 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1298. VAR pix: Pixel;
  1299. BEGIN
  1300. WHILE len > 0 DO
  1301. SYSTEM.MOVE(sadr, ADDRESSOF(pix[0]), 4);
  1302. SYSTEM.PUT16(dadr, PaletteIndex(mode.dst.pal, ORD(pix[r]), ORD(pix[g]), ORD(pix[b])));
  1303. INC(sadr, 4); INC(dadr,2); DEC(len)
  1304. END
  1305. END BGRA8888CopyP16;
  1306. PROCEDURE P16CopyAny (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1307. BEGIN
  1308. WHILE len > 0 DO
  1309. mode.dst.pack(mode.dst, dadr, dbit, mode.src.pal.col[LONG(SYSTEM.GET16(sadr)) MOD 10000H]);
  1310. INC(sadr,2); dbit := dbit + mode.dst.bpp; INC(dadr, dbit DIV 8); dbit := dbit MOD 8; DEC(len)
  1311. END
  1312. END P16CopyAny;
  1313. PROCEDURE P16CopyAny16 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1314. BEGIN
  1315. WHILE len > 0 DO
  1316. mode.dst.pack(mode.dst, dadr, 0, mode.src.pal.col[LONG(SYSTEM.GET16(sadr)) MOD 10000H]);
  1317. INC(sadr,2); INC(dadr, 2); DEC(len)
  1318. END
  1319. END P16CopyAny16;
  1320. *)
  1321. PROCEDURE P16CopyBGR888 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1322. BEGIN
  1323. WHILE len > 0 DO
  1324. SYSTEM.MOVE(ADDRESSOF(mode.src.pal.col[LONG(SYSTEM.GET16(sadr)) MOD 10000H]), dadr, 3);
  1325. INC(sadr,2); INC(dadr, 3); DEC(len)
  1326. END
  1327. END P16CopyBGR888;
  1328. PROCEDURE P16CopyBGRA8888 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1329. VAR val:LONGINT;
  1330. BEGIN
  1331. WHILE len > 0 DO
  1332. val:=LONG(SYSTEM.GET16(sadr)) MOD 10000H;
  1333. SYSTEM.MOVE(ADDRESSOF(mode.src.pal.col[val]), dadr, 4);
  1334. INC(sadr,2); INC(dadr, 4); DEC(len)
  1335. END
  1336. END P16CopyBGRA8888;
  1337. (* BGR555, BGR565, BGR466 *)
  1338. PROCEDURE AnyCopyAny16 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1339. VAR pix: Pixel;
  1340. BEGIN
  1341. WHILE len > 0 DO
  1342. pix := mode.buf;
  1343. mode.src.unpack(mode.src, sadr, 0, pix);
  1344. mode.dst.pack(mode.dst, dadr, 0, pix);
  1345. INC(dadr, 2); sbit := sbit + mode.src.bpp; INC(sadr, sbit DIV 8); sbit := sbit MOD 8; DEC(len)
  1346. END
  1347. END AnyCopyAny16;
  1348. PROCEDURE Any16CopyAny16 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1349. VAR pix: Pixel;
  1350. BEGIN
  1351. WHILE len > 0 DO
  1352. mode.src.unpack(mode.src, sadr, 0, pix);
  1353. mode.dst.pack(mode.dst, dadr, 0, pix);
  1354. INC(sadr, 2); INC(dadr, 2); DEC(len)
  1355. END
  1356. END Any16CopyAny16;
  1357. PROCEDURE BGR888CopyAny16 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1358. VAR pix: Pixel;
  1359. BEGIN
  1360. pix[a] := 0FFX;
  1361. WHILE len > 0 DO
  1362. SYSTEM.MOVE(sadr, ADDRESSOF(pix[0]), 3);
  1363. mode.dst.pack(mode.dst, dadr, 0, pix);
  1364. INC(sadr, 3); INC(dadr, 2); DEC(len)
  1365. END
  1366. END BGR888CopyAny16;
  1367. PROCEDURE BGRA8888CopyAny16 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1368. VAR pix: Pixel;
  1369. BEGIN
  1370. WHILE len > 0 DO
  1371. SYSTEM.MOVE(sadr, ADDRESSOF(pix[0]), 4);
  1372. mode.dst.pack(mode.dst, dadr, 0, pix);
  1373. INC(dadr, 2); sbit := sbit + mode.src.bpp; INC(sadr, sbit DIV 8); sbit := sbit MOD 8; DEC(len)
  1374. END
  1375. END BGRA8888CopyAny16;
  1376. PROCEDURE Any16CopyAny (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1377. VAR pix: Pixel;
  1378. BEGIN
  1379. WHILE len > 0 DO
  1380. mode.src.unpack(mode.src, sadr, 0, pix);
  1381. mode.dst.pack(mode.dst, dadr, 0, pix);
  1382. INC(sadr, 2); dbit := dbit + mode.dst.bpp; INC(dadr, dbit DIV 8); dbit := dbit MOD 8; DEC(len)
  1383. END
  1384. END Any16CopyAny;
  1385. PROCEDURE Any16CopyBGR888 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1386. VAR pix: Pixel;
  1387. BEGIN
  1388. WHILE len > 0 DO
  1389. mode.src.unpack(mode.src, sadr, 0, pix);
  1390. SYSTEM.MOVE(ADDRESSOF(pix[0]), dadr, 3);
  1391. INC(sadr, 2); INC(dadr, 3); DEC(len)
  1392. END
  1393. END Any16CopyBGR888;
  1394. PROCEDURE Any16CopyBGRA8888 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1395. VAR pix: Pixel;
  1396. BEGIN
  1397. WHILE len > 0 DO
  1398. mode.src.unpack(mode.src, sadr, 0, pix);
  1399. SYSTEM.MOVE(ADDRESSOF(pix[0]), dadr, 4);
  1400. INC(sadr, 2); INC(dadr, 4); DEC(len)
  1401. END
  1402. END Any16CopyBGRA8888;
  1403. (* BGR888 *)
  1404. PROCEDURE AnyCopyBGR888 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1405. VAR pix: Pixel;
  1406. BEGIN
  1407. WHILE len > 0 DO
  1408. pix := mode.buf;
  1409. mode.src.unpack(mode.src, sadr, sbit, pix);
  1410. SYSTEM.MOVE(ADDRESSOF(pix[0]), dadr, 3);
  1411. INC(dadr, 3); sbit := sbit + mode.src.bpp; INC(sadr, sbit DIV 8); sbit := sbit MOD 8; DEC(len)
  1412. END
  1413. END AnyCopyBGR888;
  1414. PROCEDURE BGRA8888CopyBGR888 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1415. BEGIN
  1416. WHILE len > 0 DO
  1417. SYSTEM.MOVE(sadr, dadr, 3);
  1418. INC(sadr, 4); INC(dadr, 3); DEC(len)
  1419. END
  1420. END BGRA8888CopyBGR888;
  1421. PROCEDURE SSE2BGRA8888CopyBGR888 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1422. CODE {SYSTEM.i386, SYSTEM.MMX, SYSTEM.SSE, SYSTEM.SSE2, SYSTEM.Pentium}
  1423. PUSHFD
  1424. PUSH ECX
  1425. PUSH EBX
  1426. ; CLI
  1427. MOV ESI, [EBP+sadr] ; source adr
  1428. MOV EDI, [EBP+dadr] ; source adr
  1429. MOV ECX, [EBP+len]
  1430. loop:
  1431. CMP ECX, 0
  1432. JLE end
  1433. CMP ECX, 4
  1434. JL singlepixel
  1435. fourpixel:
  1436. ; 4pixels at the time
  1437. MOV EAX, [ESI] ; pixel 0
  1438. MOV EBX, [ESI+4] ; pixel 1
  1439. AND EAX, 0FFFFFFH
  1440. AND EBX, 0FFFFFFH
  1441. MOV EDX, EBX
  1442. SHL EDX, 24
  1443. OR EAX, EDX ; 1000
  1444. MOV [EDI], EAX ; write back to mem
  1445. MOV EAX, [ESI+8] ; pixel 2
  1446. AND EAX, 0FFFFFFH
  1447. SHR EBX,8
  1448. MOV EDX, EAX
  1449. SHL EDX, 16
  1450. OR EBX, EDX ; 2211
  1451. MOV [EDI+4], EBX
  1452. MOV EDX, [ESI+12] ; pixel 3
  1453. SHL EDX, 8
  1454. SHR EAX, 16
  1455. OR EAX, EDX ; 3332
  1456. MOV [EDI], EAX
  1457. ADD ESI, 16
  1458. ADD EDI, 12
  1459. SUB ECX, 4
  1460. JG loop
  1461. JMP end
  1462. singlepixel:
  1463. MOV EAX, [ESI]
  1464. MOV [EDI], AX
  1465. SHR EAX, 16
  1466. MOV [EDI+2], AL
  1467. ADD ESI, 4
  1468. ADD EDI, 3
  1469. SUB ECX, 1
  1470. JG loop
  1471. end:
  1472. EMMS ; declare FPU registers free
  1473. POP EBX
  1474. POP ECX
  1475. POPFD
  1476. END SSE2BGRA8888CopyBGR888;
  1477. PROCEDURE BGR888CopyAny (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1478. VAR pix: Pixel;
  1479. BEGIN
  1480. pix[a] := 0FFX;
  1481. WHILE len > 0 DO
  1482. SYSTEM.MOVE(sadr, ADDRESSOF(pix[0]), 3);
  1483. mode.dst.pack(mode.dst, dadr, dbit, pix);
  1484. INC(sadr, 3); dbit := dbit + mode.dst.bpp; INC(dadr, dbit DIV 8); dbit := dbit MOD 8; DEC(len)
  1485. END
  1486. END BGR888CopyAny;
  1487. PROCEDURE BGR888CopyBGRA8888(VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1488. BEGIN
  1489. WHILE len > 0 DO
  1490. SYSTEM.MOVE(sadr, dadr, 3); SYSTEM.PUT(dadr+3, 0FFX);
  1491. INC(sadr, 3); INC(dadr, 4); DEC(len)
  1492. END
  1493. END BGR888CopyBGRA8888;
  1494. PROCEDURE SSE2BGR888CopyBGRA8888(VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1495. CODE {SYSTEM.i386, SYSTEM.MMX, SYSTEM.SSE, SYSTEM.SSE2,SYSTEM.Pentium}
  1496. PUSHFD
  1497. PUSH ECX
  1498. PUSH EBX
  1499. ; CLI
  1500. PXOR XMM0, XMM0
  1501. MOV EAX, 0FF00H
  1502. PINSRW XMM0, EAX, 1
  1503. PINSRW XMM0, EAX, 3
  1504. PINSRW XMM0, EAX, 5
  1505. PINSRW XMM0, EAX, 7 ; prepare for fourpixel
  1506. SHL EAX, 16 ; prepare for singlepixel
  1507. MOV ESI, [EBP+sadr] ; source adr
  1508. MOV EDI, [EBP+dadr] ; source adr
  1509. MOV ECX, [EBP+len]
  1510. loop:
  1511. CMP ECX, 0
  1512. JLE end
  1513. CMP ECX, 4
  1514. JL singlepixel
  1515. fourpixel:
  1516. ; 4pixels at the time
  1517. PXOR XMM2,XMM2
  1518. PXOR XMM1,XMM1
  1519. MOV EBX, [ESI+9] ; read 1st source pixel
  1520. MOVD XMM2, EBX
  1521. PSLLDQ XMM2, 4
  1522. MOV EBX, [ESI+6] ; read 2nd source pixel
  1523. MOVD XMM1, EBX
  1524. POR XMM2, XMM1
  1525. PSLLDQ XMM2, 4
  1526. MOV EBX, [ESI+3] ; read 3rd source pixel
  1527. MOVD XMM1, EBX
  1528. POR XMM2, XMM1
  1529. PSLLDQ XMM2, 4
  1530. MOV EBX, [ESI] ; read 4th source pixel
  1531. MOVD XMM1, EBX
  1532. POR XMM2, XMM1
  1533. ADD ESI, 12
  1534. POR XMM2, XMM0
  1535. MOVDQU [EDI], XMM2 ; set the pixels
  1536. ADD EDI, 16 ; inc adr
  1537. SUB ECX, 4
  1538. JG loop
  1539. JMP end
  1540. singlepixel:
  1541. MOV EBX, [ESI] ; read source pixel
  1542. OR EBX, EAX
  1543. ADD ESI, 3
  1544. MOV [EDI], EBX
  1545. ADD EDI, 4 ; inc adr
  1546. SUB ECX, 1
  1547. JG loop
  1548. end:
  1549. EMMS ; declare FPU registers free
  1550. POP EBX
  1551. POP ECX
  1552. POPFD
  1553. END SSE2BGR888CopyBGRA8888;
  1554. (* BGRA8888 *)
  1555. PROCEDURE AnyCopyBGRA8888 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1556. VAR pix: Pixel;
  1557. BEGIN
  1558. WHILE len > 0 DO
  1559. pix := mode.buf;
  1560. mode.src.unpack(mode.src, sadr, sbit, pix);
  1561. SYSTEM.MOVE(ADDRESSOF(pix[0]), dadr, 4);
  1562. INC(dadr, 4); sbit := sbit + mode.src.bpp; INC(sadr, sbit DIV 8); sbit := sbit MOD 8; DEC(len)
  1563. END
  1564. END AnyCopyBGRA8888;
  1565. PROCEDURE BGRA8888CopyAny (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1566. VAR pix: Pixel;
  1567. BEGIN
  1568. WHILE len > 0 DO
  1569. SYSTEM.MOVE(sadr, ADDRESSOF(pix[0]), 4);
  1570. mode.dst.pack(mode.dst, dadr, dbit, pix);
  1571. INC(sadr, 4); dbit := dbit + mode.dst.bpp; INC(dadr, dbit DIV 8); dbit := dbit MOD 8; DEC(len)
  1572. END
  1573. END BGRA8888CopyAny;
  1574. (*--- dstCopy Transfer ---*)
  1575. PROCEDURE EmptyTransfer (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1576. END EmptyTransfer;
  1577. (*--- srcOverDst Transfer ---*)
  1578. (* A1 *)
  1579. PROCEDURE AnyOverA1 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1580. VAR out: CHAR; pix: Pixel;
  1581. BEGIN
  1582. SYSTEM.GET(dadr, out);
  1583. WHILE len > 0 DO
  1584. mode.src.unpack(mode.src, sadr, sbit, pix);
  1585. IF pix[a] >= 80X THEN
  1586. out := Set[ORD(out), dbit]
  1587. END;
  1588. sbit := sbit + mode.src.bpp; INC(sadr, sbit DIV 8); sbit := sbit MOD 8; INC(dbit); DEC(len);
  1589. IF dbit = 8 THEN
  1590. SYSTEM.PUT(dadr, out);
  1591. INC(dadr); dbit := 0;
  1592. SYSTEM.GET(dadr, out)
  1593. END
  1594. END;
  1595. SYSTEM.PUT(dadr, out)
  1596. END AnyOverA1;
  1597. PROCEDURE A1OverA1 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1598. VAR in, out: CHAR;
  1599. BEGIN
  1600. SYSTEM.GET(sadr, in); SYSTEM.GET(dadr, out);
  1601. WHILE len > 0 DO
  1602. IF Bit[ORD(in), sbit] THEN
  1603. out := Set[ORD(out), dbit]
  1604. END;
  1605. INC(sbit); INC(dbit); DEC(len);
  1606. IF sbit = 8 THEN
  1607. INC(sadr); sbit := 0;
  1608. SYSTEM.GET(sadr, in)
  1609. END;
  1610. IF dbit = 8 THEN
  1611. SYSTEM.PUT(dadr, out);
  1612. INC(dadr); dbit := 0;
  1613. SYSTEM.GET(dadr, out)
  1614. END
  1615. END;
  1616. SYSTEM.PUT(dadr, out)
  1617. END A1OverA1;
  1618. PROCEDURE A8OverA1 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1619. VAR in, out: CHAR;
  1620. BEGIN
  1621. SYSTEM.GET(dadr, out);
  1622. WHILE len > 0 DO
  1623. SYSTEM.GET(sadr, in);
  1624. IF in >= 80X THEN
  1625. out := Set[ORD(out), dbit]
  1626. END;
  1627. INC(sadr); INC(dbit); DEC(len);
  1628. IF dbit = 8 THEN
  1629. SYSTEM.PUT(dadr, out);
  1630. INC(dadr); dbit := 0;
  1631. SYSTEM.GET(dadr, out)
  1632. END
  1633. END;
  1634. SYSTEM.PUT(dadr, out)
  1635. END A8OverA1;
  1636. PROCEDURE BGRA8888OverA1 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1637. VAR in, out: CHAR;
  1638. BEGIN
  1639. SYSTEM.GET(dadr, out);
  1640. WHILE len > 0 DO
  1641. SYSTEM.GET(sadr + a, in);
  1642. IF in >= 80X THEN
  1643. out := Set[ORD(out), dbit]
  1644. END;
  1645. INC(sadr, 4); INC(dbit); DEC(len);
  1646. IF dbit = 8 THEN
  1647. SYSTEM.PUT(dadr, out);
  1648. INC(dadr); dbit := 0;
  1649. SYSTEM.GET(dadr, out)
  1650. END
  1651. END;
  1652. SYSTEM.PUT(dadr, out)
  1653. END BGRA8888OverA1;
  1654. PROCEDURE A1OverAny (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1655. VAR in: CHAR;
  1656. BEGIN
  1657. SYSTEM.GET(sadr, in);
  1658. WHILE len > 0 DO
  1659. IF Bit[ORD(in), sbit] THEN
  1660. mode.dst.pack(mode.dst, dadr, dbit, mode.buf)
  1661. END;
  1662. INC(sbit); dbit := dbit + mode.dst.bpp; INC(dadr, dbit DIV 8); dbit := dbit MOD 8; DEC(len);
  1663. IF sbit = 8 THEN
  1664. INC(sadr); sbit := 0;
  1665. SYSTEM.GET(sadr, in)
  1666. END
  1667. END
  1668. END A1OverAny;
  1669. PROCEDURE A1OverConst8 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1670. VAR in: CHAR;
  1671. BEGIN
  1672. SYSTEM.GET(sadr, in);
  1673. WHILE len > 0 DO
  1674. IF Bit[ORD(in), sbit] THEN
  1675. SYSTEM.PUT(dadr, mode.buf[0])
  1676. END;
  1677. INC(sbit); INC(dadr); DEC(len);
  1678. IF sbit = 8 THEN
  1679. INC(sadr); sbit := 0;
  1680. SYSTEM.GET(sadr, in)
  1681. END
  1682. END
  1683. END A1OverConst8;
  1684. PROCEDURE A1OverConst16 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1685. VAR in: CHAR;
  1686. BEGIN
  1687. SYSTEM.GET(sadr, in);
  1688. WHILE len > 0 DO
  1689. IF Bit[ORD(in), sbit] THEN
  1690. SYSTEM.MOVE(ADDRESSOF(mode.buf[0]), dadr, 2)
  1691. END;
  1692. INC(sbit); INC(dadr, 2); DEC(len);
  1693. IF sbit = 8 THEN
  1694. INC(sadr); sbit := 0;
  1695. SYSTEM.GET(sadr, in)
  1696. END
  1697. END
  1698. END A1OverConst16;
  1699. PROCEDURE A1OverConst24 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1700. VAR in: CHAR;
  1701. BEGIN
  1702. SYSTEM.GET(sadr, in);
  1703. WHILE len > 0 DO
  1704. IF Bit[ORD(in), sbit] THEN
  1705. SYSTEM.MOVE(ADDRESSOF(mode.buf[0]), dadr, 3)
  1706. END;
  1707. INC(sbit); INC(dadr, 3); DEC(len);
  1708. IF sbit = 8 THEN
  1709. INC(sadr); sbit := 0;
  1710. SYSTEM.GET(sadr, in)
  1711. END
  1712. END
  1713. END A1OverConst24;
  1714. PROCEDURE A1OverConst32 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1715. VAR in: CHAR;
  1716. BEGIN
  1717. SYSTEM.GET(sadr, in);
  1718. WHILE len > 0 DO
  1719. IF Bit[ORD(in), sbit] THEN
  1720. SYSTEM.MOVE(ADDRESSOF(mode.buf[0]), dadr, 4)
  1721. END;
  1722. INC(sbit); INC(dadr, 4); DEC(len);
  1723. IF sbit = 8 THEN
  1724. INC(sadr); sbit := 0;
  1725. SYSTEM.GET(sadr, in)
  1726. END
  1727. END
  1728. END A1OverConst32;
  1729. (* A8 *)
  1730. PROCEDURE AnyOverA8 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1731. VAR pix: Pixel; b: CHAR;
  1732. BEGIN
  1733. WHILE len > 0 DO
  1734. mode.src.unpack(mode.src, sadr, sbit, pix);
  1735. IF pix[a] = 0FFX THEN
  1736. SYSTEM.PUT(dadr, 0FFX)
  1737. ELSIF pix[a] # 0X THEN
  1738. SYSTEM.GET(dadr, b);
  1739. SYSTEM.PUT(dadr, CHR(ORD(pix[a]) + ORD(b) * LONG(255-ORD(pix[a])) DIV 255))
  1740. END;
  1741. sbit := sbit + mode.src.bpp; INC(sadr, sbit DIV 8); sbit := sbit MOD 8; INC(dadr); DEC(len)
  1742. END
  1743. END AnyOverA8;
  1744. PROCEDURE A8OverAny (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1745. VAR spix, dpix: Pixel; alpha, rc,gc,bc,ac: CHAR;
  1746. BEGIN
  1747. ac := mode.col[a];
  1748. rc := mode.col[r];
  1749. gc := mode.col[g];
  1750. bc := mode.col[b];
  1751. WHILE len > 0 DO
  1752. SYSTEM.GET(sadr, alpha);
  1753. alpha := CHR(ORD(ac) * ORD(alpha) DIV 255);
  1754. IF alpha = 0FFX THEN
  1755. mode.dst.pack(mode.dst, dadr, dbit, mode.buf)
  1756. ELSIF alpha # 0X THEN
  1757. spix[a] := alpha;
  1758. (* the following computation of the colors has to be done because the blending method seems to assume this *)
  1759. spix[r] := CHR(ORD(rc) * ORD(alpha) DIV 255);
  1760. spix[g] := CHR(ORD(gc) * ORD(alpha) DIV 255);
  1761. spix[b] := CHR(ORD(bc) * ORD(alpha) DIV 255);
  1762. mode.dst.unpack(mode.dst, dadr, dbit, dpix);
  1763. Blend(mode.op, spix, dpix);
  1764. mode.dst.pack(mode.dst, dadr, dbit, dpix);
  1765. END;
  1766. INC(sadr); DEC(len);
  1767. dbit := dbit + mode.dst.bpp; INC(dadr, dbit DIV 8); dbit := dbit MOD 8
  1768. END
  1769. END A8OverAny;
  1770. PROCEDURE A8OverBGRA8888(VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1771. VAR src , dst: Pixel; rc,gc,bc,ac, fd, fs: LONGINT;
  1772. BEGIN
  1773. rc := ORD(mode.col[r]);
  1774. gc := ORD(mode.col[g]);
  1775. bc := ORD(mode.col[b]);
  1776. ac := ORD(mode.col[a]);
  1777. fs := 255;
  1778. WHILE len > 0 DO
  1779. SYSTEM.GET(sadr, src[a]);
  1780. SYSTEM.MOVE(dadr, ADDRESSOF(dst), 4);
  1781. (* the following computation of the colors has to be done because the blending method seems to assume this *)
  1782. src[a] := CHR(ac * ORD(src[a]) DIV 255);
  1783. src[r] := CHR(rc * ORD(src[a]) DIV 255);
  1784. src[g] := CHR(gc * ORD(src[a]) DIV 255);
  1785. src[b] := CHR(bc * ORD(src[a]) DIV 255);
  1786. fd := 255-ORD(src[a]);
  1787. dst[0] := Clamp[200H + (fs * ORD(src[0]) + fd * ORD(dst[0])) DIV 255];
  1788. dst[1] := Clamp[200H + (fs * ORD(src[1]) + fd * ORD(dst[1])) DIV 255];
  1789. dst[2] := Clamp[200H + (fs * ORD(src[2]) + fd * ORD(dst[2])) DIV 255];
  1790. dst[3] := Clamp[200H + (fs * ORD(src[3]) + fd * ORD(dst[3])) DIV 255];
  1791. SYSTEM.MOVE(ADDRESSOF(dst),dadr,4);
  1792. INC(sadr); INC(dadr,4); DEC(len);
  1793. END
  1794. END A8OverBGRA8888;
  1795. PROCEDURE A8OverA8 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1796. VAR in, out: CHAR;
  1797. BEGIN
  1798. WHILE len > 0 DO
  1799. SYSTEM.GET(sadr, in);
  1800. IF in = 0FFX THEN
  1801. SYSTEM.PUT(dadr, 0FFX)
  1802. ELSIF in # 0X THEN
  1803. SYSTEM.GET(dadr, out);
  1804. SYSTEM.PUT(dadr, CHR(ORD(in) + ORD(out) * LONG(255-ORD(in)) DIV 255))
  1805. END;
  1806. INC(sadr); INC(dadr); DEC(len)
  1807. END
  1808. END A8OverA8;
  1809. PROCEDURE BGRA8888OverBGRA8888(VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1810. VAR src, dst: Pixel; fd,t: LONGINT;
  1811. BEGIN
  1812. WHILE len > 0 DO
  1813. SYSTEM.MOVE(sadr, ADDRESSOF(src), 4);
  1814. IF src[a] = 0FFX THEN
  1815. SYSTEM.MOVE(sadr,dadr,4);
  1816. ELSIF src[a] # 0X THEN
  1817. SYSTEM.MOVE(dadr, ADDRESSOF(dst), 4);
  1818. fd := 256-ORD(src[a]);
  1819. dst[0] := CHR(MIN( (256 * ORD(src[0]) + fd * ORD(dst[0])) DIV 256, 255));
  1820. (*
  1821. IF t < 255 THEN dst[0] := CHR(t) ELSE dst[0] := CHR(255) END;
  1822. *)
  1823. dst[1] := CHR(MIN((256 * ORD(src[1]) + fd * ORD(dst[1])) DIV 256, 255));
  1824. (*
  1825. IF t < 255 THEN dst[1] := CHR(t) ELSE dst[1] := CHR(255) END;
  1826. *)
  1827. dst[2] := CHR(MIN( (256 * ORD(src[2]) + fd * ORD(dst[2])) DIV 256, 255));
  1828. (*
  1829. IF t < 255 THEN dst[2] := CHR(t) ELSE dst[2] := CHR(255) END;
  1830. *)
  1831. dst[3] := CHR(MIN( (256 * ORD(src[3]) + fd * ORD(dst[3])) DIV 256, 255));
  1832. (*
  1833. IF t < 255 THEN dst[3] := CHR(t) ELSE dst[3] := CHR(255) END;
  1834. *)
  1835. SYSTEM.MOVE(ADDRESSOF(dst),dadr,4);
  1836. END;
  1837. INC(sadr,4); INC(dadr,4); DEC(len);
  1838. END
  1839. END BGRA8888OverBGRA8888;
  1840. (* BGRA8888 *)
  1841. PROCEDURE BGRA8888OverAny (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1842. VAR spix, dpix: Pixel;
  1843. BEGIN
  1844. WHILE len > 0 DO
  1845. SYSTEM.MOVE(sadr, ADDRESSOF(spix),4);
  1846. (*
  1847. SYSTEM.GET (sadr, spix);
  1848. *)
  1849. IF spix[a] = 0FFX THEN
  1850. mode.dst.pack(mode.dst, dadr, dbit, spix)
  1851. ELSIF spix[a] # 0X THEN
  1852. mode.dst.unpack(mode.dst, dadr, dbit, dpix);
  1853. Blend(mode.op, spix, dpix);
  1854. mode.dst.pack(mode.dst, dadr, dbit, dpix)
  1855. END;
  1856. INC(sadr, SIZEOF (Pixel)); DEC(len);
  1857. dbit := dbit + mode.dst.bpp; INC(dadr, dbit DIV 8); dbit := dbit MOD 8
  1858. END
  1859. END BGRA8888OverAny;
  1860. PROCEDURE BGRA8888OverA8 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1861. VAR in, out: CHAR;
  1862. BEGIN
  1863. WHILE len > 0 DO
  1864. SYSTEM.GET(sadr + a, in);
  1865. IF in = 0FFX THEN
  1866. SYSTEM.PUT(dadr, 0FFX)
  1867. ELSIF in # 0X THEN
  1868. SYSTEM.GET(dadr, out);
  1869. SYSTEM.PUT(dadr, CHR(ORD(in) + ORD(out) * (255 - ORD(in)) DIV 255))
  1870. END;
  1871. INC(sadr, 4); INC(dadr); DEC(len)
  1872. END
  1873. END BGRA8888OverA8;
  1874. PROCEDURE BGRA8888OverAny16 (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1875. VAR src, dst: Pixel; fd, t: LONGINT;
  1876. BEGIN
  1877. WHILE len > 0 DO
  1878. SYSTEM.MOVE(sadr,ADDRESSOF(src),4);
  1879. (* SYSTEM.GET (sadr, src);*)
  1880. IF src[a] = 0FFX THEN
  1881. mode.dst.pack(mode.dst, dadr, dbit, src)
  1882. ELSIF src[a] # 0X THEN
  1883. mode.dst.unpack(mode.dst, dadr, 0, dst);
  1884. fd := 255-ORD(src[a]);
  1885. t := (256 * ORD(src[0]) + fd * ORD(dst[0])) DIV 256;
  1886. IF t < 255 THEN dst[0] := CHR(t) ELSE dst[0] := CHR(255) END;
  1887. t := (256 * ORD(src[1]) + fd * ORD(dst[1])) DIV 256;
  1888. IF t < 255 THEN dst[1] := CHR(t) ELSE dst[1] := CHR(255) END;
  1889. t := (256 * ORD(src[2]) + fd * ORD(dst[2])) DIV 256;
  1890. IF t < 255 THEN dst[2] := CHR(t) ELSE dst[2] := CHR(255) END;
  1891. t := (256 * ORD(src[3]) + fd * ORD(dst[3])) DIV 256;
  1892. IF t < 255 THEN dst[3] := CHR(t) ELSE dst[3] := CHR(255) END;
  1893. mode.dst.pack(mode.dst, dadr, 0, dst);
  1894. END;
  1895. INC(dadr, 2); INC(sadr, SIZEOF (Pixel)); DEC(len)
  1896. END
  1897. END BGRA8888OverAny16;
  1898. PROCEDURE BGRA8888Over565* (VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1899. VAR src, dst: Pixel; fd, t: LONGINT;
  1900. BEGIN
  1901. WHILE len > 0 DO
  1902. SYSTEM.MOVE(sadr,ADDRESSOF(src),4);
  1903. (*
  1904. SYSTEM.GET (sadr, src);
  1905. *)
  1906. IF src[a] = 0FFX THEN
  1907. SYSTEM.PUT16(dadr, ASH(ORD(src[b]), -3) + ASH(ASH(ORD(src[g]), -2), 5) + ASH(ASH(ORD(src[r]), -3), 11));
  1908. ELSIF src[a] # 0X THEN
  1909. t := SYSTEM.GET16(dadr);
  1910. dst[b] := CHR((t MOD 32) * 8); dst[g] := CHR((t DIV 32 MOD 64) * 4); dst[r] := CHR((t DIV 2048 MOD 32) * 8);
  1911. fd := 256-ORD(src[a]);
  1912. t := (256 * ORD(src[0]) + fd * ORD(dst[0])) DIV 256;
  1913. IF t < 255 THEN dst[0] := CHR(t) ELSE dst[0] := CHR(255) END;
  1914. t := (256 * ORD(src[1]) + fd * ORD(dst[1])) DIV 256;
  1915. IF t < 255 THEN dst[1] := CHR(t) ELSE dst[1] := CHR(255) END;
  1916. t := (256 * ORD(src[2]) + fd * ORD(dst[2])) DIV 256;
  1917. IF t < 255 THEN dst[2] := CHR(t) ELSE dst[2] := CHR(255) END;
  1918. t := (256 * ORD(src[3]) + fd * ORD(dst[3])) DIV 256;
  1919. IF t < 255 THEN dst[3] := CHR(t) ELSE dst[3] := CHR(255) END;
  1920. SYSTEM.PUT16(dadr, ASH(ORD(dst[b]), -3) + ASH(ASH(ORD(dst[g]), -2), 5) + ASH(ASH(ORD(dst[r]), -3), 11));
  1921. END;
  1922. INC(dadr, 2); INC(sadr, 4); DEC(len)
  1923. END
  1924. END BGRA8888Over565;
  1925. PROCEDURE MMXBGRA8888Over565(VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  1926. CODE {SYSTEM.i386, SYSTEM.MMX}
  1927. PUSHFD
  1928. PUSH ECX
  1929. ; CLI
  1930. MOV ESI, [EBP+sadr]
  1931. MOV EDI, [EBP+dadr]
  1932. PXOR MMX0, MMX0
  1933. PXOR MMX1, MMX1
  1934. MOV EAX, 0FFFFFFFFH
  1935. MOVD MMX7, EAX
  1936. PUNPCKLBW MMX7, MMX0 ; 00FF00FF00FF00FF
  1937. MOV ECX, [EBP+len]
  1938. loop:
  1939. CMP ECX, 0
  1940. JE end
  1941. MOV EAX, [ESI]
  1942. XOR EBX, EBX
  1943. MOV BX, [EDI]
  1944. ; 255 - alpha
  1945. MOV EDX, EAX
  1946. SHR EDX, 24
  1947. CMP EDX, 0
  1948. JE empty
  1949. CMP EDX, 255
  1950. JE full
  1951. alpha:
  1952. NEG EDX
  1953. ADD EDX, 255
  1954. MOVD MMX6, EDX
  1955. PUNPCKLWD MMX6, MMX6
  1956. PUNPCKLDQ MMX6, MMX6
  1957. MOVD MMX1, EAX
  1958. ; unpack dst
  1959. MOV EDX, EBX ; b
  1960. SHL EDX, 3
  1961. AND EDX, 0F8H
  1962. MOV EAX, EDX
  1963. MOV EDX, EBX ; g
  1964. SHL EDX, 5
  1965. AND EDX, 0FC00H
  1966. OR EAX, EDX
  1967. MOV EDX, EBX ; r
  1968. SHL EDX, 8
  1969. AND EDX, 0F80000H
  1970. OR EAX, EDX
  1971. MOVD MMX2, EAX
  1972. PUNPCKLBW MMX1, MMX0 ; 0000ARGB --> 0A0R0G0B
  1973. PMULLW MMX1, MMX7
  1974. PUNPCKLBW MMX2, MMX0 ; 0000ARGB --> 0A0R0G0B
  1975. PMULLW MMX2, MMX6
  1976. PADDUSW MMX1, MMX2
  1977. ; PSRLW MMX1, 8 ; normalize
  1978. DB 0FH, 71H, 0D1H, 08H
  1979. PACKUSWB MMX1, MMX0
  1980. ; HUGA BIMBO Muell
  1981. MOVD EAX, MMX1
  1982. full:
  1983. ; XOR EDX, EDX
  1984. ; SHR EAX, 3
  1985. ; MOV EDX, EAX
  1986. ; AND EDX, 1FH
  1987. ; SHR EAX, 2
  1988. ; AND EAX, 0FFFFFFE0H
  1989. ; OR EDX, EAX
  1990. ; AND EDX, 7FFH
  1991. ;
  1992. ; SHR EAX, 3
  1993. ; AND EAX,
  1994. ;
  1995. ;
  1996. ; SHR AL, 3
  1997. ; SHR AH, 2
  1998. ; MOV EDX, EAX
  1999. ; SHR EAX, 3
  2000. ; AND EAX, 01F0000H
  2001. ; OR EDX, EAX
  2002. ; AND EDX, 01F3F1FH
  2003. MOV EBX, EAX
  2004. AND EBX, 0FFH
  2005. SHR EBX, 3
  2006. MOV EDX, EBX
  2007. MOV EBX, EAX
  2008. SHR EBX, 8
  2009. AND EBX, 0FFH
  2010. SHR EBX, 2
  2011. SHL EBX, 5
  2012. OR EDX, EBX
  2013. MOV EBX, EAX
  2014. SHR EBX, 16
  2015. AND EBX, 0FFH
  2016. SHR EBX, 3
  2017. SHL EBX, 11
  2018. OR EDX, EBX
  2019. MOV [EDI], DX
  2020. empty:
  2021. ADD ESI, 4;
  2022. ADD EDI, 2;
  2023. DEC ECX
  2024. JMP loop
  2025. end:
  2026. EMMS ; declare FPU registers free
  2027. POP ECX
  2028. POPFD
  2029. END MMXBGRA8888Over565;
  2030. PROCEDURE SSE2BGRA8888Over565(VAR mode: Mode0; sadr: ADDRESS; sbit: LONGINT; dadr: ADDRESS; dbit, len: LONGINT);
  2031. CODE {SYSTEM.i386, SYSTEM.MMX, SYSTEM.SSE, SYSTEM.SSE2}
  2032. PUSHFD
  2033. PUSH ECX
  2034. PUSH EBX
  2035. ; CLI
  2036. PXOR MMX0, MMX0
  2037. PXOR MMX1, MMX1
  2038. PXOR MMX2, MMX2
  2039. PXOR MMX3, MMX3
  2040. PXOR MMX4, MMX4
  2041. PXOR MMX5, MMX5
  2042. PXOR MMX6, MMX6
  2043. PXOR MMX7, MMX7
  2044. PXOR XMM3, XMM3
  2045. PXOR XMM4, XMM4
  2046. MOV ESI, [EBP+sadr]
  2047. MOV EDI, [EBP+dadr]
  2048. MOV ECX, [EBP+len]
  2049. ; create masks
  2050. ; src only FF which is rotated -> MMX3
  2051. MOV EAX, 0000000FFH
  2052. MOVD MMX3, EAX
  2053. ; dest red -> MMX4
  2054. MOV EAX, 0F800F800H
  2055. MOVD MMX4, EAX
  2056. ; dest green -> MMX5
  2057. MOV EAX, 07E007E0H
  2058. MOVD MMX5, EAX
  2059. ; dest blue -> MMX6 ; moved as MMX6 is used in singlepixel
  2060. ; MOV EAX, 001F001FH
  2061. ; MOVD MMX6, EAX
  2062. ; BEGIN
  2063. ; WHILE len > 0 DO
  2064. loop:
  2065. CMP ECX,0
  2066. JE end ; jump to end if ECX = 0
  2067. ; if len < 8 then do one pixel at the time
  2068. CMP ECX, 8
  2069. JL singlepixel
  2070. ; else
  2071. ; take 8 at the time
  2072. MOV EBX, ESI
  2073. AND EBX, 0FH
  2074. CMP EBX, 0
  2075. JNE singlepixel
  2076. alleightpixels:
  2077. ; dest blue -> MMX6
  2078. MOV EAX, 001F001FH
  2079. MOVD MMX6, EAX
  2080. ; src := SYSTEM.VAL(Pixel, SYSTEM.GET32(sadr));
  2081. ; Load data into memory
  2082. ;MOV XMM4, 0FF000000FF000000FF000000FF000000H
  2083. MOVDQA XMM2, [ESI] ;src 5-8
  2084. MOVQ2DQ XMM4, MMX3 ; 000000000000000000000000000000FFH
  2085. MOVDQA XMM1, [ESI+16] ;src 1-4
  2086. PREFETCHNTA [ESI+32] ; prepare src 9-15
  2087. ; get alphas
  2088. MOVDQU XMM6, XMM2
  2089. PSHUFD XMM4, XMM4, 0
  2090. MOVDQU XMM5, XMM1
  2091. PSLLD XMM4, 24
  2092. PAND XMM6, XMM4 ; alpha 5-8 in XMM6
  2093. PAND XMM5, XMM4 ; alpha 1-4 in XMM5
  2094. PSRLD XMM5, 24
  2095. PSHUFHW XMM5, XMM5, 85H
  2096. PSRLD XMM6, 24
  2097. ; put both alphas into 1 register
  2098. PSHUFHW XMM6, XMM6, 85H
  2099. PSHUFLW XMM5, XMM5, 85H
  2100. PSHUFLW XMM6, XMM6, 58H
  2101. PSHUFD XMM5, XMM5, 0D0H ; 0102030400000000
  2102. PSHUFD XMM6, XMM6, 5CH ; 0000000005060708
  2103. PXOR XMM0,XMM0
  2104. POR XMM5, XMM6 ; XMM5 = alphas 0102030405060708
  2105. PCMPEQD XMM0, XMM5
  2106. PMOVMSKB EAX, XMM0
  2107. CMP EAX, 0FFFFH ; all alphas = zero; TEST not possible, because only 8 bits compared
  2108. JE endloop
  2109. ; mask out alpha = zero
  2110. ; fd := 255-ORD(src[a]); fd = XMM4
  2111. ; MOV XMM4, 00FF00FF00FF00FF00FF00FF00FF00FFH
  2112. PXOR XMM4, XMM4
  2113. MOV EAX, 00FFH
  2114. PINSRW XMM4, EAX ,0
  2115. PSHUFLW XMM4, XMM4, 0
  2116. PSHUFD XMM4, XMM4, 0
  2117. PSUBW XMM4, XMM5
  2118. MOV EAX,1H
  2119. PINSRW XMM3, EAX ,0
  2120. PSHUFLW XMM3, XMM3, 0
  2121. PSHUFD XMM3, XMM3, 0
  2122. PADDUSW XMM4, XMM3
  2123. ; new red
  2124. ; calculate red 2
  2125. ; get source
  2126. ; sred14 = src14 && (srcMask <<16)
  2127. ; srcMask << 16
  2128. MOVQ2DQ XMM3, MMX3
  2129. PSHUFD XMM3, XMM3, 0
  2130. MOVDQU XMM5, XMM1
  2131. MOVDQU XMM6, XMM2
  2132. PSLLD XMM3, 16
  2133. ; sred14 = src14 && (srcMask << 24)
  2134. ; src14 must be copied because it mustn't be changed
  2135. PAND XMM5, XMM3 ; sred14
  2136. PSRLD XMM5, 16
  2137. ; sred14s = shuffled sred14
  2138. PSHUFHW XMM5, XMM5,85H
  2139. PAND XMM6, XMM3 ; sred58
  2140. PSRLD XMM6, 16
  2141. PSHUFLW XMM5, XMM5,85H
  2142. PSHUFHW XMM6, XMM6,85H
  2143. PSHUFD XMM5, XMM5,0D0H ; sred14s
  2144. PSHUFLW XMM6, XMM6,58H
  2145. PSHUFD XMM6, XMM6,5CH ; sred58s
  2146. POR XMM5, XMM6 ; sred18
  2147. ; sred18255 = sred18 * 256- sred18
  2148. MOVDQU XMM7, XMM5
  2149. PSLLW XMM5, 8
  2150. PSUBUSW XMM5, XMM7 ; sred18255
  2151. ; src is now ready
  2152. ; destination
  2153. ; dest18 must be copied because it mustn't be changed
  2154. ; Load data into memory
  2155. MOVDQU XMM3, [EDI] ;dest 1-8
  2156. MOVQ2DQ XMM6, MMX4
  2157. PSHUFD XMM6, XMM6, 0
  2158. MOVDQU XMM7, XMM3
  2159. PAND XMM7, XMM6 ; dred18
  2160. PSRLW XMM7, 8
  2161. ; dred18alpha = dred18 * negalpha
  2162. PMULLW XMM7, XMM4 ; dred18alpha
  2163. ; dest is prepared
  2164. ; combining dest and src
  2165. ; dred18big = sred18255 + dred18alpha
  2166. PADDUSW XMM7, XMM5 ; dred18big
  2167. ; dred18f = dred18big && destMaskred128 because >> 11 and << 11 is && mask
  2168. PAND XMM7, XMM6 ; dred18f
  2169. ; dest18nr0 = dest18 && (~destMaskred128)
  2170. PANDN XMM6, XMM3 ; dest18nr0
  2171. ; dest18nrf = dest18nr0 || dred18f
  2172. POR XMM6, XMM7
  2173. MOVDQU XMM3, XMM6
  2174. ; red is calculated
  2175. ; calculate green:
  2176. ; get source
  2177. ; sgreen14 = src14 && (srcMask <<8)
  2178. ; srcMask << 8
  2179. MOVQ2DQ XMM7, MMX3
  2180. PSHUFD XMM7, XMM7, 0
  2181. MOVDQU XMM5, XMM1
  2182. PSLLD XMM7, 8
  2183. PAND XMM5, XMM7 ; sgreen14
  2184. PSRLD XMM5, 8
  2185. ; sgreen14s = shuffled sgreen14
  2186. PSHUFHW XMM5, XMM5,85H
  2187. MOVDQU XMM6, XMM2
  2188. PSHUFLW XMM5, XMM5,85H
  2189. PAND XMM6, XMM7 ; sgreen58
  2190. PSRLD XMM6, 8
  2191. PSHUFD XMM5, XMM5,0D0H ; sgreen14s
  2192. ; sgreen58 = src58&& (srcMask << 8)
  2193. ; src58 must be copied because it mustn't be changed
  2194. ; sgreen58s = shuffled sgreen58
  2195. PSHUFHW XMM6, XMM6,85H
  2196. PSHUFLW XMM6, XMM6,58H
  2197. PSHUFD XMM6, XMM6,5CH ; sgreen58s
  2198. ; sgreen18 = sgreen14s || sgreen58s
  2199. POR XMM5, XMM6 ; sgreen18
  2200. ; sgreen18255 = sgreen18 * 256- sgreen18
  2201. MOVDQU XMM7, XMM5
  2202. MOVQ2DQ XMM6, MMX5
  2203. PSLLW XMM5, 8
  2204. PSUBUSW XMM5, XMM7 ; sgreen18255
  2205. PSHUFD XMM6, XMM6, 0
  2206. MOVDQU XMM7, XMM3
  2207. PAND XMM7, XMM6 ; dgreen18
  2208. PSRLW XMM7,3
  2209. ; dgreen18alpha = dgreen18 * negalpha
  2210. PMULLW XMM7, XMM4 ; dgreen18alpha
  2211. ; dest is prepared
  2212. ; combining dest and src
  2213. ; dgreen18big = sgreen18255 + dgreen18alpha
  2214. PADDUSW XMM7, XMM5 ; dgreen18big
  2215. PANDN XMM6, XMM3 ; dest18ng0
  2216. ; dgreen18f = (dgreen18big >> 11) <<5
  2217. PSRLW XMM7, 10 ; dgreen18f
  2218. PSLLW XMM7, 5
  2219. ; dest18ng0 = dest18 && (~destMaskgreen128)
  2220. ; dest18ngf = dest18ng0 || dred18f
  2221. POR XMM6, XMM7
  2222. MOVDQU XMM3, XMM6
  2223. ; green is calculated
  2224. ; calculate blue
  2225. ; get source
  2226. ; sblue14 = src14 && (srcMask)
  2227. ; srcMask
  2228. MOVQ2DQ XMM7, MMX3
  2229. MOVDQU XMM5, XMM1
  2230. PSHUFD XMM7, XMM7, 0
  2231. MOVDQU XMM6, XMM2
  2232. ; sblue14 = src14 && (srcMask)
  2233. ; src14 must be copied because it mustn't be changed
  2234. PAND XMM5, XMM7 ; sblue14
  2235. ; sblue14s = shuffled sblue14
  2236. PSHUFHW XMM5, XMM5,85H
  2237. PAND XMM6, XMM7 ; sblue58
  2238. PSHUFHW XMM6, XMM6,85H
  2239. PSHUFLW XMM5, XMM5,85H
  2240. PSHUFLW XMM6, XMM6,58H
  2241. PSHUFD XMM5, XMM5,0D0H ; sblue14s
  2242. PSHUFD XMM6, XMM6,5CH ; sblue58s
  2243. POR XMM5, XMM6 ; sblue18
  2244. ; sblue18255 = sblue18 * 256- sblue18
  2245. MOVDQU XMM7, XMM5
  2246. PSLLW XMM5, 8
  2247. PSUBUSW XMM5, XMM7 ; sblue18255
  2248. MOVQ2DQ XMM6, MMX6
  2249. PSHUFD XMM6, XMM6, 0
  2250. MOVDQU XMM7, XMM3
  2251. PAND XMM7, XMM6 ; dblue18
  2252. PSLLW XMM7, 3
  2253. PMULLW XMM7, XMM4 ; dblue18alpha
  2254. ; dest is prepared
  2255. ; combining dest and src
  2256. ; dblue18big = sblue18255 + dblue18alpha
  2257. PADDUSW XMM7, XMM5 ; dblue18big
  2258. ; dblue18f = (dblue18big >> 11)
  2259. PANDN XMM6, XMM3 ; dest18nr0
  2260. PSRLW XMM7, 11 ; dblue18f
  2261. ; dest18nr0 = dest18 && (~destMaskblue128)
  2262. ; dest18nbf = dest18nb0 || dblue18f
  2263. POR XMM6, XMM7
  2264. MOVDQU XMM3, XMM6
  2265. ; blue is calculated
  2266. ; now dest is calculated, store it
  2267. ; get 0 stuff
  2268. MOVDQU XMM5, [EDI]
  2269. PAND XMM5,XMM0
  2270. PANDN XMM0, XMM3
  2271. POR XMM0, XMM5
  2272. MOVDQU [EDI],XMM0
  2273. PREFETCHNTA [EDI+16] ; prepare dest 9-15
  2274. endloop:
  2275. ADD ESI, 32 ; num of bytes
  2276. ADD EDI, 16
  2277. SUB ECX, 8
  2278. JMP loop
  2279. singlepixel: ; original code from MMXBGRA8888Over565, adjusted to fit this procedure
  2280. MOV EAX, 0FFFFFFFFH
  2281. MOVD MMX7, EAX
  2282. PUNPCKLBW MMX7, MMX0 ; 00FF00FF00FF00FF
  2283. MOV EAX,[ESI]
  2284. XOR EBX, EBX
  2285. MOV BX, [EDI]
  2286. ; 255 - alpha
  2287. MOV EDX, EAX
  2288. SHR EDX, 24
  2289. CMP EDX, 0
  2290. JE empty
  2291. CMP EDX, 255
  2292. JE full
  2293. alpha:
  2294. NEG EDX
  2295. ADD EDX, 255
  2296. MOVD MMX6, EDX
  2297. PUNPCKLWD MMX6, MMX6
  2298. PUNPCKLDQ MMX6, MMX6
  2299. MOVD MMX1, EAX
  2300. ; unpack dst
  2301. MOV EDX, EBX ; b
  2302. SHL EDX, 3
  2303. AND EDX, 0F8H
  2304. MOV EAX, EDX
  2305. MOV EDX, EBX ; g
  2306. SHL EDX, 5
  2307. AND EDX, 0FC00H
  2308. OR EAX, EDX
  2309. MOV EDX, EBX ; r
  2310. SHL EDX, 8
  2311. AND EDX, 0F80000H
  2312. OR EAX, EDX
  2313. MOVD MMX2, EAX
  2314. PUNPCKLBW MMX1, MMX0 ; 0000ARGB --> 0A0R0G0B
  2315. PMULLW MMX1, MMX7
  2316. PUNPCKLBW MMX2, MMX0 ; 0000ARGB --> 0A0R0G0B
  2317. PMULLW MMX2, MMX6
  2318. PADDUSW MMX1, MMX2
  2319. ; PSRLW MMX1, 8 ; normalize
  2320. DB 0FH, 71H, 0D1H, 08H
  2321. PACKUSWB MMX1, MMX0
  2322. ; HUGA BIMBO Muell
  2323. MOVD EAX, MMX1
  2324. full:
  2325. MOV EBX, EAX
  2326. AND EBX, 0FFH
  2327. SHR EBX, 3
  2328. MOV EDX, EBX
  2329. MOV EBX, EAX
  2330. SHR EBX, 8
  2331. AND EBX, 0FFH
  2332. SHR EBX, 2
  2333. SHL EBX, 5
  2334. OR EDX, EBX
  2335. MOV EBX, EAX
  2336. SHR EBX, 16
  2337. AND EBX, 0FFH
  2338. SHR EBX, 3
  2339. SHL EBX, 11
  2340. OR EDX, EBX
  2341. MOV [EDI], DX
  2342. empty:
  2343. ADD ESI, 4;
  2344. ADD EDI, 2;
  2345. DEC ECX
  2346. JMP loop
  2347. end:
  2348. EMMS ; declare FPU registers free
  2349. POP EBX
  2350. POP ECX
  2351. POPFD
  2352. END SSE2BGRA8888Over565;
  2353. (** find (optimized) pixel transfer procedure for transfer mode and given source and destination formats **)
  2354. PROCEDURE Bind* (VAR mode: Mode; VAR src, dst: Format);
  2355. VAR op: LONGINT; val,i: LONGINT;
  2356. BEGIN
  2357. IF Same(src, mode.src) & Same(dst, mode.dst) THEN
  2358. ASSERT(mode.transfer # NIL, 120);
  2359. RETURN (* assume transfer procedure is still valid *)
  2360. END;
  2361. mode.src := src; mode.dst := dst; mode.buf := mode.col;
  2362. IF (src.pal # NIL) & ((mode.map = NIL) OR (LEN(mode.map^) # src.pal.used) ) THEN
  2363. NEW(mode.map, src.pal.used)
  2364. END;
  2365. (* try to convert complex composite operations into simpler ones *)
  2366. IF alpha IN src.components * dst.components THEN (* source and destination contain alpha information *)
  2367. op := mode.op
  2368. ELSIF alpha IN src.components THEN (* only source contains alpha *)
  2369. CASE mode.op OF
  2370. | dstOverSrc: op := dstCopy
  2371. | srcInDst: op := srcCopy
  2372. | srcWithoutDst: op := clear
  2373. | srcAtopDst: op := srcOverDst
  2374. | dstAtopSrc: op := dstInSrc
  2375. | srcXorDst: op := dstWithoutSrc
  2376. ELSE op := mode.op
  2377. END
  2378. ELSIF alpha IN dst.components THEN (* only destination contains alpha *)
  2379. CASE mode.op OF
  2380. | srcOverDst: op := srcCopy
  2381. | dstInSrc: op := dstCopy
  2382. | dstWithoutSrc: op := clear
  2383. | srcAtopDst: op := srcInDst
  2384. | dstAtopSrc: op := dstOverSrc
  2385. | srcXorDst: op := srcWithoutDst
  2386. ELSE op := mode.op
  2387. END
  2388. ELSE (* no alpha in either source or destination *)
  2389. CASE mode.op OF
  2390. | srcOverDst, srcInDst, srcAtopDst: op := srcCopy
  2391. | dstOverSrc, dstInSrc, dstAtopSrc: op := dstCopy
  2392. | srcWithoutDst, dstWithoutSrc, srcXorDst: op := clear
  2393. ELSE op := mode.op
  2394. END
  2395. END;
  2396. IF op = InvDst THEN
  2397. mode.transfer:=InvAny;
  2398. ELSIF op = InvOverDst THEN
  2399. mode.transfer:=InvOverAny;
  2400. ELSIF op = clear THEN
  2401. CASE dst.code OF
  2402. | a1: mode.transfer := Clear1
  2403. | a8, bgr555, bgr565, bgr466, bgr888(*, bgra8888*): mode.transfer := ClearBytes
  2404. | bgra8888: mode.transfer:=Clear32;
  2405. | p8:
  2406. mode.buf[0] := CHR(CLUTs.Match(dst.pal.clut, 0));
  2407. IF mode.buf[0] = 0X THEN mode.transfer := ClearBytes
  2408. ELSE mode.transfer := ConstCopy8
  2409. END
  2410. | d8:
  2411. mode.buf[0] := CHR(ColorToIndex(0));
  2412. IF mode.buf[0] = 0X THEN mode.transfer := ClearBytes
  2413. ELSE mode.transfer := ConstCopy8
  2414. END
  2415. | p16:
  2416. val:=CLUTs.Match(dst.pal.clut, 0);
  2417. IF dst.pal.used>256 THEN val:=val*dst.pal.used DIV 256 END;
  2418. SYSTEM.PUT16(ADDRESSOF(mode.buf[0]),SHORT(val)); (*PH090122*)
  2419. (*mode.buf[0] := CHR(PaletteIndex(dst.pal, 0, 0, 0));*)
  2420. IF val = 0 THEN mode.transfer := ClearBytes
  2421. ELSE mode.transfer := ConstCopy16
  2422. END
  2423. ELSE mode.transfer := ClearAny
  2424. END
  2425. ELSIF op = srcCopy THEN
  2426. CASE dst.code OF
  2427. | a1:
  2428. CASE src.code OF
  2429. | a1: mode.transfer := Copy1
  2430. | a8: mode.transfer := A8CopyA1
  2431. | bgra8888: mode.transfer := BGRA8888CopyA1
  2432. ELSE
  2433. IF alpha IN src.components THEN mode.transfer := AnyCopyA1
  2434. ELSE mode.transfer := Set1
  2435. END
  2436. END
  2437. | a8:
  2438. CASE src.code OF
  2439. | a1: mode.transfer := A1CopyA8
  2440. | a8: mode.transfer := Copy8
  2441. | bgra8888: mode.transfer := BGRA8888CopyA8
  2442. ELSE
  2443. IF alpha IN src.components THEN mode.transfer := AnyCopyA8
  2444. ELSE mode.buf[0] := 0FFX; mode.transfer := ConstCopy8
  2445. END
  2446. END
  2447. | p8:
  2448. CASE src.code OF
  2449. | a1, a8:
  2450. mode.buf[0] := CHR(CLUTs.Match(dst.pal.clut, ORD(mode.col[b]) + ASH(ORD(mode.col[g]), 8) +
  2451. ASH(ORD(mode.col[r]), 16)));
  2452. mode.transfer := ConstCopy8
  2453. | p8:
  2454. IF src.pal = dst.pal THEN mode.transfer := Copy8
  2455. ELSE
  2456. FOR i := 0 TO src.pal.used-1 DO
  2457. mode.map[i] := SHORT(CLUTs.Match(dst.pal.clut, ORD(src.pal.col[i, b]) + ASH(ORD(src.pal.col[i, g]), 8) +
  2458. ASH(ORD(src.pal.col[i, r]), 16)))
  2459. END;
  2460. mode.transfer := I8CopyI8
  2461. END
  2462. | d8:
  2463. FOR i := 0 TO 255 DO
  2464. mode.map[i] := SHORT(CLUTs.Match(dst.pal.clut, IndexToColor(i) MOD 1000000H))
  2465. END;
  2466. mode.transfer := I8CopyI8
  2467. | bgr555, bgr565, bgr466,p16: mode.transfer := Any16CopyP8
  2468. | bgr888: mode.transfer := BGR888CopyP8
  2469. | bgra8888: mode.transfer := BGRA8888CopyP8
  2470. ELSE mode.transfer := AnyCopyP8
  2471. END
  2472. | d8:
  2473. CASE src.code OF
  2474. | a1, a8:
  2475. mode.buf[0] := CHR(ColorToIndex(
  2476. ORD(mode.col[b]) + ASH(ORD(mode.col[g]), 8) + ASH(ORD(mode.col[r]), 16)));
  2477. mode.transfer := ConstCopy8
  2478. | p8:
  2479. FOR i := 0 TO src.pal.used-1 DO
  2480. mode.map[i] := SHORT(ColorToIndex(
  2481. ORD(src.pal.col[i, b]) + ASH(ORD(src.pal.col[i, g]), 8) + ASH(ORD(src.pal.col[i, r]), 16)))
  2482. END;
  2483. mode.transfer := I8CopyI8
  2484. | d8: mode.transfer := Copy8
  2485. | bgr555, bgr565, bgr466, p16: mode.transfer := Any16CopyD8
  2486. | bgr888: mode.transfer := BGR888CopyD8
  2487. | bgra8888: mode.transfer := BGRA8888CopyD8
  2488. ELSE mode.transfer := AnyCopyD8
  2489. END
  2490. | p16:
  2491. CASE src.code OF
  2492. | a1, a8: dst.pack(dst, ADDRESSOF(mode.buf[0]), 0, mode.col); mode.transfer := ConstCopy16
  2493. | p8: mode.transfer := P8CopyAny16
  2494. | d8: mode.transfer := D8CopyAny16
  2495. | p16:
  2496. IF src.pal = dst.pal THEN mode.transfer := Copy16
  2497. ELSE
  2498. FOR i := 0 TO src.pal.used-1 DO
  2499. val:=CLUTs.Match(dst.pal.clut, ORD(src.pal.col[i, b]) + ASH(ORD(src.pal.col[i, g]), 8) +
  2500. ASH(ORD(src.pal.col[i, r]), 16));
  2501. IF dst.pal.used>256 THEN val := val * dst.pal.used DIV 256 END;
  2502. mode.map[i] := SHORT(val)
  2503. END;
  2504. mode.transfer := I16CopyI16
  2505. END
  2506. | bgr555, bgr565, bgr466: mode.transfer := Any16CopyAny16
  2507. | bgr888: mode.transfer := BGR888CopyAny16
  2508. | bgra8888: mode.transfer := BGRA8888CopyAny16
  2509. ELSE mode.transfer := AnyCopyAny16
  2510. END;
  2511. | bgr555, bgr565, bgr466:
  2512. CASE src.code OF
  2513. | a1, a8: dst.pack(dst, ADDRESSOF(mode.buf[0]), 0, mode.col); mode.transfer := ConstCopy16
  2514. | p8: mode.transfer := P8CopyAny16
  2515. | d8: mode.transfer := D8CopyAny16
  2516. | bgr555, bgr565, bgr466,p16:
  2517. IF src.code = dst.code THEN mode.transfer := Copy16
  2518. ELSE mode.transfer := Any16CopyAny16
  2519. END
  2520. | bgr888: mode.transfer := BGR888CopyAny16
  2521. | bgra8888: mode.transfer := BGRA8888CopyAny16
  2522. ELSE mode.transfer := AnyCopyAny16
  2523. END;
  2524. | bgr888:
  2525. CASE src.code OF
  2526. | a1, a8: mode.buf := mode.col; mode.transfer := ConstCopy24
  2527. | p8: mode.transfer := P8CopyBGR888
  2528. | d8: mode.transfer := D8CopyBGR888
  2529. | p16: mode.transfer := P16CopyBGR888 (*PH090122*)
  2530. | bgr555, bgr565, bgr466: mode.transfer := Any16CopyBGR888
  2531. | bgr888: mode.transfer := Copy24
  2532. | bgra8888:
  2533. (* IF SSE2enabled THEN mode.transfer := SSE2BGRA8888CopyBGR888
  2534. ELSE *) mode.transfer := BGRA8888CopyBGR888
  2535. (* END*);
  2536. ELSE mode.transfer := AnyCopyBGR888
  2537. END
  2538. | bgra8888:
  2539. CASE src.code OF
  2540. | a1: mode.transfer := A1CopyBGRA8888
  2541. | a8: mode.transfer := A8CopyBGRA8888
  2542. | p8: mode.transfer := P8CopyBGRA8888
  2543. | d8: mode.transfer := D8CopyBGRA8888
  2544. | p16: mode.transfer := P16CopyBGRA8888 (*PH090122*)
  2545. | bgr555, bgr565, bgr466: mode.transfer := Any16CopyBGRA8888
  2546. | bgr888: IF SSE2enabled THEN mode.transfer := SSE2BGR888CopyBGRA8888
  2547. ELSE mode.transfer :=BGR888CopyBGRA8888;
  2548. END;
  2549. | bgra8888: mode.transfer := Copy32
  2550. ELSE mode.transfer := AnyCopyBGRA8888
  2551. END
  2552. ELSE
  2553. CASE src.code OF
  2554. | a1: mode.transfer := A1CopyAny
  2555. | p8: mode.transfer := P8CopyAny
  2556. | d8: mode.transfer := D8CopyAny
  2557. | bgr555, bgr565, bgr466,p16: mode.transfer := Any16CopyAny
  2558. | bgr888: mode.transfer := BGR888CopyAny
  2559. | bgra8888: mode.transfer := BGRA8888CopyAny
  2560. ELSE
  2561. IF (src.bpp MOD 8 = 0) & (dst.bpp MOD 8 = 0) THEN mode.transfer := AnyBytesCopyAnyBytes
  2562. ELSE mode.transfer := AnyCopyAny
  2563. END
  2564. END
  2565. END
  2566. ELSIF op = dstOverSrc THEN
  2567. mode.transfer := EmptyTransfer
  2568. ELSIF op = srcOverDst THEN
  2569. CASE dst.code OF
  2570. | a1:
  2571. CASE src.code OF
  2572. | a1: mode.transfer := A1OverA1
  2573. | a8: mode.transfer := A8OverA1
  2574. | bgra8888: mode.transfer := BGRA8888OverA1
  2575. ELSE mode.transfer := AnyOverA1
  2576. END
  2577. | a8:
  2578. CASE src.code OF
  2579. | a1: mode.buf[0] := 0FFX; mode.transfer := A1OverConst8
  2580. | a8: mode.transfer := A8OverA8
  2581. | bgra8888: mode.transfer := BGRA8888OverA8
  2582. ELSE mode.transfer := AnyOverA8
  2583. END
  2584. | bgra8888:
  2585. CASE src.code OF
  2586. | a1: mode.buf := mode.col; mode.transfer := A1OverConst32
  2587. | a8: mode.buf := mode.col; mode.transfer := A8OverAny;
  2588. IF mode.op = srcOverDst THEN mode.transfer := A8OverBGRA8888 END;
  2589. | bgra8888: mode.transfer := BGRA8888OverBGRA8888
  2590. ELSE mode.transfer := BGRA8888OverAny; (* ? *)
  2591. END
  2592. ELSE
  2593. CASE src.code OF
  2594. | a1:
  2595. CASE dst.code OF
  2596. | p8:
  2597. mode.buf[0] := CHR(CLUTs.Match(dst.pal.clut, ORD(mode.col[b]) + ASH(ORD(mode.col[g]), 8) +
  2598. ASH(ORD(mode.col[r]), 16)));
  2599. mode.transfer := A1OverConst8
  2600. | d8:
  2601. mode.buf[0] := CHR(ColorToIndex(ORD(mode.col[b]) + ASH(ORD(mode.col[g]), 8) +
  2602. ASH(ORD(mode.col[r]), 16)));
  2603. mode.transfer := A1OverConst8
  2604. | p16: (* this is probably not correct ... *)
  2605. mode.buf[0] := CHR(PaletteIndex(dst.pal, ORD(mode.col[r]), ORD(mode.col[g]), ORD(mode.col[b])));
  2606. mode.transfer := A1OverConst16
  2607. | bgr555, bgr565, bgr466: dst.pack(dst, ADDRESSOF(mode.buf[0]), 0, mode.col); mode.transfer := A1OverConst16
  2608. | bgr888: mode.buf := mode.col; mode.transfer := A1OverConst24
  2609. ELSE mode.transfer := A1OverAny
  2610. END
  2611. | a8: mode.buf := mode.col; mode.transfer := A8OverAny
  2612. | bgra8888:
  2613. CASE dst.code OF
  2614. | bgr555, bgr466, p16: mode.transfer := BGRA8888OverAny16
  2615. | bgr565 : IF MMXenabled THEN
  2616. mode.transfer := MMXBGRA8888Over565;
  2617. IF SSE2enabled THEN mode.transfer := SSE2BGRA8888Over565; END;
  2618. ELSE mode.transfer := BGRA8888Over565
  2619. END
  2620. ELSE mode.transfer := BGRA8888OverAny
  2621. END
  2622. ELSE
  2623. mode.transfer := AnyBlendAny
  2624. END
  2625. END
  2626. ELSE
  2627. mode.transfer := AnyBlendAny
  2628. END;
  2629. ASSERT(mode.transfer # NIL, 120)
  2630. END Bind;
  2631. (**--- Image Operations ---**)
  2632. (** get pixel from image **)
  2633. PROCEDURE Get* (img: Image; x, y: LONGINT; VAR pix: Pixel; VAR mode: Mode);
  2634. VAR bit: LONGINT; adr: ADDRESS;
  2635. BEGIN
  2636. ASSERT((0 <= x) & (x < img.width) & (0 <= y) & (y < img.height), 100);
  2637. bit := x * img.fmt.bpp; adr := img.adr + y * img.bpr + bit DIV 8; bit := bit MOD 8;
  2638. Bind(mode, img.fmt, PixelFormat);
  2639. (*mode.transfer(mode, adr, bit, ADDRESSOF(pix), 0, 1)*)
  2640. mode.transfer(mode, adr, bit, ADDRESSOF(pix[0]), 0, 1) (*PH090122*)
  2641. END Get;
  2642. (** put pixel into image **)
  2643. PROCEDURE Put* (img: Image; x, y: LONGINT; CONST pix: Pixel; VAR mode: Mode);
  2644. VAR bit: LONGINT; adr: ADDRESS;
  2645. BEGIN
  2646. (*ASSERT((0 <= x) & (x < img.width) & (0 <= y) & (y < img.height), 100);*) (*avoid a HALT if roundoff errors from higher levels occur here*)
  2647. IF (0 > x) OR (x >= img.width) OR (0 > y) OR (y >= img.height) THEN RETURN END;
  2648. bit := x * img.fmt.bpp; adr := img.adr + y * img.bpr + bit DIV 8; bit := bit MOD 8;
  2649. Bind(mode, PixelFormat, img.fmt);
  2650. mode.transfer(mode, ADDRESSOF(pix[0]), 0, adr, bit, 1)
  2651. END Put;
  2652. (** fill rectangular area **)
  2653. PROCEDURE Fill* (img: Image; llx, lly, urx, ury: LONGINT; CONST pix: Pixel; VAR mode: Mode);
  2654. VAR bit, bb, x, c, t: LONGINT; m: Mode; adr, aa: ADDRESS;
  2655. BEGIN
  2656. ASSERT((0 <= llx) & (llx < urx) & (urx <= img.width) & (0 <= lly) & (lly < ury) & (ury <= img.height), 100);
  2657. bit := llx * img.fmt.bpp; adr := img.adr + lly * img.bpr + bit DIV 8; bit := bit MOD 8;
  2658. IF (mode.op = srcCopy) & (img.fmt.code IN {bgr565}) THEN (* shortcut for speed in important cases *)
  2659. c := ASH(ORD(pix[b]), -3) + ASH(ASH(ORD(pix[g]), -2), 5) + ASH(ASH(ORD(pix[r]), -3), 11);
  2660. t := urx - llx;
  2661. WHILE lly < ury DO
  2662. Fill16(adr, t, c);
  2663. INC(lly); INC(adr, img.bpr)
  2664. END
  2665. ELSIF (mode.op = srcCopy) & (img.fmt.code = bgra8888) THEN (*!to do: move Fill32 with standardized parameters in to Bind() instead*)
  2666. c := SYSTEM.VAL(LONGINT, pix);
  2667. t := urx - llx;
  2668. WHILE lly < ury DO
  2669. Fill32(adr, t, c);
  2670. INC(lly); INC(adr, img.bpr)
  2671. END
  2672. ELSE
  2673. Bind(mode, PixelFormat, img.fmt);
  2674. IF (mode.op IN {clear, srcCopy}) OR (pix[a] = 0FFX) & (mode.op IN {srcOverDst, dstWithoutSrc}) THEN (* dst is replaced *)
  2675. (* copy one pixel to lower left corner of rect *)
  2676. mode.transfer(mode, ADDRESSOF(pix[0]), 0, adr, bit, 1);
  2677. (* copy pixel to rest of bottom row *)
  2678. InitMode(m, srcCopy); Bind(m, img.fmt, img.fmt);
  2679. IF (bit = 0) & (img.fmt.bpp MOD 8 = 0) THEN (* use simple address calculation *)
  2680. bb := img.fmt.bpp DIV 8; aa := adr + bb; x := llx+1;
  2681. WHILE x < urx DO
  2682. m.transfer(m, adr, 0, aa, 0, 1);
  2683. INC(aa, bb); INC(x)
  2684. END
  2685. ELSE
  2686. bb := bit + img.fmt.bpp; aa := adr + bb DIV 8; bb := bb MOD 8; x := llx+1;
  2687. WHILE x < urx DO
  2688. m.transfer(m, adr, bit, aa, bb, 1);
  2689. bb := bb + img.fmt.bpp; aa := aa + bb DIV 8; bb := bb MOD 8; INC(x)
  2690. END
  2691. END;
  2692. (* now copy bottom row to others *)
  2693. INC(lly); aa := adr + img.bpr;
  2694. WHILE lly < ury DO
  2695. m.transfer(m, adr, bit, aa, bit, urx - llx);
  2696. INC(lly); INC(aa, img.bpr)
  2697. END
  2698. ELSE (* fill pixel by pixel *)
  2699. WHILE lly < ury DO
  2700. x := llx; aa := adr; bb := bit;
  2701. WHILE x < urx DO
  2702. mode.transfer(mode, ADDRESSOF(pix[0]), 0, aa, bb, 1);
  2703. bb := bb + img.fmt.bpp; aa := aa + bb DIV 8; bb := bb MOD 8; INC(x)
  2704. END;
  2705. INC(lly); INC(adr, img.bpr)
  2706. END
  2707. END
  2708. END
  2709. END Fill;
  2710. (** clear image **)
  2711. PROCEDURE Clear* (img: Image);
  2712. VAR mode: Mode;
  2713. BEGIN
  2714. InitMode(mode, clear);
  2715. Bind(mode, PixelFormat, img.fmt);
  2716. Fill(img, 0, 0, img.width, img.height, Zero, mode)
  2717. END Clear;
  2718. (** get several pixels and store them in array in requested format **)
  2719. PROCEDURE GetPixels* (img: Image; x, y, w: LONGINT; VAR fmt: Format; VAR buf: ARRAY OF CHAR; ofs : LONGINT; VAR mode: Mode);
  2720. VAR sbit: LONGINT; sadr: ADDRESS;
  2721. BEGIN
  2722. ASSERT((0 <= x) & (x + w <= img.width) & (0 <= y) & (y <= img.height), 100);
  2723. ASSERT(ofs + w * fmt.bpp DIV 8 <= LEN(buf), 101);
  2724. Bind(mode, img.fmt, fmt);
  2725. sbit := x * img.fmt.bpp; sadr := img.adr + y * img.bpr + sbit DIV 8; sbit := sbit MOD 8;
  2726. mode.transfer(mode, sadr, sbit, ADDRESSOF(buf[ofs]), 0, w)
  2727. END GetPixels;
  2728. (** put several pixels from array in given format into image **)
  2729. PROCEDURE PutPixels* (img: Image; x, y, w: LONGINT; VAR fmt: Format; VAR buf: ARRAY OF CHAR; ofs : LONGINT; VAR mode: Mode);
  2730. VAR dbit: LONGINT; dadr: ADDRESS;
  2731. BEGIN
  2732. ASSERT((0 <= x) & (x + w <= img.width) & (0 <= y) & (y <= img.height), 100);
  2733. ASSERT(ofs + w * fmt.bpp DIV 8 <= LEN(buf), 101);
  2734. dbit := x * img.fmt.bpp; dadr := img.adr + y * img.bpr + dbit DIV 8; dbit := dbit MOD 8;
  2735. Bind(mode, fmt, img.fmt);
  2736. mode.transfer(mode, ADDRESSOF(buf[ofs]), 0, dadr, dbit, w)
  2737. END PutPixels;
  2738. (** copy rectangular area to the same or another image in specified mode **)
  2739. PROCEDURE Copy* (src, dst: Image; llx, lly, urx, ury, dx, dy: LONGINT; VAR mode: Mode);
  2740. VAR w, h, sbit, dbit, slen, sb, db, len, l, w1, h1: LONGINT; sadr, dadr, sa, da: ADDRESS;
  2741. BEGIN
  2742. ASSERT((0 <= llx) & (llx <= urx) & (urx <= src.width) & (0 <= lly) & (lly <= ury) & (ury <= src.height), 100);
  2743. ASSERT((0 <= dx) & (dx + urx - llx <= dst.width) & (0 <= dy) & (dy + ury - lly <= dst.height), 101);
  2744. Bind(mode, src.fmt, dst.fmt);
  2745. w := urx - llx; h := ury - lly;
  2746. IF (src # dst) OR (lly > dy) OR (lly = dy) & ((llx > dx) OR (urx <= dx)) THEN (* copy lines bottom-up *)
  2747. sbit := llx * src.fmt.bpp; sadr := src.adr + lly * src.bpr + sbit DIV 8; sbit := sbit MOD 8;
  2748. dbit := dx * dst.fmt.bpp; dadr := dst.adr + dy * dst.bpr + dbit DIV 8; dbit := dbit MOD 8;
  2749. WHILE h > 0 DO
  2750. mode.transfer(mode, sadr, sbit, dadr, dbit, w);
  2751. INC(sadr, src.bpr); INC(dadr, dst.bpr); DEC(h)
  2752. END
  2753. ELSIF lly < dy THEN (* copy lines top-down *)
  2754. sbit := llx * src.fmt.bpp; sadr := src.adr + ury * src.bpr + sbit DIV 8; sbit := sbit MOD 8;
  2755. dbit := dx * dst.fmt.bpp; dadr := dst.adr + (dy + h) * dst.bpr + dbit DIV 8; dbit := dbit MOD 8;
  2756. WHILE h > 0 DO
  2757. DEC(sadr, src.bpr); DEC(dadr, dst.bpr); DEC(h);
  2758. mode.transfer(mode, sadr, sbit, dadr, dbit, w)
  2759. END
  2760. ELSIF llx # dx THEN (* uh oh! overlapping spans *) (* could use CopyN32 with reversed direction flag CLD, see http://en.wikibooks.org/wiki/X86_Assembly/Data_Transfer#Move_String *)
  2761. slen := dx + w - urx; (* maximal span length guaranteeing non-overlapping spans *)
  2762. sbit := urx * src.fmt.bpp; sadr := src.adr + lly * src.bpr + sbit DIV 8; sbit := sbit MOD 8;
  2763. dbit := (dx + w) * dst.fmt.bpp; dadr := dst.adr + dy * dst.bpr + dbit DIV 8; dbit := dbit MOD 8;
  2764. WHILE h > 0 DO
  2765. sa := sadr; sb := sbit; da := dadr; db := dbit; len := w;
  2766. WHILE len > 0 DO
  2767. l := slen;
  2768. IF l > len THEN l := len END;
  2769. DEC(sb, l * src.fmt.bpp); INC(sa, sb DIV 8); sb := sb MOD 8;
  2770. DEC(db, l * dst.fmt.bpp); INC(da, db DIV 8); db := db MOD 8;
  2771. mode.transfer(mode, sa, sb, da, db, l);
  2772. DEC(len, l)
  2773. END;
  2774. INC(sadr, src.bpr); INC(dadr, dst.bpr); DEC(h)
  2775. END
  2776. END
  2777. END Copy;
  2778. (** replicate pattern within rectangular area of image using given mode **)
  2779. PROCEDURE FillPattern* (pat, dst: Image; llx, lly, urx, ury, px, py: LONGINT; VAR mode: Mode);
  2780. VAR pw, ph, olx, oby, ilx, olw, irw, dy, sy, dx, sx, ty: LONGINT;
  2781. BEGIN
  2782. ASSERT((0 <= llx) & (llx <= urx) & (urx <= dst.width) & (0 <= lly) & (lly <= ury) & (ury <= dst.height), 100);
  2783. pw := pat.width; ph := pat.height;
  2784. olx := px + (llx - px) DIV pw * pw;
  2785. oby := py + (lly - py) DIV ph * ph;
  2786. ilx := olx + pw; olw := llx - olx;
  2787. irw := (urx - px) MOD pw;
  2788. IF urx - irw < ilx THEN irw := olw + urx - llx END;
  2789. dy := lly; sy := lly - oby;
  2790. IF (oby < lly) & (oby + ph <= ury) THEN
  2791. dx := llx; sx := olw;
  2792. IF (olx < llx) & (ilx <= urx) THEN
  2793. Copy(pat, dst, sx, sy, pw, ph, llx, lly, mode);
  2794. dx := ilx; sx := 0
  2795. END;
  2796. WHILE dx + pw <= urx DO
  2797. Copy(pat, dst, 0, sy, pw, ph, dx, lly, mode);
  2798. INC(dx, pw)
  2799. END;
  2800. IF dx < urx THEN
  2801. Copy(pat, dst, sx, sy, irw, ph, dx, lly, mode)
  2802. END;
  2803. dy := oby + ph; sy := 0
  2804. END;
  2805. WHILE dy + ph <= ury DO
  2806. dx := llx; sx := olw;
  2807. IF (olx < llx) & (ilx <= urx) THEN
  2808. Copy(pat, dst, sx, 0, pw, ph, llx, dy, mode);
  2809. dx := ilx; sx := 0
  2810. END;
  2811. WHILE dx + pw <= urx DO
  2812. Copy(pat, dst, 0, 0, pw, ph, dx, dy, mode);
  2813. INC(dx, pw)
  2814. END;
  2815. IF dx < urx THEN
  2816. Copy(pat, dst, sx, 0, irw, ph, dx, dy, mode)
  2817. END;
  2818. INC(dy, ph)
  2819. END;
  2820. IF dy < ury THEN
  2821. ty := sy + ury - dy;
  2822. dx := llx; sx := olw;
  2823. IF (olx < llx) & (ilx <= urx) THEN
  2824. Copy(pat, dst, sx, sy, pw, ty, llx, dy, mode);
  2825. dx := ilx; sx := 0
  2826. END;
  2827. WHILE dx + pw <= urx DO
  2828. Copy(pat, dst, 0, sy, pw, ty, dx, dy, mode);
  2829. INC(dx, pw)
  2830. END;
  2831. IF dx < urx THEN
  2832. Copy(pat, dst, sx, sy, irw, ty, dx, dy, mode)
  2833. END
  2834. END
  2835. END FillPattern;
  2836. (** darken image while maintaining coverage **)
  2837. PROCEDURE Darken* (img: Image; factor: REAL);
  2838. VAR s, i, j, k, y, x, bit: LONGINT; adr: ADDRESS; clamp: ARRAY 256 OF CHAR; pix: Pixel;
  2839. BEGIN
  2840. s := ABS(ENTIER(255*factor + 0.5));
  2841. IF (s # 255) & (img.fmt.components # {alpha}) THEN
  2842. i := 256; j := 256*s;
  2843. REPEAT
  2844. DEC(i); DEC(j, s); k := j DIV 255;
  2845. IF k <= 255 THEN clamp[i] := CHR(k) ELSE clamp[i] := 0FFX END
  2846. UNTIL i = 0;
  2847. y := 0;
  2848. WHILE y < img.height DO
  2849. x := 0; adr := img.adr + y * img.bpr; bit := 0;
  2850. WHILE x < img.width DO
  2851. img.fmt.unpack(img.fmt, adr, bit, pix);
  2852. pix[r] := clamp[ORD(pix[r])]; pix[g] := clamp[ORD(pix[g])]; pix[b] := clamp[ORD(pix[b])];
  2853. img.fmt.pack(img.fmt, adr, bit, pix);
  2854. bit := bit + img.fmt.bpp; INC(adr, bit); bit := bit MOD 8;
  2855. INC(x)
  2856. END;
  2857. INC(y)
  2858. END
  2859. END
  2860. END Darken;
  2861. (** fade image **)
  2862. PROCEDURE Fade* (img: Image; factor: REAL);
  2863. VAR s, i, j, k, y, x, bit: LONGINT; adr: ADDRESS; clamp: ARRAY 256 OF CHAR; pix: Pixel;
  2864. BEGIN
  2865. s := ABS(ENTIER(255*factor + 0.5));
  2866. IF s = 0 THEN
  2867. Clear(img)
  2868. ELSIF s # 255 THEN
  2869. i := 256; j := 256*s;
  2870. REPEAT
  2871. DEC(i); DEC(j, s); k := j DIV 255;
  2872. IF k <= 255 THEN clamp[i] := CHR(k) ELSE clamp[i] := 0FFX END
  2873. UNTIL i = 0;
  2874. y := 0;
  2875. WHILE y < img.height DO
  2876. x := 0; adr := img.adr + y * img.bpr; bit := 0;
  2877. WHILE x < img.width DO
  2878. img.fmt.unpack(img.fmt, adr, bit, pix);
  2879. pix[r] := clamp[ORD(pix[r])]; pix[g] := clamp[ORD(pix[g])];
  2880. pix[b] := clamp[ORD(pix[b])]; pix[a] := clamp[ORD(pix[a])];
  2881. img.fmt.pack(img.fmt, adr, bit, pix);
  2882. bit := bit + img.fmt.bpp; INC(adr, bit); bit := bit MOD 8;
  2883. INC(x)
  2884. END;
  2885. INC(y)
  2886. END
  2887. END
  2888. END Fade;
  2889. (** make image brighter and more transparent; Opaque(I, f) = Darken(Fade(I, f), 1/f) **)
  2890. PROCEDURE Opaque* (img: Image; factor: REAL);
  2891. VAR s, i, j, k, y, x, bit: LONGINT; adr: ADDRESS; clamp: ARRAY 256 OF CHAR; pix: Pixel;
  2892. BEGIN
  2893. s := ABS(ENTIER(255*factor + 0.5));
  2894. IF s = 0 THEN
  2895. Clear(img)
  2896. ELSIF s # 255 THEN
  2897. i := 256; j := 256*s;
  2898. REPEAT
  2899. DEC(i); DEC(j, s); k := j DIV 255;
  2900. IF k <= 255 THEN clamp[i] := CHR(k) ELSE clamp[i] := 0FFX END
  2901. UNTIL i = 0;
  2902. y := 0;
  2903. WHILE y < img.height DO
  2904. x := 0; adr := img.adr + y * img.bpr; bit := 0;
  2905. WHILE x < img.width DO
  2906. img.fmt.unpack(img.fmt, adr, bit, pix);
  2907. pix[a] := clamp[ORD(pix[a])];
  2908. img.fmt.pack(img.fmt, adr, bit, pix);
  2909. bit := bit + img.fmt.bpp; INC(adr, bit); bit := bit MOD 8;
  2910. INC(x)
  2911. END;
  2912. INC(y)
  2913. END
  2914. END
  2915. END Opaque;
  2916. (** add components of two (faded) images **)
  2917. PROCEDURE Add* (i, j, res: Image);
  2918. VAR y, x, ibit, jbit, rbit, k: LONGINT; iadr, jadr, radr: ADDRESS; ipix, jpix, rpix: Pixel;
  2919. BEGIN
  2920. ASSERT((i.width = j.width) & (i.height = j.height) & (i.width <= res.width) & (i.height <= res.height), 100);
  2921. y := 0;
  2922. WHILE y < i.height DO
  2923. x := 0; iadr := i.adr + y * i.bpr; ibit := 0; jadr := j.adr + y * j.bpr; jbit := 0; radr := res.adr + y * res.bpr; rbit := 0;
  2924. WHILE x < i.width DO
  2925. i.fmt.unpack(i.fmt, iadr, ibit, ipix); j.fmt.unpack(j.fmt, jadr, jbit, jpix);
  2926. FOR k := 0 TO 3 DO
  2927. rpix[k] := Clamp[ORD(ipix[k]) + ORD(jpix[k])]
  2928. END;
  2929. res.fmt.pack(res.fmt, radr, rbit, rpix);
  2930. ibit := ibit + i.fmt.bpp; INC(iadr, ibit); ibit := ibit MOD 8;
  2931. jbit := jbit + j.fmt.bpp; INC(jadr, jbit); jbit := jbit MOD 8;
  2932. rbit := rbit + res.fmt.bpp; INC(radr, rbit); rbit := rbit MOD 8;
  2933. INC(x)
  2934. END;
  2935. INC(y)
  2936. END
  2937. END Add;
  2938. (** copy image to another using error diffusion dithering (Floyd-Steinberg) **)
  2939. PROCEDURE Dither* (src, dst: Image);
  2940. TYPE
  2941. error = RECORD r, g, b: LONGINT END;
  2942. VAR
  2943. e351: POINTER TO ARRAY OF error;
  2944. y, x, sb, db, ex, e, e3, e5: LONGINT;
  2945. sadr, dadr, sa, da: ADDRESS;
  2946. e7, e51, e1: error;
  2947. spix, dpix: Pixel;
  2948. BEGIN
  2949. ASSERT((src.width <= dst.width) & (src.height <= dst.height), 100);
  2950. NEW(e351, src.width+2); (* accumulated error for next row *)
  2951. y := 0; sadr := src.adr; dadr := dst.adr;
  2952. WHILE y < src.height DO (* scan from left to right *)
  2953. e7.r := 0; e7.g := 0; e7.b := 0;
  2954. e51.r := 0; e51.g := 0; e51.b := 0;
  2955. e1.r := 0; e1.g := 0; e1.b := 0;
  2956. x := 0; sa := sadr; sb := 0; da := dadr; db := 0;
  2957. WHILE x < src.width DO
  2958. ex := x+1;
  2959. src.fmt.unpack(src.fmt, sa, sb, spix);
  2960. spix[r] := Clamp[200H + ORD(spix[r]) + e351[ex].r + e7.r];
  2961. spix[g] := Clamp[200H + ORD(spix[g]) + e351[ex].g + e7.g];
  2962. spix[b] := Clamp[200H + ORD(spix[b]) + e351[ex].b + e7.b];
  2963. dst.fmt.pack(dst.fmt, da, db, spix);
  2964. dst.fmt.unpack(dst.fmt, da, db, dpix);
  2965. e := ORD(spix[r]) - ORD(dpix[r]); e3 := 3*e DIV 16; e5 := 5*e DIV 16;
  2966. e7.r := 7*e DIV 16; e351[x].r := e3 + e51.r; e51.r := e5 + e1.r; e1.r := e - e3 - e5 - e7.r;
  2967. e := ORD(spix[g]) - ORD(dpix[g]); e3 := 3*e DIV 16; e5 := 5*e DIV 16;
  2968. e7.g := 7*e DIV 16; e351[x].g := e3 + e51.g; e51.g := e5 + e1.g; e1.g := e - e3 - e5 - e7.g;
  2969. e := ORD(spix[b]) - ORD(dpix[b]); e3 := 3*e DIV 16; e5 := 5*e DIV 16;
  2970. e7.b := 7*e DIV 16; e351[x].b := e3 + e51.b; e51.b := e5 + e1.b; e1.b := e - e3 - e5 - e7.b;
  2971. sb := sb + src.fmt.bpp; INC(sa, sb DIV 8); sb := sb MOD 8;
  2972. db := db + dst.fmt.bpp; INC(da, db DIV 8); db := db MOD 8;
  2973. x := ex
  2974. END;
  2975. INC(y); INC(sadr, src.bpr); INC(dadr, dst.bpr);
  2976. IF y < src.height THEN (* scan from right to left *)
  2977. e351[x] := e51;
  2978. e7.r := 0; e7.g := 0; e7.b := 0;
  2979. e51.r := 0; e51.g := 0; e51.b := 0;
  2980. e1.r := 0; e1.g := 0; e1.b := 0;
  2981. INC(sa, src.bpr); INC(da, dst.bpr);
  2982. WHILE x > 0 DO
  2983. ex := x; DEC(x);
  2984. sb := sb - src.fmt.bpp; INC(sa, sb DIV 8); sb := sb MOD 8;
  2985. db := db - dst.fmt.bpp; INC(da, db DIV 8); db := db MOD 8;
  2986. src.fmt.unpack(src.fmt, sa, sb, spix);
  2987. spix[r] := Clamp[200H + ORD(spix[r]) + e351[ex].r + e7.r];
  2988. spix[g] := Clamp[200H + ORD(spix[g]) + e351[ex].g + e7.g];
  2989. spix[b] := Clamp[200H + ORD(spix[b]) + e351[ex].b + e7.b];
  2990. dst.fmt.pack(dst.fmt, da, db, spix);
  2991. dst.fmt.unpack(dst.fmt, da, db, dpix);
  2992. INC(ex);
  2993. e := ORD(spix[r]) - ORD(dpix[r]); e3 := 3*e DIV 16; e5 := 5*e DIV 16;
  2994. e7.r := 7*e DIV 16; e351[x].r := e3 + e51.r; e51.r := e5 + e1.r; e1.r := e - e3 - e5 - e7.r;
  2995. e := ORD(spix[g]) - ORD(dpix[g]); e3 := 3*e DIV 16; e5 := 5*e DIV 16;
  2996. e7.g := 7*e DIV 16; e351[x].g := e3 + e51.g; e51.g := e5 + e1.g; e1.g := e - e3 - e5 - e7.g;
  2997. e := ORD(spix[b]) - ORD(dpix[b]); e3 := 3*e DIV 16; e5 := 5*e DIV 16;
  2998. e7.b := 7*e DIV 16; e351[x].b := e3 + e51.b; e51.b := e5 + e1.b; e1.b := e - e3 - e5 - e7.b
  2999. END;
  3000. e351[1] := e51;
  3001. INC(y); INC(sadr, src.bpr); INC(dadr, dst.bpr)
  3002. END
  3003. END
  3004. END Dither;
  3005. (**--- File I/O ---**)
  3006. (** write image to file rider **)
  3007. PROCEDURE Write* (VAR fr: Streams.Writer; img: Image);
  3008. VAR m: Image; h, w, len: LONGINT; adr, aa: ADDRESS; buf: ARRAY 256 OF CHAR;
  3009. SrcCopy:Mode;
  3010. BEGIN
  3011. InitMode(SrcCopy, srcCopy);
  3012. IF ~(img.fmt.code IN {a1..bgra8888,p16}) THEN
  3013. NEW(m);
  3014. IF img.fmt.components = {color} THEN Create(m, img.width, img.height, BGR888)
  3015. ELSIF img.fmt.components = {alpha} THEN Create(m, img.width, img.height, A8)
  3016. ELSIF img.fmt.components = {index} THEN Create(m, img.width, img.height, D8)
  3017. ELSE Create(m, img.width, img.height, BGRA8888)
  3018. END;
  3019. Copy(img, m, 0, 0, img.width, img.height, 0, 0, SrcCopy);
  3020. img := m
  3021. END;
  3022. fr.RawNum(2); (* version *)
  3023. fr.RawNum(img.fmt.code);
  3024. fr.RawNum(img.width); fr.RawNum(img.height);
  3025. fr.RawNum(ABS(img.bpr));
  3026. h := img.height; adr := img.adr;
  3027. WHILE h > 0 DO
  3028. w := ABS(img.bpr); aa := adr;
  3029. WHILE w > 0 DO
  3030. len := 256;
  3031. IF len > w THEN len := w END;
  3032. SYSTEM.MOVE(aa, ADDRESSOF(buf[0]), len);
  3033. fr.Bytes(buf, 0, len);
  3034. DEC(w, len); INC(aa, len)
  3035. END;
  3036. DEC(h); INC(adr, img.bpr)
  3037. END;
  3038. IF img.fmt.code IN {p8,p16} THEN
  3039. fr.RawNum(img.fmt.pal.used);
  3040. len := 0;
  3041. WHILE len < img.fmt.pal.used DO
  3042. fr.Char(img.fmt.pal.col[len, r]);
  3043. fr.Char(img.fmt.pal.col[len, g]);
  3044. fr.Char(img.fmt.pal.col[len, b]);
  3045. INC(len)
  3046. END
  3047. END;
  3048. fr.Update (* optional *)
  3049. END Write;
  3050. (** read image from file rider **)
  3051. PROCEDURE Read* (VAR fr: Streams.Reader; img: Image);
  3052. VAR ver, code, w, h, bpr, len, bytesRead: LONGINT; adr, aa: ADDRESS; fmt: Format; buf: ARRAY 256 OF CHAR; used: LONGINT;
  3053. BEGIN
  3054. ASSERT(img#NIL,100);
  3055. fr.RawNum(ver); (* know version 1&2*)
  3056. ASSERT(ver IN {1,2},101);
  3057. fr.RawNum(code);
  3058. CASE code OF
  3059. | a1: fmt := A1
  3060. | a8: fmt := A8
  3061. | p8: InitFormat(fmt, p8, 8, 1, {index}, NIL, PackP8, UnpackP8)
  3062. | d8: fmt := D8
  3063. | p16: InitFormat(fmt, p16, 16, 2, {index}, NIL, PackP16, UnpackP16);
  3064. | bgr555: fmt := BGR555
  3065. | bgr565: fmt := BGR565
  3066. | bgr466: fmt := BGR466
  3067. | bgr888: fmt := BGR888
  3068. | bgra8888: fmt := BGRA8888
  3069. END;
  3070. fr.RawNum(w); fr.RawNum(h);
  3071. Create(img, SHORT(w), SHORT(h), fmt);
  3072. fr.RawNum(bpr);
  3073. ASSERT(bpr <= img.bpr);
  3074. adr := img.adr;
  3075. WHILE h > 0 DO
  3076. w := bpr; aa := adr;
  3077. WHILE w > 0 DO
  3078. len := 256;
  3079. IF len > w THEN len := w END;
  3080. fr.Bytes(buf, 0, len, bytesRead); (* ignore bytesRead *)
  3081. SYSTEM.MOVE(ADDRESSOF(buf[0]), aa, len);
  3082. DEC(w, len); INC(aa, len)
  3083. END;
  3084. DEC(h); INC(adr, img.bpr)
  3085. END;
  3086. IF code IN {p8,p16} THEN
  3087. fr.RawNum(used);
  3088. len := 0;
  3089. NEW(img.fmt.pal); img.fmt.pal.Init(used);
  3090. WHILE len < used DO
  3091. fr.Char(img.fmt.pal.col[len, r]);
  3092. fr.Char(img.fmt.pal.col[len, g]);
  3093. fr.Char(img.fmt.pal.col[len, b]);
  3094. img.fmt.pal.col[len, a] := 0FFX;
  3095. INC(len)
  3096. END;
  3097. InitPalette(img.fmt.pal, used, 4)
  3098. END
  3099. END Read;
  3100. (*--- Initialization ---*)
  3101. PROCEDURE InitBitTables;
  3102. VAR b, i: LONGINT;
  3103. BEGIN
  3104. FOR b := 0 TO 0FFH DO
  3105. FOR i := 0 TO 7 DO
  3106. IF ODD(ASH(b, -i)) THEN
  3107. Bit[b, i] := TRUE; Set[b, i] := CHR(b); Clr[b, i] := CHR(b - ASH(1, i))
  3108. ELSE
  3109. Bit[b, i] := FALSE; Set[b, i] := CHR(b + ASH(1, i)); Clr[b, i] := CHR(b)
  3110. END
  3111. END
  3112. END
  3113. END InitBitTables;
  3114. PROCEDURE InitClamp;
  3115. VAR i: LONGINT;
  3116. BEGIN
  3117. FOR i := 0 TO 1FFH DO Clamp[i] := 0X END;
  3118. FOR i := 0 TO 0FFH DO Clamp[200H+i] := CHR(i) END;
  3119. FOR i := 300H TO 4FFH DO Clamp[i] := 0FFX END
  3120. END InitClamp;
  3121. PROCEDURE ToggleMMX*;
  3122. BEGIN
  3123. MMXenabled := ~MMXenabled
  3124. END ToggleMMX;
  3125. PROCEDURE ToggleSSE2*;
  3126. BEGIN
  3127. SSE2enabled := ~SSE2enabled;
  3128. KernelLog.String("SSE2 toggled! Is now: "); KernelLog.Boolean(SSE2enabled);KernelLog.Ln;
  3129. END ToggleSSE2;
  3130. (** Map a color value to an 8-bit CLUT index. Only used if format = index8. *)
  3131. PROCEDURE ColorToIndex*(col: LONGINT): LONGINT;
  3132. BEGIN
  3133. (* default implementation is not very useful and should be overridden. *)
  3134. RETURN SYSTEM.VAL(LONGINT,
  3135. SYSTEM.VAL(SET, ASH(col, 7-23)) * {5..7} +
  3136. SYSTEM.VAL(SET, ASH(col, 4-15)) * {2..4} +
  3137. SYSTEM.VAL(SET, ASH(col, 1-7)) * {0..1})
  3138. END ColorToIndex;
  3139. (** Map an 8-bit CLUT index to a color value. Only used if format = index8. *)
  3140. PROCEDURE IndexToColor*(index: LONGINT): LONGINT;
  3141. BEGIN
  3142. (* default implementation is not very useful and should be overridden. *)
  3143. RETURN
  3144. ASH(SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, index) * {5..7}), 23-7) +
  3145. ASH(SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, index) * {2..4}), 15-4) +
  3146. ASH(SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, index) * {0..1}), 7-1)
  3147. END IndexToColor;
  3148. BEGIN
  3149. MMXenabled := 23 IN Machine.features;
  3150. SSE2enabled := Machine.SSE2Support;
  3151. (* plugin := Displays.registry.Await(""); (* assume only one system-wide D8 display driver *)
  3152. d8display := plugin(Displays.Display); *)
  3153. InitFormat(A1, a1, 1, 1, {alpha}, NIL, PackA1, UnpackA1);
  3154. InitFormat(A8, a8, 8, 1, {alpha}, NIL, PackA8, UnpackA8);
  3155. InitFormat(D8, d8, 8, 1, {index}, NIL, PackD8, UnpackD8);
  3156. InitFormat(BGR555, bgr555, 16, 2, {color}, NIL, PackBGR555, UnpackBGR555);
  3157. InitFormat(BGR565, bgr565, 16, 2, {color}, NIL, PackBGR565, UnpackBGR565);
  3158. InitFormat(BGR466, bgr466, 16, 2, {color}, NIL, PackBGR466, UnpackBGR466);
  3159. InitFormat(BGR888, bgr888, 24, 4, {color}, NIL, PackBGR888, UnpackBGR888);
  3160. InitFormat(BGRA8888, bgra8888, 32, 4, {color, alpha}, NIL, PackBGRA8888, UnpackBGRA8888);
  3161. PixelFormat := BGRA8888;
  3162. Zero[0] := 0X; Zero[1] := 0X; Zero[2] := 0X; Zero[3] := 0X;
  3163. InitBitTables; InitClamp
  3164. END Raster.
  3165. (**
  3166. Remarks
  3167. 1. Images
  3168. While many applications wish to handle images of any kind without having to care about details, other applications need low-level access to image interna for maximum effiency. With this in mind, the Images module provides an abstract procedural interface but also discloses low-level information to those clients needing it:
  3169. * an image references a contiguous block of memory holding pixel data
  3170. * the point of reference is the address of the pixel in the lower-left corner
  3171. * pixels are organized in rows (either bottom-up or top-down)
  3172. * rows can be aligned to an arbitrary number of bytes
  3173. * the leftmost pixel in a row has the lowest address of all pixels in that row
  3174. * every pixel uses the same number of bits
  3175. Memory for images can be automatically allocated by using Create(). Alternatively, an image can be initialized on an existing memory block (Init(), InitBuf()) or even on part of an other image (InitRect()).
  3176. 2. Pixels
  3177. A general pixel pix[] contains four components (in range 0X..255X), specifying red, green, blue, and alpha value of the pixel and accessable as pix[r], pix[g], pix[b] and pix[a]. Note that in order to speed up compositing operations, the alpha value is premultiplied into the color components. Example: a red pixel with 50% coverage can be initialized with SetRGBA(pix, 255, 0, 0, 127), after which pix[r]=pix[a]=7FX and pix[g]=pix[b]=0X. Use GetRGBA() to recover the original color and alpha values.
  3178. 3. Palettes
  3179. Many bitmap images and Oberon display drivers use some kind of indexed format to store colors, i.e. the value stored in the bitmap serves as an index into an array of colors. A Palette stores up to 256 colors as an array of pixels, making the mapping of an index to the corresponding color straightforward. To speed up the inverse mapping from an RGB triple to an index with PaletteIndex(), additional data is initialized when InitPalette() is called. Use ComputePalette() to compute a palette that best approximates the colors in a given image (e.g. before quantizing it to indexed format).
  3180. 4. Formats
  3181. While general pixels accurately describe color and alpha information, they use a lot of memory (32 bits). Most images therefore only store part of that information. A Format record describes how pixels are represented within an image. It contains
  3182. * the number of bits used per pixel (must be 1, 2, 4, 8, 16, 24 or 32)
  3183. * the set of components stored in a pixel (color, index and/or alpha)
  3184. * a palette if the format uses one
  3185. * procedures for storing (packing) and loading (unpacking) a general pixel
  3186. The pack and unpack procedures are given an address and a bit number specifying where the pixel is located in memory, with bit numbers ascending from left to right (although a format is free to choose any bit ordering within a pixel).
  3187. 5. Predefined Formats
  3188. The following global variables contain formats which are special and have a unique code number identifying them. Besides, most operations have better performance if acting on images using them.
  3189. * A1 (code a1): one bit alpha, MSB leftmost (corresponds to Oberon display patterns)
  3190. * A8 (code a8): 8 bit alpha (mainly for anti-aliased character patterns)
  3191. * - (code p8): 8 bit indexed with custom palette (Oberon pictures, use InitPaletteFormat to initialize)
  3192. * D8 (code d8): 8 bit indexed with display palette (no palette structure attached)
  3193. * - (code p16): 16 bit indexed with 16bit Palette. This type is, e.g., often used in medical imaging (DICOM-3 standard) (* PH 2004 *)
  3194. * BGR555 (code bgr555), BGR565 (code bgr565), BGR466 (code bgr466): 16 bit hi-color
  3195. * BGR888 (code bgr888): 24 bit true-color
  3196. * BGRA8888 (code bgra8888), PixelFormat: 32 bit true-color with alpha channel (general pixel format)
  3197. Procedure DisplayFormat() returns the format that best matches the supplied kind of display transfer format. The returned image format is preferably used for allocating shadow bitmaps.
  3198. 6. Compositing
  3199. Most operations require a transfer mode for specifying how source and destination pixels should be combined when alpha information is present. The following compositing operations are supported:
  3200. * clear: destination becomes black and completely transparent
  3201. * srcCopy: source completely replaces destination (cf. Display.replace)
  3202. * dstCopy: no effect
  3203. * srcOverDst: source replaces destination where source is opaque (cf. Display.paint)
  3204. * dstOverSrc: destination replaces source where destination is opaque
  3205. * srcInDst: source where destination is opaque
  3206. * dstInSrc: destination where source is opaque
  3207. * srcWithoutDest*: source is cleared where destination is opaque
  3208. * dstWithoutSrc*: destination is cleared where source is opaque
  3209. * srcAtopDst*: source replaces destination where destination is opaque
  3210. * dstAtopSrc*: destination replaces source where source is opaque
  3211. * srcXorDst*: destination is cleared where both source and destination are opaque (cf. Display.invert)
  3212. A transfer mode is initialized with a compositing operation and optionally with a color. (The color is used when the source is a pure alpha format which doesn't contain any color of its own.) An initialized mode can be bound to a source and destination format by calling Bind(), by which the mode's transfer procedure is set appropriately. A transfer procedure unpacks pixels from source and destination, blends them according to the compositing operation, and packs the resulting pixel in the destination. Bind() chooses an optimal transfer procedure for the given combination of compositing operation, source format, and destination format.
  3213. 7. Internalization and Externalization
  3214. Images can be loaded from file and stored to file using one of many popular image file formats. The Load() and Store() procedures rely on a section 'ImageFormats' in the Aos registry. This section contains a list of file types that are associated with command procedures. When one of these commands is called, it should initialize the global 'LoadProc' and 'StoreProc' variables. These, when called, should read an image from or write an image to the file and set 'done' to TRUE if successful.
  3215. **)