ARM.Raster.Mod 118 KB

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