AMD64.Raster.Mod 107 KB

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