I386.Raster.Mod 112 KB

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