GR32.pas 152 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743
  1. unit GR32;
  2. (* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1 or LGPL 2.1 with linking exception
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * Alternatively, the contents of this file may be used under the terms of the
  16. * Free Pascal modified version of the GNU Lesser General Public License
  17. * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
  18. * of this license are applicable instead of those above.
  19. * Please see the file LICENSE.txt for additional information concerning this
  20. * license.
  21. *
  22. * The Original Code is Graphics32
  23. *
  24. * The Initial Developer of the Original Code is
  25. * Alex A. Denisov
  26. *
  27. * Portions created by the Initial Developer are Copyright (C) 2000-2009
  28. * the Initial Developer. All Rights Reserved.
  29. *
  30. * Contributor(s):
  31. * Michael Hansen <[email protected]>
  32. * Andre Beckedorf <[email protected]>
  33. * Mattias Andersson <[email protected]>
  34. * J. Tulach <tulach at position.cz>
  35. * Jouni Airaksinen <markvera at spacesynth.net>
  36. * Timothy Weber <teejaydub at users.sourceforge.net>
  37. *
  38. * ***** END LICENSE BLOCK ***** *)
  39. interface
  40. {$I GR32.inc}
  41. uses
  42. System.Types,
  43. System.UITypes,
  44. System.Classes,
  45. System.SysUtils,
  46. FMX.Controls,
  47. FMX.Graphics;
  48. { Version Control }
  49. const
  50. Graphics32Version = '2.0.0 alpha';
  51. { 32-bit Color }
  52. type
  53. PColor32 = ^TColor32;
  54. TColor32 = type Cardinal;
  55. PColor32Array = ^TColor32Array;
  56. TColor32Array = array [0..0] of TColor32;
  57. TArrayOfColor32 = array of TColor32;
  58. {$IFNDEF RGBA_FORMAT}
  59. TColor32Component = (ccBlue, ccGreen, ccRed, ccAlpha);
  60. {$ELSE}
  61. TColor32Component = (ccRed, ccGreen, ccBlue, ccAlpha);
  62. {$ENDIF}
  63. TColor32Components = set of TColor32Component;
  64. PColor32Entry = ^TColor32Entry;
  65. TColor32Entry = packed record
  66. case Integer of
  67. {$IFNDEF RGBA_FORMAT}
  68. 0: (B, G, R, A: Byte);
  69. {$ELSE}
  70. 0: (R, G, B, A: Byte);
  71. {$ENDIF}
  72. 1: (ARGB: TColor32);
  73. 2: (Planes: array[0..3] of Byte);
  74. 3: (Components: array[TColor32Component] of Byte);
  75. end;
  76. PColor32EntryArray = ^TColor32EntryArray;
  77. TColor32EntryArray = array [0..0] of TColor32Entry;
  78. TArrayOfColor32Entry = array of TColor32Entry;
  79. PPalette32 = ^TPalette32;
  80. TPalette32 = array [Byte] of TColor32;
  81. const
  82. // Some predefined color constants
  83. clBlack32 = TColor32($FF000000);
  84. clDimGray32 = TColor32($FF3F3F3F);
  85. clGray32 = TColor32($FF7F7F7F);
  86. clLightGray32 = TColor32($FFBFBFBF);
  87. clWhite32 = TColor32($FFFFFFFF);
  88. clMaroon32 = TColor32($FF7F0000);
  89. clGreen32 = TColor32($FF007F00);
  90. clOlive32 = TColor32($FF7F7F00);
  91. clNavy32 = TColor32($FF00007F);
  92. clPurple32 = TColor32($FF7F007F);
  93. clTeal32 = TColor32($FF007F7F);
  94. clRed32 = TColor32($FFFF0000);
  95. clLime32 = TColor32($FF00FF00);
  96. clYellow32 = TColor32($FFFFFF00);
  97. clBlue32 = TColor32($FF0000FF);
  98. clFuchsia32 = TColor32($FFFF00FF);
  99. clAqua32 = TColor32($FF00FFFF);
  100. clAliceBlue32 = TColor32($FFF0F8FF);
  101. clAntiqueWhite32 = TColor32($FFFAEBD7);
  102. clAquamarine32 = TColor32($FF7FFFD4);
  103. clAzure32 = TColor32($FFF0FFFF);
  104. clBeige32 = TColor32($FFF5F5DC);
  105. clBisque32 = TColor32($FFFFE4C4);
  106. clBlancheDalmond32 = TColor32($FFFFEBCD);
  107. clBlueViolet32 = TColor32($FF8A2BE2);
  108. clBrown32 = TColor32($FFA52A2A);
  109. clBurlyWood32 = TColor32($FFDEB887);
  110. clCadetblue32 = TColor32($FF5F9EA0);
  111. clChartReuse32 = TColor32($FF7FFF00);
  112. clChocolate32 = TColor32($FFD2691E);
  113. clCoral32 = TColor32($FFFF7F50);
  114. clCornFlowerBlue32 = TColor32($FF6495ED);
  115. clCornSilk32 = TColor32($FFFFF8DC);
  116. clCrimson32 = TColor32($FFDC143C);
  117. clDarkBlue32 = TColor32($FF00008B);
  118. clDarkCyan32 = TColor32($FF008B8B);
  119. clDarkGoldenRod32 = TColor32($FFB8860B);
  120. clDarkGray32 = TColor32($FFA9A9A9);
  121. clDarkGreen32 = TColor32($FF006400);
  122. clDarkGrey32 = TColor32($FFA9A9A9);
  123. clDarkKhaki32 = TColor32($FFBDB76B);
  124. clDarkMagenta32 = TColor32($FF8B008B);
  125. clDarkOliveGreen32 = TColor32($FF556B2F);
  126. clDarkOrange32 = TColor32($FFFF8C00);
  127. clDarkOrchid32 = TColor32($FF9932CC);
  128. clDarkRed32 = TColor32($FF8B0000);
  129. clDarkSalmon32 = TColor32($FFE9967A);
  130. clDarkSeaGreen32 = TColor32($FF8FBC8F);
  131. clDarkSlateBlue32 = TColor32($FF483D8B);
  132. clDarkSlateGray32 = TColor32($FF2F4F4F);
  133. clDarkSlateGrey32 = TColor32($FF2F4F4F);
  134. clDarkTurquoise32 = TColor32($FF00CED1);
  135. clDarkViolet32 = TColor32($FF9400D3);
  136. clDeepPink32 = TColor32($FFFF1493);
  137. clDeepSkyBlue32 = TColor32($FF00BFFF);
  138. clDodgerBlue32 = TColor32($FF1E90FF);
  139. clFireBrick32 = TColor32($FFB22222);
  140. clFloralWhite32 = TColor32($FFFFFAF0);
  141. clGainsBoro32 = TColor32($FFDCDCDC);
  142. clGhostWhite32 = TColor32($FFF8F8FF);
  143. clGold32 = TColor32($FFFFD700);
  144. clGoldenRod32 = TColor32($FFDAA520);
  145. clGreenYellow32 = TColor32($FFADFF2F);
  146. clGrey32 = TColor32($FF808080);
  147. clHoneyDew32 = TColor32($FFF0FFF0);
  148. clHotPink32 = TColor32($FFFF69B4);
  149. clIndianRed32 = TColor32($FFCD5C5C);
  150. clIndigo32 = TColor32($FF4B0082);
  151. clIvory32 = TColor32($FFFFFFF0);
  152. clKhaki32 = TColor32($FFF0E68C);
  153. clLavender32 = TColor32($FFE6E6FA);
  154. clLavenderBlush32 = TColor32($FFFFF0F5);
  155. clLawnGreen32 = TColor32($FF7CFC00);
  156. clLemonChiffon32 = TColor32($FFFFFACD);
  157. clLightBlue32 = TColor32($FFADD8E6);
  158. clLightCoral32 = TColor32($FFF08080);
  159. clLightCyan32 = TColor32($FFE0FFFF);
  160. clLightGoldenRodYellow32= TColor32($FFFAFAD2);
  161. clLightGreen32 = TColor32($FF90EE90);
  162. clLightGrey32 = TColor32($FFD3D3D3);
  163. clLightPink32 = TColor32($FFFFB6C1);
  164. clLightSalmon32 = TColor32($FFFFA07A);
  165. clLightSeagreen32 = TColor32($FF20B2AA);
  166. clLightSkyblue32 = TColor32($FF87CEFA);
  167. clLightSlategray32 = TColor32($FF778899);
  168. clLightSlategrey32 = TColor32($FF778899);
  169. clLightSteelblue32 = TColor32($FFB0C4DE);
  170. clLightYellow32 = TColor32($FFFFFFE0);
  171. clLtGray32 = TColor32($FFC0C0C0);
  172. clMedGray32 = TColor32($FFA0A0A4);
  173. clDkGray32 = TColor32($FF808080);
  174. clMoneyGreen32 = TColor32($FFC0DCC0);
  175. clLegacySkyBlue32 = TColor32($FFA6CAF0);
  176. clCream32 = TColor32($FFFFFBF0);
  177. clLimeGreen32 = TColor32($FF32CD32);
  178. clLinen32 = TColor32($FFFAF0E6);
  179. clMediumAquamarine32 = TColor32($FF66CDAA);
  180. clMediumBlue32 = TColor32($FF0000CD);
  181. clMediumOrchid32 = TColor32($FFBA55D3);
  182. clMediumPurple32 = TColor32($FF9370DB);
  183. clMediumSeaGreen32 = TColor32($FF3CB371);
  184. clMediumSlateBlue32 = TColor32($FF7B68EE);
  185. clMediumSpringGreen32 = TColor32($FF00FA9A);
  186. clMediumTurquoise32 = TColor32($FF48D1CC);
  187. clMediumVioletRed32 = TColor32($FFC71585);
  188. clMidnightBlue32 = TColor32($FF191970);
  189. clMintCream32 = TColor32($FFF5FFFA);
  190. clMistyRose32 = TColor32($FFFFE4E1);
  191. clMoccasin32 = TColor32($FFFFE4B5);
  192. clNavajoWhite32 = TColor32($FFFFDEAD);
  193. clOldLace32 = TColor32($FFFDF5E6);
  194. clOliveDrab32 = TColor32($FF6B8E23);
  195. clOrange32 = TColor32($FFFFA500);
  196. clOrangeRed32 = TColor32($FFFF4500);
  197. clOrchid32 = TColor32($FFDA70D6);
  198. clPaleGoldenRod32 = TColor32($FFEEE8AA);
  199. clPaleGreen32 = TColor32($FF98FB98);
  200. clPaleTurquoise32 = TColor32($FFAFEEEE);
  201. clPaleVioletred32 = TColor32($FFDB7093);
  202. clPapayaWhip32 = TColor32($FFFFEFD5);
  203. clPeachPuff32 = TColor32($FFFFDAB9);
  204. clPeru32 = TColor32($FFCD853F);
  205. clPlum32 = TColor32($FFDDA0DD);
  206. clPowderBlue32 = TColor32($FFB0E0E6);
  207. clRosyBrown32 = TColor32($FFBC8F8F);
  208. clRoyalBlue32 = TColor32($FF4169E1);
  209. clSaddleBrown32 = TColor32($FF8B4513);
  210. clSalmon32 = TColor32($FFFA8072);
  211. clSandyBrown32 = TColor32($FFF4A460);
  212. clSeaGreen32 = TColor32($FF2E8B57);
  213. clSeaShell32 = TColor32($FFFFF5EE);
  214. clSienna32 = TColor32($FFA0522D);
  215. clSilver32 = TColor32($FFC0C0C0);
  216. clSkyblue32 = TColor32($FF87CEEB);
  217. clSlateBlue32 = TColor32($FF6A5ACD);
  218. clSlateGray32 = TColor32($FF708090);
  219. clSlateGrey32 = TColor32($FF708090);
  220. clSnow32 = TColor32($FFFFFAFA);
  221. clSpringgreen32 = TColor32($FF00FF7F);
  222. clSteelblue32 = TColor32($FF4682B4);
  223. clTan32 = TColor32($FFD2B48C);
  224. clThistle32 = TColor32($FFD8BFD8);
  225. clTomato32 = TColor32($FFFF6347);
  226. clTurquoise32 = TColor32($FF40E0D0);
  227. clViolet32 = TColor32($FFEE82EE);
  228. clWheat32 = TColor32($FFF5DEB3);
  229. clWhitesmoke32 = TColor32($FFF5F5F5);
  230. clYellowgreen32 = TColor32($FF9ACD32);
  231. // Some semi-transparent color constants
  232. clTrWhite32 = TColor32($7FFFFFFF);
  233. clTrGray32 = TColor32($7F7F7F7F);
  234. clTrBlack32 = TColor32($7F000000);
  235. clTrRed32 = TColor32($7FFF0000);
  236. clTrGreen32 = TColor32($7F00FF00);
  237. clTrBlue32 = TColor32($7F0000FF);
  238. // Color construction and conversion functions
  239. function Color32(AlphaColor: TAlphaColor): TColor32; overload;
  240. function Color32(R, G, B: Byte; A: Byte = $FF): TColor32; overload;
  241. function Color32(Index: Byte; var Palette: TPalette32): TColor32; overload;
  242. function Gray32(Intensity: Byte; Alpha: Byte = $FF): TColor32; {$IFDEF USEINLINING} inline; {$ENDIF}
  243. function WinColor(Color32: TColor32): TColor;
  244. function ArrayOfColor32(Colors: array of TColor32): TArrayOfColor32;
  245. // Color component access
  246. procedure Color32ToRGB(Color32: TColor32; var R, G, B: Byte);
  247. procedure Color32ToRGBA(Color32: TColor32; var R, G, B, A: Byte);
  248. function Color32Components(R, G, B, A: Boolean): TColor32Components;
  249. function RedComponent(Color32: TColor32): Integer; {$IFDEF USEINLINING} inline; {$ENDIF}
  250. function GreenComponent(Color32: TColor32): Integer; {$IFDEF USEINLINING} inline; {$ENDIF}
  251. function BlueComponent(Color32: TColor32): Integer; {$IFDEF USEINLINING} inline; {$ENDIF}
  252. function AlphaComponent(Color32: TColor32): Integer; {$IFDEF USEINLINING} inline; {$ENDIF}
  253. function Intensity(Color32: TColor32): Integer; {$IFDEF USEINLINING} inline; {$ENDIF}
  254. function InvertColor(Color32: TColor32): TColor32; {$IFDEF USEINLINING} inline; {$ENDIF}
  255. function SetAlpha(Color32: TColor32; NewAlpha: Integer): TColor32; {$IFDEF USEINLINING} inline; {$ENDIF}
  256. procedure ModifyAlpha(var Color32: TColor32; NewAlpha: Byte); {$IFDEF USEINLINING} inline; {$ENDIF}
  257. procedure ScaleAlpha(var Color32: TColor32; Scale: Single); {$IFDEF USEINLINING} inline; {$ENDIF}
  258. // Color space conversion
  259. function HSLtoRGB(H, S, L: Single): TColor32; overload;
  260. procedure RGBtoHSL(RGB: TColor32; out H, S, L : Single); overload;
  261. function HSLtoRGB(H, S, L: Integer; A: Integer = $ff): TColor32; overload;
  262. procedure RGBtoHSL(RGB: TColor32; out H, S, L: Byte); overload;
  263. function HSVtoRGB(H, S, V: Single): TColor32;
  264. procedure RGBToHSV(Color: TColor32; out H, S, V: Single);
  265. {$IFNDEF PLATFORM_INDEPENDENT}
  266. // Palette conversion functions
  267. function WinPalette(const P: TPalette32): HPALETTE;
  268. {$ENDIF}
  269. { A fixed-point type }
  270. type
  271. // This type has data bits arrangement compatible with Windows.TFixed
  272. PFixed = ^TFixed;
  273. TFixed = type Integer;
  274. PFixedRec = ^TFixedRec;
  275. TFixedRec = packed record
  276. case Integer of
  277. 0: (Fixed: TFixed);
  278. 1: (Frac: Word; Int: SmallInt);
  279. end;
  280. PFixedArray = ^TFixedArray;
  281. TFixedArray = array [0..0] of TFixed;
  282. PArrayOfFixed = ^TArrayOfFixed;
  283. TArrayOfFixed = array of TFixed;
  284. PArrayOfArrayOfFixed = ^TArrayOfArrayOfFixed;
  285. TArrayOfArrayOfFixed = array of TArrayOfFixed;
  286. // TFloat determines the precision level for certain floating-point operations
  287. PFloat = ^TFloat;
  288. TFloat = Single;
  289. { Other dynamic arrays }
  290. type
  291. PByteArray = ^TByteArray;
  292. TByteArray = array [0..0] of Byte;
  293. PArrayOfByte = ^TArrayOfByte;
  294. TArrayOfByte = array of Byte;
  295. PWordArray = ^TWordArray;
  296. TWordArray = array [0..0] of Word;
  297. PArrayOfWord = ^TArrayOfWord;
  298. TArrayOfWord = array of Word;
  299. PIntegerArray = ^TIntegerArray;
  300. TIntegerArray = array [0..0] of Integer;
  301. PArrayOfInteger = ^TArrayOfInteger;
  302. TArrayOfInteger = array of Integer;
  303. PArrayOfArrayOfInteger = ^TArrayOfArrayOfInteger;
  304. TArrayOfArrayOfInteger = array of TArrayOfInteger;
  305. PCardinalArray = ^TCardinalArray;
  306. TCardinalArray = array [0..0] of Cardinal;
  307. PArrayOfCardinal = ^TArrayOfCardinal;
  308. TArrayOfCardinal = array of Cardinal;
  309. PArrayOfArrayOfCardinal = ^TArrayOfArrayOfCardinal;
  310. TArrayOfArrayOfCardinal = array of TArrayOfCardinal;
  311. PSingleArray = ^TSingleArray;
  312. TSingleArray = array [0..0] of Single;
  313. PArrayOfSingle = ^TArrayOfSingle;
  314. TArrayOfSingle = array of Single;
  315. PFloatArray = ^TFloatArray;
  316. TFloatArray = array [0..0] of TFloat;
  317. PArrayOfFloat = ^TArrayOfFloat;
  318. TArrayOfFloat = array of TFloat;
  319. const
  320. // Fixed point math constants
  321. FixedOne = $10000;
  322. FixedHalf = $7FFF;
  323. FixedPI = Round(PI * FixedOne);
  324. FixedToFloat = 1 / FixedOne;
  325. COne255th = 1 / $FF;
  326. function Fixed(S: Single): TFixed; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  327. function Fixed(I: Integer): TFixed; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  328. { Points }
  329. type
  330. {$IFNDEF GR32_FMX}
  331. {$IFNDEF FPC}
  332. {$IFNDEF BCB}
  333. PPoint = ^TPoint;
  334. TPoint = Windows.TPoint;
  335. {$ENDIF}
  336. {$ENDIF}
  337. {$ENDIF}
  338. PPointArray = ^TPointArray;
  339. TPointArray = array [0..0] of TPoint;
  340. PArrayOfPoint = ^TArrayOfPoint;
  341. TArrayOfPoint = array of TPoint;
  342. PArrayOfArrayOfPoint = ^TArrayOfArrayOfPoint;
  343. TArrayOfArrayOfPoint = array of TArrayOfPoint;
  344. PFloatPoint = ^TFloatPoint;
  345. TFloatPoint = record
  346. X, Y: TFloat;
  347. {$IFDEF SUPPORT_ENHANCED_RECORDS}
  348. public
  349. {$IFNDEF FPC}
  350. {$IFDEF COMPILERXE2_UP}
  351. constructor Create(P: TPointF); overload;
  352. {$ENDIF}
  353. constructor Create(P: TPoint); overload;
  354. constructor Create(X, Y: Integer); overload;
  355. constructor Create(X, Y: Single); overload;
  356. {$ENDIF}
  357. // operator overloads
  358. class operator Equal(const Lhs, Rhs: TFloatPoint): Boolean;
  359. class operator NotEqual(const Lhs, Rhs: TFloatPoint): Boolean;
  360. class operator Add(const Lhs, Rhs: TFloatPoint): TFloatPoint;
  361. class operator Subtract(const Lhs, Rhs: TFloatPoint): TFloatPoint;
  362. {$IFDEF COMPILERXE2_UP}
  363. class operator Explicit(A: TPointF): TFloatPoint;
  364. class operator Implicit(A: TPointF): TFloatPoint;
  365. {$ENDIF}
  366. class function Zero: TFloatPoint; inline; static;
  367. {$ENDIF}
  368. end;
  369. PFloatPointArray = ^TFloatPointArray;
  370. TFloatPointArray = array [0..0] of TFloatPoint;
  371. PArrayOfFloatPoint = ^TArrayOfFloatPoint;
  372. TArrayOfFloatPoint = array of TFloatPoint;
  373. PArrayOfArrayOfFloatPoint = ^TArrayOfArrayOfFloatPoint;
  374. TArrayOfArrayOfFloatPoint = array of TArrayOfFloatPoint;
  375. PFixedPoint = ^TFixedPoint;
  376. TFixedPoint = record
  377. X, Y: TFixed;
  378. {$IFDEF SUPPORT_ENHANCED_RECORDS}
  379. public
  380. {$IFNDEF FPC}
  381. {$IFDEF COMPILERXE2_UP}
  382. constructor Create(P: TPointF); overload;
  383. {$ENDIF}
  384. constructor Create(P: TFloatPoint); overload;
  385. constructor Create(X, Y: TFixed); overload;
  386. constructor Create(X, Y: Integer); overload;
  387. constructor Create(X, Y: TFloat); overload;
  388. {$ENDIF}
  389. // operator overloads
  390. class operator Equal(const Lhs, Rhs: TFixedPoint): Boolean;
  391. class operator NotEqual(const Lhs, Rhs: TFixedPoint): Boolean;
  392. class operator Add(const Lhs, Rhs: TFixedPoint): TFixedPoint;
  393. class operator Subtract(const Lhs, Rhs: TFixedPoint): TFixedPoint;
  394. class function Zero: TFixedPoint; inline; static;
  395. {$ENDIF}
  396. end;
  397. PFixedPointArray = ^TFixedPointArray;
  398. TFixedPointArray = array [0..0] of TFixedPoint;
  399. PArrayOfFixedPoint = ^TArrayOfFixedPoint;
  400. TArrayOfFixedPoint = array of TFixedPoint;
  401. PArrayOfArrayOfFixedPoint = ^TArrayOfArrayOfFixedPoint;
  402. TArrayOfArrayOfFixedPoint = array of TArrayOfFixedPoint;
  403. // construction and conversion of point types
  404. function Point(X, Y: Integer): TPoint; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  405. function Point(const FP: TFloatPoint): TPoint; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  406. function Point(const FXP: TFixedPoint): TPoint; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  407. function FloatPoint(X, Y: Single): TFloatPoint; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  408. function FloatPoint(const P: TPoint): TFloatPoint; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  409. function FloatPoint(const FXP: TFixedPoint): TFloatPoint; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  410. function FixedPoint(X, Y: Integer): TFixedPoint; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  411. function FixedPoint(X, Y: Single): TFixedPoint; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  412. function FixedPoint(const P: TPoint): TFixedPoint; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  413. function FixedPoint(const FP: TFloatPoint): TFixedPoint; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  414. { Rectangles }
  415. type
  416. {$IFNDEF GR32_FMX}
  417. {$IFNDEF FPC}
  418. PRect = Windows.PRect;
  419. TRect = Windows.TRect;
  420. {$ENDIF}
  421. {$ENDIF}
  422. PFloatRect = ^TFloatRect;
  423. TFloatRect = packed record
  424. case Integer of
  425. 0: (Left, Top, Right, Bottom: TFloat);
  426. 1: (TopLeft, BottomRight: TFloatPoint);
  427. end;
  428. PFixedRect = ^TFixedRect;
  429. TFixedRect = packed record
  430. case Integer of
  431. 0: (Left, Top, Right, Bottom: TFixed);
  432. 1: (TopLeft, BottomRight: TFixedPoint);
  433. end;
  434. TRectRounding = (rrClosest, rrOutside, rrInside);
  435. // Rectangle construction/conversion functions
  436. function MakeRect(const L, T, R, B: Integer): TRect; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  437. function MakeRect(const FR: TFloatRect; Rounding: TRectRounding = rrClosest): TRect; overload;
  438. function MakeRect(const FXR: TFixedRect; Rounding: TRectRounding = rrClosest): TRect; overload;
  439. function FixedRect(const L, T, R, B: TFixed): TFixedRect; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  440. function FixedRect(const TopLeft, BottomRight: TFixedPoint): TFixedRect; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  441. function FixedRect(const ARect: TRect): TFixedRect; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  442. function FixedRect(const FR: TFloatRect): TFixedRect; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  443. function FloatRect(const L, T, R, B: TFloat): TFloatRect; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  444. function FloatRect(const TopLeft, BottomRight: TFloatPoint): TFloatRect; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  445. function FloatRect(const ARect: TRect): TFloatRect; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  446. function FloatRect(const FXR: TFixedRect): TFloatRect; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  447. // Some basic operations over rectangles
  448. function IntersectRect(out Dst: TRect; const R1, R2: TRect): Boolean; overload;
  449. function IntersectRect(out Dst: TFloatRect; const FR1, FR2: TFloatRect): Boolean; overload;
  450. function UnionRect(out Rect: TRect; const R1, R2: TRect): Boolean; overload;
  451. function UnionRect(out Rect: TFloatRect; const R1, R2: TFloatRect): Boolean; overload;
  452. function EqualRect(const R1, R2: TRect): Boolean; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  453. function EqualRect(const R1, R2: TFloatRect): Boolean; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  454. procedure InflateRect(var R: TRect; Dx, Dy: Integer); overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  455. procedure InflateRect(var FR: TFloatRect; Dx, Dy: TFloat); overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  456. procedure OffsetRect(var R: TRect; Dx, Dy: Integer); overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  457. procedure OffsetRect(var FR: TFloatRect; Dx, Dy: TFloat); overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  458. function IsRectEmpty(const R: TRect): Boolean; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  459. function IsRectEmpty(const FR: TFloatRect): Boolean; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  460. function PtInRect(const R: TRect; const P: TPoint): Boolean; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  461. function PtInRect(const R: TFloatRect; const P: TPoint): Boolean; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  462. function PtInRect(const R: TRect; const P: TFloatPoint): Boolean; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  463. function PtInRect(const R: TFloatRect; const P: TFloatPoint): Boolean; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  464. function EqualRectSize(const R1, R2: TRect): Boolean; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  465. function EqualRectSize(const R1, R2: TFloatRect): Boolean; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  466. type
  467. { TBitmap32 draw mode }
  468. TDrawMode = (dmOpaque, dmBlend, dmCustom, dmTransparent);
  469. TCombineMode = (cmBlend, cmMerge);
  470. TWrapMode = (wmClamp, wmRepeat, wmMirror);
  471. TWrapProc = function(Value, Max: Integer): Integer;
  472. TWrapProcEx = function(Value, Min, Max: Integer): Integer;
  473. {$IFDEF DEPRECATEDMODE}
  474. { Stretch filters }
  475. TStretchFilter = (sfNearest, sfDraft, sfLinear, sfCosine, sfSpline,
  476. sfLanczos, sfMitchell);
  477. {$ENDIF}
  478. { Gamma bias for line/pixel antialiasing }
  479. var
  480. GAMMA_TABLE: array [Byte] of Byte;
  481. procedure SetGamma(Gamma: Single = 1.6);
  482. type
  483. { TPlainInterfacedPersistent }
  484. { TPlainInterfacedPersistent provides simple interface support with
  485. optional reference-counting operation. }
  486. TPlainInterfacedPersistent = class(TPersistent, IInterface)
  487. private
  488. FRefCounted: Boolean;
  489. FRefCount: Integer;
  490. protected
  491. { IInterface }
  492. {$IFDEF FPC_HAS_CONSTREF}
  493. function QueryInterface(constref iid: TGuid; out obj): HResult; {$IFDEF WINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
  494. function _AddRef: LongInt; {$IFDEF WINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
  495. function _Release: LongInt; {$IFDEF WINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
  496. {$ELSE}
  497. function QueryInterface(const iid: TGuid; out obj): HResult; stdcall;
  498. function _AddRef: LongInt; stdcall;
  499. function _Release: LongInt; stdcall;
  500. {$ENDIF}
  501. property RefCounted: Boolean read FRefCounted write FRefCounted;
  502. public
  503. procedure AfterConstruction; override;
  504. procedure BeforeDestruction; override;
  505. class function NewInstance: TObject; override;
  506. property RefCount: Integer read FRefCount;
  507. end;
  508. { TNotifiablePersistent }
  509. { TNotifiablePersistent provides a change notification mechanism }
  510. TNotifiablePersistent = class(TPlainInterfacedPersistent)
  511. private
  512. FUpdateCount: Integer;
  513. FOnChange: TNotifyEvent;
  514. protected
  515. property UpdateCount: Integer read FUpdateCount;
  516. public
  517. procedure Changed; virtual;
  518. procedure BeginUpdate; virtual;
  519. procedure EndUpdate; virtual;
  520. property OnChange: TNotifyEvent read FOnChange write FOnChange;
  521. end;
  522. { TThreadPersistent }
  523. { TThreadPersistent is an ancestor for TBitmap32 object. In addition to
  524. TPersistent methods, it provides thread-safe locking and change notification }
  525. TThreadPersistent = class(TNotifiablePersistent)
  526. private
  527. FLockCount: Integer;
  528. protected
  529. {$IFDEF FPC}
  530. FLock: TCriticalSection;
  531. {$ELSE}
  532. {$IFDEF GR32_FMX}
  533. FLock: TObject;
  534. {$ELSE}
  535. FLock: TRTLCriticalSection;
  536. {$ENDIF}
  537. {$ENDIF}
  538. property LockCount: Integer read FLockCount;
  539. public
  540. constructor Create; virtual;
  541. destructor Destroy; override;
  542. procedure Lock;
  543. procedure Unlock;
  544. end;
  545. { TCustomMap }
  546. { An ancestor for bitmaps and similar 2D distributions wich have width and
  547. height properties }
  548. TCustomMap = class(TThreadPersistent)
  549. protected
  550. FHeight: Integer;
  551. FWidth: Integer;
  552. FOnResize: TNotifyEvent;
  553. procedure SetHeight(NewHeight: Integer); virtual;
  554. procedure SetWidth(NewWidth: Integer); virtual;
  555. procedure ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer); virtual;
  556. public
  557. constructor Create(Width, Height: Integer); reintroduce; overload;
  558. procedure Delete; virtual;
  559. function Empty: Boolean; virtual;
  560. procedure Resized; virtual;
  561. function SetSizeFrom(Source: TPersistent): Boolean;
  562. function SetSize(NewWidth, NewHeight: Integer): Boolean; virtual;
  563. property Height: Integer read FHeight write SetHeight;
  564. property Width: Integer read FWidth write SetWidth;
  565. property OnResize: TNotifyEvent read FOnResize write FOnResize;
  566. end;
  567. { TBitmap32 }
  568. { This is the core of Graphics32 unit. The TBitmap32 class is responsible
  569. for storage of a bitmap, as well as for drawing in it.
  570. The OnCombine event is fired only when DrawMode is set to dmCustom and two
  571. bitmaps are blended together. Unlike most normal events, it does not contain
  572. "Sender" parameter and is not called through some virtual method. This
  573. (a little bit non-standard) approach allows for faster operation. }
  574. const
  575. // common cases
  576. AREAINFO_RECT = $80000000;
  577. AREAINFO_LINE = $40000000; // 24 bits for line width in pixels...
  578. AREAINFO_ELLIPSE = $20000000;
  579. AREAINFO_ABSOLUTE = $10000000;
  580. AREAINFO_MASK = $FF000000;
  581. type
  582. TPixelCombineEvent = procedure(F: TColor32; var B: TColor32; M: TColor32) of object;
  583. TAreaChangedEvent = procedure(Sender: TObject; const Area: TRect;
  584. const Info: Cardinal) of object;
  585. TCustomResampler = class;
  586. TCustomBackend = class;
  587. TCustomBackendClass = class of TCustomBackend;
  588. TCustomBitmap32 = class(TCustomMap)
  589. private
  590. FBackend: TCustomBackend;
  591. FBits: PColor32Array;
  592. FClipRect: TRect;
  593. FFixedClipRect: TFixedRect;
  594. F256ClipRect: TRect;
  595. FClipping: Boolean;
  596. FDrawMode: TDrawMode;
  597. FCombineMode: TCombineMode;
  598. FWrapMode: TWrapMode;
  599. FMasterAlpha: Cardinal;
  600. FOuterColor: TColor32;
  601. FPenColor: TColor32;
  602. FStippleCounter: Single;
  603. FStipplePattern: TArrayOfColor32;
  604. FStippleStep: Single;
  605. {$IFDEF DEPRECATEDMODE}
  606. FStretchFilter: TStretchFilter;
  607. {$ENDIF}
  608. FOnPixelCombine: TPixelCombineEvent;
  609. FOnAreaChanged: TAreaChangedEvent;
  610. FOldOnAreaChanged: TAreaChangedEvent;
  611. FMeasuringMode: Boolean;
  612. FResampler: TCustomResampler;
  613. procedure BackendChangedHandler(Sender: TObject); virtual;
  614. procedure BackendChangingHandler(Sender: TObject); virtual;
  615. {$IFDEF BITS_GETTER}
  616. function GetBits: PColor32Array; {$IFDEF USEINLINING} inline; {$ENDIF}
  617. {$ENDIF}
  618. function GetPixelPtr(X, Y: Integer): PColor32;
  619. function GetScanLine(Y: Integer): PColor32Array;
  620. procedure SetCombineMode(const Value: TCombineMode);
  621. procedure SetDrawMode(Value: TDrawMode);
  622. procedure SetWrapMode(Value: TWrapMode);
  623. procedure SetMasterAlpha(Value: Cardinal);
  624. {$IFDEF DEPRECATEDMODE}
  625. procedure SetStretchFilter(Value: TStretchFilter);
  626. {$ENDIF}
  627. procedure SetClipRect(const Value: TRect);
  628. procedure SetResampler(Resampler: TCustomResampler);
  629. function GetResamplerClassName: string;
  630. procedure SetResamplerClassName(const Value: string);
  631. protected
  632. WrapProcHorz: TWrapProcEx;
  633. WrapProcVert: TWrapProcEx;
  634. BlendProc: Pointer;
  635. RasterX, RasterY: Integer;
  636. RasterXF, RasterYF: TFixed;
  637. procedure ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer); override;
  638. procedure CopyMapTo(Dst: TCustomBitmap32); virtual;
  639. procedure CopyPropertiesTo(Dst: TCustomBitmap32); virtual;
  640. procedure AssignTo(Dst: TPersistent); override;
  641. function Equal(B: TCustomBitmap32): Boolean;
  642. procedure SET_T256(X, Y: Integer; C: TColor32);
  643. procedure SET_TS256(X, Y: Integer; C: TColor32);
  644. function GET_T256(X, Y: Integer): TColor32;
  645. function GET_TS256(X, Y: Integer): TColor32;
  646. procedure ReadData(Stream: TStream); virtual;
  647. procedure WriteData(Stream: TStream); virtual;
  648. procedure DefineProperties(Filer: TFiler); override;
  649. procedure InitializeBackend(Backend: TCustomBackendClass); virtual;
  650. procedure FinalizeBackend; virtual;
  651. procedure SetBackend(const Backend: TCustomBackend); virtual;
  652. {$IFDEF FPC_HAS_CONSTREF}
  653. function QueryInterface(constref iid: TGuid; out obj): HResult; {$IFDEF WINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
  654. {$ELSE}
  655. function QueryInterface(const iid: TGuid; out obj): HResult; stdcall;
  656. {$ENDIF}
  657. function GetPixel(X, Y: Integer): TColor32; {$IFDEF USEINLINING} inline; {$ENDIF}
  658. function GetPixelS(X, Y: Integer): TColor32; {$IFDEF USEINLINING} inline; {$ENDIF}
  659. function GetPixelW(X, Y: Integer): TColor32; {$IFDEF USEINLINING} inline; {$ENDIF}
  660. function GetPixelF(X, Y: Single): TColor32; {$IFDEF USEINLINING} inline; {$ENDIF}
  661. function GetPixelFS(X, Y: Single): TColor32; {$IFDEF USEINLINING} inline; {$ENDIF}
  662. function GetPixelFW(X, Y: Single): TColor32; {$IFDEF USEINLINING} inline; {$ENDIF}
  663. function GetPixelX(X, Y: TFixed): TColor32;
  664. function GetPixelXS(X, Y: TFixed): TColor32;
  665. function GetPixelXW(X, Y: TFixed): TColor32;
  666. function GetPixelFR(X, Y: Single): TColor32;
  667. function GetPixelXR(X, Y: TFixed): TColor32;
  668. function GetPixelB(X, Y: Integer): TColor32; {$IFDEF USEINLINING} inline; {$ENDIF}
  669. procedure SetPixel(X, Y: Integer; Value: TColor32); {$IFDEF USEINLINING} inline; {$ENDIF}
  670. procedure SetPixelS(X, Y: Integer; Value: TColor32);
  671. procedure SetPixelW(X, Y: Integer; Value: TColor32); {$IFDEF USEINLINING} inline; {$ENDIF}
  672. procedure SetPixelF(X, Y: Single; Value: TColor32); {$IFDEF USEINLINING} inline; {$ENDIF}
  673. procedure SetPixelFS(X, Y: Single; Value: TColor32);
  674. procedure SetPixelFW(X, Y: Single; Value: TColor32);
  675. procedure SetPixelX(X, Y: TFixed; Value: TColor32);
  676. procedure SetPixelXS(X, Y: TFixed; Value: TColor32);
  677. procedure SetPixelXW(X, Y: TFixed; Value: TColor32);
  678. public
  679. constructor Create(Backend: TCustomBackendClass); reintroduce; overload; virtual;
  680. constructor Create; reintroduce; overload; virtual;
  681. destructor Destroy; override;
  682. class function GetPlatformBackendClass: TCustomBackendClass; virtual;
  683. procedure Assign(Source: TPersistent); override;
  684. function BoundsRect: TRect;
  685. function Empty: Boolean; override;
  686. procedure Clear; overload;
  687. procedure Clear(FillColor: TColor32); overload;
  688. procedure Delete; override;
  689. procedure BeginMeasuring(const Callback: TAreaChangedEvent);
  690. procedure EndMeasuring;
  691. function ReleaseBackend: TCustomBackend;
  692. procedure PropertyChanged; virtual;
  693. procedure Changed; overload; override;
  694. procedure Changed(const Area: TRect; const Info: Cardinal = AREAINFO_RECT); reintroduce; overload; virtual;
  695. procedure LoadFromStream(Stream: TStream); virtual;
  696. procedure SaveToStream(Stream: TStream; SaveTopDown: Boolean = False); virtual;
  697. procedure ResetAlpha; overload;
  698. procedure ResetAlpha(const AlphaValue: Byte); overload;
  699. procedure Draw(DstX, DstY: Integer; Src: TCustomBitmap32); overload;
  700. procedure Draw(DstX, DstY: Integer; const SrcRect: TRect; Src: TCustomBitmap32); overload;
  701. procedure Draw(const DstRect, SrcRect: TRect; Src: TCustomBitmap32); overload;
  702. procedure SetPixelT(X, Y: Integer; Value: TColor32); overload;
  703. procedure SetPixelT(var Ptr: PColor32; Value: TColor32); overload;
  704. procedure SetPixelTS(X, Y: Integer; Value: TColor32);
  705. procedure DrawTo(Dst: TCustomBitmap32); overload;
  706. procedure DrawTo(Dst: TCustomBitmap32; DstX, DstY: Integer); overload;
  707. procedure DrawTo(Dst: TCustomBitmap32; DstX, DstY: Integer; const SrcRect: TRect); overload;
  708. procedure DrawTo(Dst: TCustomBitmap32; const DstRect: TRect); overload;
  709. procedure DrawTo(Dst: TCustomBitmap32; const DstRect, SrcRect: TRect); overload;
  710. procedure SetStipple(NewStipple: TArrayOfColor32); overload;
  711. procedure SetStipple(NewStipple: array of TColor32); overload;
  712. procedure AdvanceStippleCounter(LengthPixels: Single);
  713. function GetStippleColor: TColor32;
  714. procedure HorzLine(X1, Y, X2: Integer; Value: TColor32);
  715. procedure HorzLineS(X1, Y, X2: Integer; Value: TColor32);
  716. procedure HorzLineT(X1, Y, X2: Integer; Value: TColor32);
  717. procedure HorzLineTS(X1, Y, X2: Integer; Value: TColor32);
  718. procedure HorzLineTSP(X1, Y, X2: Integer);
  719. procedure HorzLineX(X1, Y, X2: TFixed; Value: TColor32);
  720. procedure HorzLineXS(X1, Y, X2: TFixed; Value: TColor32);
  721. procedure VertLine(X, Y1, Y2: Integer; Value: TColor32);
  722. procedure VertLineS(X, Y1, Y2: Integer; Value: TColor32);
  723. procedure VertLineT(X, Y1, Y2: Integer; Value: TColor32);
  724. procedure VertLineTS(X, Y1, Y2: Integer; Value: TColor32);
  725. procedure VertLineTSP(X, Y1, Y2: Integer);
  726. procedure VertLineX(X, Y1, Y2: TFixed; Value: TColor32);
  727. procedure VertLineXS(X, Y1, Y2: TFixed; Value: TColor32);
  728. procedure Line(X1, Y1, X2, Y2: Integer; Value: TColor32; L: Boolean = False);
  729. procedure LineS(X1, Y1, X2, Y2: Integer; Value: TColor32; L: Boolean = False);
  730. procedure LineT(X1, Y1, X2, Y2: Integer; Value: TColor32; L: Boolean = False);
  731. procedure LineTS(X1, Y1, X2, Y2: Integer; Value: TColor32; L: Boolean = False);
  732. procedure LineA(X1, Y1, X2, Y2: Integer; Value: TColor32; L: Boolean = False);
  733. procedure LineAS(X1, Y1, X2, Y2: Integer; Value: TColor32; L: Boolean = False);
  734. procedure LineX(X1, Y1, X2, Y2: TFixed; Value: TColor32; L: Boolean = False); overload;
  735. procedure LineF(X1, Y1, X2, Y2: Single; Value: TColor32; L: Boolean = False); overload;
  736. procedure LineXS(X1, Y1, X2, Y2: TFixed; Value: TColor32; L: Boolean = False); overload;
  737. procedure LineFS(X1, Y1, X2, Y2: Single; Value: TColor32; L: Boolean = False); overload;
  738. procedure LineXP(X1, Y1, X2, Y2: TFixed; L: Boolean = False); overload;
  739. procedure LineFP(X1, Y1, X2, Y2: Single; L: Boolean = False); overload;
  740. procedure LineXSP(X1, Y1, X2, Y2: TFixed; L: Boolean = False); overload;
  741. procedure LineFSP(X1, Y1, X2, Y2: Single; L: Boolean = False); overload;
  742. property PenColor: TColor32 read FPenColor write FPenColor;
  743. procedure MoveTo(X, Y: Integer);
  744. procedure LineToS(X, Y: Integer);
  745. procedure LineToTS(X, Y: Integer);
  746. procedure LineToAS(X, Y: Integer);
  747. procedure MoveToX(X, Y: TFixed);
  748. procedure MoveToF(X, Y: Single);
  749. procedure LineToXS(X, Y: TFixed);
  750. procedure LineToFS(X, Y: Single);
  751. procedure LineToXSP(X, Y: TFixed);
  752. procedure LineToFSP(X, Y: Single);
  753. procedure FillRect(X1, Y1, X2, Y2: Integer; Value: TColor32);
  754. procedure FillRectS(X1, Y1, X2, Y2: Integer; Value: TColor32); overload;
  755. procedure FillRectT(X1, Y1, X2, Y2: Integer; Value: TColor32);
  756. procedure FillRectTS(X1, Y1, X2, Y2: Integer; Value: TColor32); overload;
  757. procedure FillRectS(const ARect: TRect; Value: TColor32); overload;
  758. procedure FillRectTS(const ARect: TRect; Value: TColor32); overload;
  759. procedure FrameRectS(X1, Y1, X2, Y2: Integer; Value: TColor32); overload;
  760. procedure FrameRectTS(X1, Y1, X2, Y2: Integer; Value: TColor32); overload;
  761. procedure FrameRectTSP(X1, Y1, X2, Y2: Integer);
  762. procedure FrameRectS(const ARect: TRect; Value: TColor32); overload;
  763. procedure FrameRectTS(const ARect: TRect; Value: TColor32); overload;
  764. procedure RaiseRectTS(X1, Y1, X2, Y2: Integer; Contrast: Integer); overload;
  765. procedure RaiseRectTS(const ARect: TRect; Contrast: Integer); overload;
  766. procedure Roll(Dx, Dy: Integer; FillBack: Boolean; FillColor: TColor32);
  767. procedure FlipHorz(Dst: TCustomBitmap32 = nil);
  768. procedure FlipVert(Dst: TCustomBitmap32 = nil);
  769. procedure Rotate90(Dst: TCustomBitmap32 = nil);
  770. procedure Rotate180(Dst: TCustomBitmap32 = nil);
  771. procedure Rotate270(Dst: TCustomBitmap32 = nil);
  772. procedure ResetClipRect;
  773. property Pixel[X, Y: Integer]: TColor32 read GetPixel write SetPixel; default;
  774. property PixelS[X, Y: Integer]: TColor32 read GetPixelS write SetPixelS;
  775. property PixelW[X, Y: Integer]: TColor32 read GetPixelW write SetPixelW;
  776. property PixelX[X, Y: TFixed]: TColor32 read GetPixelX write SetPixelX;
  777. property PixelXS[X, Y: TFixed]: TColor32 read GetPixelXS write SetPixelXS;
  778. property PixelXW[X, Y: TFixed]: TColor32 read GetPixelXW write SetPixelXW;
  779. property PixelF[X, Y: Single]: TColor32 read GetPixelF write SetPixelF;
  780. property PixelFS[X, Y: Single]: TColor32 read GetPixelFS write SetPixelFS;
  781. property PixelFW[X, Y: Single]: TColor32 read GetPixelFW write SetPixelFW;
  782. property PixelFR[X, Y: Single]: TColor32 read GetPixelFR;
  783. property PixelXR[X, Y: TFixed]: TColor32 read GetPixelXR;
  784. property Backend: TCustomBackend read FBackend write SetBackend;
  785. {$IFDEF BITS_GETTER}
  786. property Bits: PColor32Array read GetBits;
  787. {$ELSE}
  788. property Bits: PColor32Array read FBits;
  789. {$ENDIF}
  790. property ClipRect: TRect read FClipRect write SetClipRect;
  791. property Clipping: Boolean read FClipping;
  792. property PixelPtr[X, Y: Integer]: PColor32 read GetPixelPtr;
  793. property ScanLine[Y: Integer]: PColor32Array read GetScanLine;
  794. property StippleCounter: Single read FStippleCounter write FStippleCounter;
  795. property StippleStep: Single read FStippleStep write FStippleStep;
  796. property MeasuringMode: Boolean read FMeasuringMode;
  797. published
  798. property DrawMode: TDrawMode read FDrawMode write SetDrawMode default dmOpaque;
  799. property CombineMode: TCombineMode read FCombineMode write SetCombineMode default cmBlend;
  800. property WrapMode: TWrapMode read FWrapMode write SetWrapMode default wmClamp;
  801. property MasterAlpha: Cardinal read FMasterAlpha write SetMasterAlpha default $FF;
  802. property OuterColor: TColor32 read FOuterColor write FOuterColor default 0;
  803. {$IFDEF DEPRECATEDMODE}
  804. property StretchFilter: TStretchFilter read FStretchFilter write SetStretchFilter default sfNearest;
  805. {$ENDIF}
  806. property ResamplerClassName: string read GetResamplerClassName write SetResamplerClassName;
  807. property Resampler: TCustomResampler read FResampler write SetResampler;
  808. property OnChange;
  809. property OnPixelCombine: TPixelCombineEvent read FOnPixelCombine write FOnPixelCombine;
  810. property OnAreaChanged: TAreaChangedEvent read FOnAreaChanged write FOnAreaChanged;
  811. property OnResize;
  812. end;
  813. TBitmap32 = class(TCustomBitmap32)
  814. protected
  815. procedure FinalizeBackend; override;
  816. procedure SetBackend(const Backend: TCustomBackend); override;
  817. // procedure HandleChanged; virtual;
  818. procedure CopyPropertiesTo(Dst: TCustomBitmap32); override;
  819. public
  820. class function GetPlatformBackendClass: TCustomBackendClass; override;
  821. // {$IFDEF BCB}
  822. // procedure Draw(const DstRect, SrcRect: TRect; hSrc: Cardinal); overload;
  823. // {$ELSE}
  824. // procedure Draw(const DstRect, SrcRect: TRect; hSrc: HDC); overload;
  825. // {$ENDIF}
  826. //{$IFDEF BCB}
  827. // procedure DrawTo(hDst: Cardinal; DstX, DstY: Integer); overload;
  828. // procedure DrawTo(hDst: Cardinal; const DstRect, SrcRect: TRect); overload;
  829. // procedure TileTo(hDst: Cardinal; const DstRect, SrcRect: TRect);
  830. //{$ELSE}
  831. // procedure DrawTo(hDst: HDC; DstX: Integer = 0; DstY: Integer = 0); overload;
  832. // procedure DrawTo(hDst: HDC; const DstRect, SrcRect: TRect); overload;
  833. // procedure TileTo(hDst: HDC; const DstRect, SrcRect: TRect);
  834. //{$ENDIF}
  835. // procedure UpdateFont;
  836. // procedure Textout(X, Y: Integer; const Text: string); overload;
  837. // procedure Textout(X, Y: Integer; const ClipRect: TRect; const Text: string); overload;
  838. // procedure Textout(var DstRect: TRect; const Flags: Cardinal; const Text: string); overload;
  839. // function TextExtent(const Text: string): TSize;
  840. // function TextHeight(const Text: string): Integer;
  841. // function TextWidth(const Text: string): Integer;
  842. // procedure RenderText(X, Y: Integer; const Text: string; AALevel: Integer; Color: TColor32);
  843. // procedure TextoutW(X, Y: Integer; const Text: Widestring); overload;
  844. // procedure TextoutW(X, Y: Integer; const ClipRect: TRect; const Text: Widestring); overload;
  845. // procedure TextoutW(var DstRect: TRect; const Flags: Cardinal; const Text: Widestring); overload;
  846. // function TextExtentW(const Text: Widestring): TSize;
  847. // function TextHeightW(const Text: Widestring): Integer;
  848. // function TextWidthW(const Text: Widestring): Integer;
  849. // procedure RenderTextW(X, Y: Integer; const Text: Widestring; AALevel: Integer; Color: TColor32);
  850. // property Canvas: TCanvas read GetCanvas;
  851. // function CanvasAllocated: Boolean;
  852. // procedure DeleteCanvas;
  853. // property Font: TFont read GetFont write SetFont;
  854. //
  855. // property BitmapHandle: HBITMAP read GetHandle;
  856. // property BitmapInfo: TBitmapInfo read GetBitmapInfo;
  857. // property Handle: HDC read GetHDC;
  858. published
  859. // property OnHandleChanged: TNotifyEvent read FOnHandleChanged write FOnHandleChanged;
  860. end;
  861. { TCustomBackend }
  862. { This class functions as backend for the TBitmap32 class.
  863. It manages and provides the backing buffer as well as OS or
  864. graphics subsystem specific features.}
  865. TCustomBackend = class(TThreadPersistent)
  866. protected
  867. FBits: PColor32Array;
  868. FOwner: TCustomBitmap32;
  869. FOnChanging: TNotifyEvent;
  870. procedure Changing; virtual;
  871. {$IFDEF BITS_GETTER}
  872. function GetBits: PColor32Array; virtual;
  873. {$ENDIF}
  874. procedure InitializeSurface(NewWidth, NewHeight: Integer; ClearBuffer: Boolean); virtual;
  875. procedure FinalizeSurface; virtual;
  876. public
  877. constructor Create; overload; override;
  878. constructor Create(Owner: TCustomBitmap32); reintroduce; overload; virtual;
  879. destructor Destroy; override;
  880. procedure Assign(Source: TPersistent); override;
  881. procedure Clear; virtual;
  882. function Empty: Boolean; virtual;
  883. procedure ChangeSize(out Width, Height: Integer; NewWidth, NewHeight: Integer; ClearBuffer: Boolean = True); virtual;
  884. {$IFDEF BITS_GETTER}
  885. property Bits: PColor32Array read GetBits;
  886. {$ELSE}
  887. property Bits: PColor32Array read FBits;
  888. {$ENDIF}
  889. property OnChanging: TNotifyEvent read FOnChanging write FOnChanging;
  890. end;
  891. { TCustomSampler }
  892. TCustomSampler = class(TNotifiablePersistent)
  893. public
  894. function GetSampleInt(X, Y: Integer): TColor32; virtual;
  895. function GetSampleFixed(X, Y: TFixed): TColor32; virtual;
  896. function GetSampleFloat(X, Y: TFloat): TColor32; virtual;
  897. procedure PrepareSampling; virtual;
  898. procedure FinalizeSampling; virtual;
  899. function HasBounds: Boolean; virtual;
  900. function GetSampleBounds: TFloatRect; virtual;
  901. end;
  902. TPixelAccessMode = (pamUnsafe, pamSafe, pamWrap, pamTransparentEdge);
  903. { TCustomResampler }
  904. { Base class for TCustomBitmap32 specific resamplers. }
  905. TCustomResampler = class(TCustomSampler)
  906. private
  907. FBitmap: TCustomBitmap32;
  908. FClipRect: TRect;
  909. FPixelAccessMode: TPixelAccessMode;
  910. procedure SetPixelAccessMode(const Value: TPixelAccessMode);
  911. protected
  912. function GetWidth: TFloat; virtual;
  913. procedure Resample(
  914. Dst: TCustomBitmap32; DstRect: TRect; DstClip: TRect;
  915. Src: TCustomBitmap32; SrcRect: TRect;
  916. CombineOp: TDrawMode; CombineCallBack: TPixelCombineEvent); virtual; abstract;
  917. procedure AssignTo(Dst: TPersistent); override;
  918. property ClipRect: TRect read FClipRect;
  919. public
  920. constructor Create; overload; virtual;
  921. constructor Create(ABitmap: TCustomBitmap32); overload; virtual;
  922. procedure Changed; override;
  923. procedure PrepareSampling; override;
  924. function HasBounds: Boolean; override;
  925. function GetSampleBounds: TFloatRect; override;
  926. property Bitmap: TCustomBitmap32 read FBitmap write FBitmap;
  927. property Width: TFloat read GetWidth;
  928. published
  929. property PixelAccessMode: TPixelAccessMode read FPixelAccessMode write SetPixelAccessMode default pamSafe;
  930. end;
  931. TCustomResamplerClass = class of TCustomResampler;
  932. var
  933. StockBitmap: TBitmap;
  934. resourcestring
  935. RCStrUnmatchedReferenceCounting = 'Unmatched reference counting.';
  936. RCStrCannotSetSize = 'Can''t set size from ''%s''';
  937. RCStrInpropriateBackend = 'Inpropriate Backend';
  938. implementation
  939. uses
  940. GR32_Common, Math, GR32_Blend, GR32_LowLevel, GR32_Math, GR32_Resamplers,
  941. GR32_Containers,
  942. GR32_VectorUtils, GR32_Backends_Generic;
  943. type
  944. { We can not use the Win32 defined record here since we are cross-platform. }
  945. TBmpHeader = packed record
  946. bfType: Word;
  947. bfSize: LongInt;
  948. bfReserved: LongInt;
  949. bfOffBits: LongInt;
  950. biSize: LongInt;
  951. biWidth: LongInt;
  952. biHeight: LongInt;
  953. biPlanes: Word;
  954. biBitCount: Word;
  955. biCompression: LongInt;
  956. biSizeImage: LongInt;
  957. biXPelsPerMeter: LongInt;
  958. biYPelsPerMeter: LongInt;
  959. biClrUsed: LongInt;
  960. biClrImportant: LongInt;
  961. end;
  962. const
  963. ZERO_RECT: TRect = (Left: 0; Top: 0; Right: 0; Bottom: 0);
  964. { Color construction and conversion functions }
  965. {$IFDEF PUREPASCAL}
  966. {$DEFINE USENATIVECODE}
  967. {$ENDIF}
  968. {$IFDEF TARGET_X64}
  969. {$DEFINE USENATIVECODE}
  970. {$ENDIF}
  971. function Color32(AlphaColor: TAlphaColor): TColor32; overload;
  972. var
  973. R: TAlphaColorRec;
  974. E: TColor32Entry;
  975. begin
  976. R.Color := AlphaColor;
  977. E.A := R.A;
  978. E.R := R.R;
  979. E.G := R.G;
  980. E.B := R.B;
  981. Result := E.ARGB;
  982. end;
  983. function Color32(R, G, B: Byte; A: Byte = $FF): TColor32; overload;
  984. {$IFDEF USENATIVECODE}
  985. begin
  986. Result := (A shl 24) or (R shl 16) or (G shl 8) or B;
  987. {$ELSE}
  988. asm
  989. MOV AH, A
  990. SHL EAX, 16
  991. MOV AH, DL
  992. MOV AL, CL
  993. {$ENDIF}
  994. end;
  995. function Color32(Index: Byte; var Palette: TPalette32): TColor32; overload;
  996. begin
  997. Result := Palette[Index];
  998. end;
  999. function Gray32(Intensity: Byte; Alpha: Byte = $FF): TColor32;
  1000. begin
  1001. Result := TColor32(Alpha) shl 24 + TColor32(Intensity) shl 16 +
  1002. TColor32(Intensity) shl 8 + TColor32(Intensity);
  1003. end;
  1004. function WinColor(Color32: TColor32): TColor;
  1005. {$IFDEF PUREPASCAL}
  1006. begin
  1007. Result := ((Color32 and $00FF0000) shr 16) or
  1008. (Color32 and $0000FF00) or
  1009. ((Color32 and $000000FF) shl 16);
  1010. {$ELSE}
  1011. asm
  1012. {$IFDEF TARGET_x64}
  1013. MOV EAX, ECX
  1014. {$ENDIF}
  1015. // the alpha channel byte is set to zero!
  1016. ROL EAX, 8 // ABGR -> RGBA
  1017. XOR AL, AL // BGRA -> BGR0
  1018. BSWAP EAX // BGR0 -> 0RGB
  1019. {$ENDIF}
  1020. end;
  1021. function ArrayOfColor32(Colors: array of TColor32): TArrayOfColor32;
  1022. var
  1023. L: Integer;
  1024. begin
  1025. // build a dynamic color array from specified colors
  1026. L := High(Colors) + 1;
  1027. SetLength(Result, L);
  1028. MoveLongword(Colors[0], Result[0], L);
  1029. end;
  1030. procedure Color32ToRGB(Color32: TColor32; var R, G, B: Byte);
  1031. begin
  1032. R := (Color32 and $00FF0000) shr 16;
  1033. G := (Color32 and $0000FF00) shr 8;
  1034. B := Color32 and $000000FF;
  1035. end;
  1036. procedure Color32ToRGBA(Color32: TColor32; var R, G, B, A: Byte);
  1037. begin
  1038. A := Color32 shr 24;
  1039. R := (Color32 and $00FF0000) shr 16;
  1040. G := (Color32 and $0000FF00) shr 8;
  1041. B := Color32 and $000000FF;
  1042. end;
  1043. function Color32Components(R, G, B, A: Boolean): TColor32Components;
  1044. const
  1045. ccR : array[Boolean] of TColor32Components = ([], [ccRed]);
  1046. ccG : array[Boolean] of TColor32Components = ([], [ccGreen]);
  1047. ccB : array[Boolean] of TColor32Components = ([], [ccBlue]);
  1048. ccA : array[Boolean] of TColor32Components = ([], [ccAlpha]);
  1049. begin
  1050. Result := ccR[R] + ccG[G] + ccB[B] + ccA[A];
  1051. end;
  1052. function RedComponent(Color32: TColor32): Integer;
  1053. begin
  1054. Result := (Color32 and $00FF0000) shr 16;
  1055. end;
  1056. function GreenComponent(Color32: TColor32): Integer;
  1057. begin
  1058. Result := (Color32 and $0000FF00) shr 8;
  1059. end;
  1060. function BlueComponent(Color32: TColor32): Integer;
  1061. begin
  1062. Result := Color32 and $000000FF;
  1063. end;
  1064. function AlphaComponent(Color32: TColor32): Integer;
  1065. begin
  1066. Result := Color32 shr 24;
  1067. end;
  1068. function Intensity(Color32: TColor32): Integer;
  1069. begin
  1070. // (R * 61 + G * 174 + B * 21) / 256
  1071. Result := (
  1072. (Color32 and $00FF0000) shr 16 * 61 +
  1073. (Color32 and $0000FF00) shr 8 * 174 +
  1074. (Color32 and $000000FF) * 21
  1075. ) shr 8;
  1076. end;
  1077. function InvertColor(Color32: TColor32): TColor32;
  1078. begin
  1079. TColor32Entry(Result).R := $FF - TColor32Entry(Color32).R;
  1080. TColor32Entry(Result).G := $FF - TColor32Entry(Color32).G;
  1081. TColor32Entry(Result).B := $FF - TColor32Entry(Color32).B;
  1082. TColor32Entry(Result).A := TColor32Entry(Color32).A;
  1083. end;
  1084. function SetAlpha(Color32: TColor32; NewAlpha: Integer): TColor32;
  1085. begin
  1086. if NewAlpha < 0 then
  1087. NewAlpha := 0
  1088. else if NewAlpha > $FF then
  1089. NewAlpha := $FF;
  1090. Result := (Color32 and $00FFFFFF) or (TColor32(NewAlpha) shl 24);
  1091. end;
  1092. procedure ModifyAlpha(var Color32: TColor32; NewAlpha: Byte);
  1093. begin
  1094. TColor32Entry(Color32).A := NewAlpha;
  1095. end;
  1096. procedure ScaleAlpha(var Color32: TColor32; Scale: Single);
  1097. begin
  1098. TColor32Entry(Color32).A := Round(Scale * TColor32Entry(Color32).A);
  1099. end;
  1100. { Color space conversions }
  1101. function HSLtoRGB(H, S, L: Single): TColor32;
  1102. const
  1103. OneOverThree = 1 / 3;
  1104. var
  1105. M1, M2: Single;
  1106. function HueToColor(Hue: Single): Byte;
  1107. var
  1108. V: Double;
  1109. begin
  1110. Hue := Hue - Floor(Hue);
  1111. if 6 * Hue < 1 then
  1112. V := M1 + (M2 - M1) * Hue * 6
  1113. else if 2 * Hue < 1 then
  1114. V := M2
  1115. else if 3 * Hue < 2 then
  1116. V := M1 + (M2 - M1) * (2 * OneOverThree - Hue) * 6
  1117. else V := M1;
  1118. Result := Round($FF * V);
  1119. end;
  1120. begin
  1121. if S = 0 then
  1122. begin
  1123. Result := Gray32(Round($FF * L));
  1124. Exit;
  1125. end;
  1126. if L <= 0.5 then
  1127. M2 := L * (1 + S)
  1128. else
  1129. M2 := L + S - L * S;
  1130. M1 := 2 * L - M2;
  1131. Result := Color32(
  1132. HueToColor(H + OneOverThree),
  1133. HueToColor(H),
  1134. HueToColor(H - OneOverThree));
  1135. end;
  1136. procedure RGBtoHSL(RGB: TColor32; out H, S, L : Single);
  1137. const
  1138. // reciprocal mul. opt.
  1139. R6 = 1 / 6;
  1140. var
  1141. R, G, B, D, Cmax, Cmin: Single;
  1142. begin
  1143. R := RedComponent(RGB) * COne255th;
  1144. G := GreenComponent(RGB) * COne255th;
  1145. B := BlueComponent(RGB) * COne255th;
  1146. Cmax := Max(R, Max(G, B));
  1147. Cmin := Min(R, Min(G, B));
  1148. L := (Cmax + Cmin) * 0.5;
  1149. if Cmax = Cmin then
  1150. begin
  1151. H := 0;
  1152. S := 0
  1153. end
  1154. else
  1155. begin
  1156. D := Cmax - Cmin;
  1157. if L < 0.5 then
  1158. S := D / (Cmax + Cmin)
  1159. else
  1160. S := D / (2 - Cmax - Cmin);
  1161. if R = Cmax then
  1162. H := (G - B) / D
  1163. else
  1164. if G = Cmax then
  1165. H := 2 + (B - R) / D
  1166. else
  1167. H := 4 + (R - G) / D;
  1168. H := H * R6;
  1169. if H < 0 then H := H + 1
  1170. end;
  1171. end;
  1172. function HSLtoRGB(H, S, L, A: Integer): TColor32;
  1173. var
  1174. V, M, M1, M2, VSF: Integer;
  1175. begin
  1176. if L <= $7F then
  1177. V := L * (256 + S) shr 8
  1178. else
  1179. V := L + S - Integer(Div255(L * S));
  1180. if V <= 0 then
  1181. Result := $FF000000
  1182. else
  1183. begin
  1184. M := L * 2 - V;
  1185. H := H * 6;
  1186. VSF := (V - M) * (H and $FF) shr 8;
  1187. M1 := M + VSF;
  1188. M2 := V - VSF;
  1189. case H shr 8 of
  1190. 0: Result := Color32(V, M1, M, A);
  1191. 1: Result := Color32(M2, V, M, A);
  1192. 2: Result := Color32(M, V, M1, A);
  1193. 3: Result := Color32(M, M2, V, A);
  1194. 4: Result := Color32(M1, M, V, A);
  1195. 5: Result := Color32(V, M, M2, A);
  1196. else
  1197. Result := 0;
  1198. end;
  1199. end;
  1200. end;
  1201. procedure RGBtoHSL(RGB: TColor32; out H, S, L: Byte);
  1202. var
  1203. R, G, B, D, Cmax, Cmin, HL: Integer;
  1204. begin
  1205. R := (RGB shr 16) and $ff;
  1206. G := (RGB shr 8) and $ff;
  1207. B := RGB and $ff;
  1208. Cmax := Max(R, G, B);
  1209. Cmin := Min(R, G, B);
  1210. L := (Cmax + Cmin) shr 1;
  1211. if Cmax = Cmin then
  1212. begin
  1213. H := 0;
  1214. S := 0
  1215. end
  1216. else
  1217. begin
  1218. D := (Cmax - Cmin) * $FF;
  1219. if L <= $7F then
  1220. S := D div (Cmax + Cmin)
  1221. else
  1222. S := D div ($FF * 2 - Cmax - Cmin);
  1223. D := D * 6;
  1224. if R = Cmax then
  1225. HL := (G - B) * $FF * $FF div D
  1226. else if G = Cmax then
  1227. HL := $FF * 2 div 6 + (B - R) * $FF * $FF div D
  1228. else
  1229. HL := $FF * 4 div 6 + (R - G) * $FF * $FF div D;
  1230. if HL < 0 then HL := HL + $FF * 2;
  1231. H := HL;
  1232. end;
  1233. end;
  1234. function HSVtoRGB(H, S, V: Single): TColor32;
  1235. var
  1236. Tmp: TFloat;
  1237. Sel, Q, P: Integer;
  1238. begin
  1239. V := 255 * V;
  1240. if S = 0 then
  1241. begin
  1242. Result := Gray32(Trunc(V));
  1243. Exit;
  1244. end;
  1245. H := H - Floor(H);
  1246. Tmp := 6 * H - Floor(6 * H);
  1247. Sel := Trunc(6 * H);
  1248. if (Sel mod 2) = 0 then
  1249. Tmp := 1 - Tmp;
  1250. Q := Trunc(V * (1 - S));
  1251. P := Trunc(V * (1 - S * Tmp));
  1252. case Sel of
  1253. 0:
  1254. Result := Color32(Trunc(V), P, Q);
  1255. 1:
  1256. Result := Color32(P, Trunc(V), Q);
  1257. 2:
  1258. Result := Color32(Q, Trunc(V), P);
  1259. 3:
  1260. Result := Color32(Q, P, Trunc(V));
  1261. 4:
  1262. Result := Color32(P, Q, Trunc(V));
  1263. 5:
  1264. Result := Color32(Trunc(V), Q, P);
  1265. else
  1266. Result := Gray32(0);
  1267. end;
  1268. end;
  1269. procedure RGBToHSV(Color: TColor32; out H, S, V: Single);
  1270. var
  1271. Delta, Min, Max: Single;
  1272. R, G, B: Integer;
  1273. const
  1274. COneSixth = 1 / 6;
  1275. begin
  1276. R := RedComponent(Color);
  1277. G := GreenComponent(Color);
  1278. B := BlueComponent(Color);
  1279. Min := MinIntValue([R, G, B]);
  1280. Max := MaxIntValue([R, G, B]);
  1281. V := Max / 255;
  1282. Delta := Max - Min;
  1283. if Max = 0 then
  1284. S := 0
  1285. else
  1286. S := Delta / Max;
  1287. if S = 0.0 then
  1288. H := 0
  1289. else
  1290. begin
  1291. if R = Max then
  1292. H := COneSixth * (G - B) / Delta
  1293. else if G = Max then
  1294. H := COneSixth * (2 + (B - R) / Delta)
  1295. else if B = Max then
  1296. H := COneSixth * (4 + (R - G) / Delta);
  1297. if H < 0.0 then
  1298. H := H + 1;
  1299. end;
  1300. end;
  1301. { Fixed-point conversion routines }
  1302. function Fixed(S: Single): TFixed;
  1303. begin
  1304. Result := Round(S * FixedOne);
  1305. end;
  1306. function Fixed(I: Integer): TFixed;
  1307. begin
  1308. Result := I shl 16;
  1309. end;
  1310. { Points }
  1311. function Point(X, Y: Integer): TPoint;
  1312. begin
  1313. Result.X := X;
  1314. Result.Y := Y;
  1315. end;
  1316. function Point(const FP: TFloatPoint): TPoint;
  1317. begin
  1318. Result.X := Round(FP.X);
  1319. Result.Y := Round(FP.Y);
  1320. end;
  1321. function Point(const FXP: TFixedPoint): TPoint;
  1322. begin
  1323. Result.X := FixedRound(FXP.X);
  1324. Result.Y := FixedRound(FXP.Y);
  1325. end;
  1326. function FloatPoint(X, Y: Single): TFloatPoint;
  1327. begin
  1328. Result.X := X;
  1329. Result.Y := Y;
  1330. end;
  1331. function FloatPoint(const P: TPoint): TFloatPoint;
  1332. begin
  1333. Result.X := P.X;
  1334. Result.Y := P.Y;
  1335. end;
  1336. function FloatPoint(const FXP: TFixedPoint): TFloatPoint;
  1337. begin
  1338. with FXP do
  1339. begin
  1340. Result.X := X * FixedToFloat;
  1341. Result.Y := Y * FixedToFloat;
  1342. end;
  1343. end;
  1344. {$IFDEF SUPPORT_ENHANCED_RECORDS}
  1345. {$IFNDEF FPC}
  1346. constructor TFloatPoint.Create(P: TPoint);
  1347. begin
  1348. Self.X := P.X;
  1349. Self.Y := P.Y;
  1350. end;
  1351. {$IFDEF COMPILERXE2_UP}
  1352. constructor TFloatPoint.Create(P: TPointF);
  1353. begin
  1354. Self.X := P.X;
  1355. Self.Y := P.Y;
  1356. end;
  1357. {$ENDIF}
  1358. constructor TFloatPoint.Create(X, Y: Integer);
  1359. begin
  1360. Self.X := X;
  1361. Self.Y := Y;
  1362. end;
  1363. constructor TFloatPoint.Create(X, Y: TFloat);
  1364. begin
  1365. Self.X := X;
  1366. Self.Y := Y;
  1367. end;
  1368. {$ENDIF}
  1369. // operator overloads
  1370. class operator TFloatPoint.Equal(const Lhs, Rhs: TFloatPoint): Boolean;
  1371. begin
  1372. Result := (Lhs.X = Rhs.X) and (Lhs.Y = Rhs.Y);
  1373. end;
  1374. class operator TFloatPoint.NotEqual(const Lhs, Rhs: TFloatPoint): Boolean;
  1375. begin
  1376. Result := (Lhs.X <> Rhs.X) or (Lhs.Y <> Rhs.Y);
  1377. end;
  1378. class operator TFloatPoint.Add(const Lhs, Rhs: TFloatPoint): TFloatPoint;
  1379. begin
  1380. Result.X := Lhs.X + Rhs.X;
  1381. Result.Y := Lhs.Y + Rhs.Y;
  1382. end;
  1383. class operator TFloatPoint.Subtract(const Lhs, Rhs: TFloatPoint): TFloatPoint;
  1384. begin
  1385. Result.X := Lhs.X - Rhs.X;
  1386. Result.Y := Lhs.Y - Rhs.Y;
  1387. end;
  1388. {$IFDEF COMPILERXE2_UP}
  1389. class operator TFloatPoint.Explicit(A: TPointF): TFloatPoint;
  1390. begin
  1391. Result.X := A.X;
  1392. Result.Y := A.Y;
  1393. end;
  1394. class operator TFloatPoint.Implicit(A: TPointF): TFloatPoint;
  1395. begin
  1396. Result.X := A.X;
  1397. Result.Y := A.Y;
  1398. end;
  1399. {$ENDIF}
  1400. class function TFloatPoint.Zero: TFloatPoint;
  1401. begin
  1402. Result.X := 0;
  1403. Result.Y := 0;
  1404. end;
  1405. {$IFNDEF FPC}
  1406. {$IFDEF COMPILERXE2_UP}
  1407. constructor TFixedPoint.Create(P: TPointF);
  1408. begin
  1409. Self.X := Fixed(P.X);
  1410. Self.Y := Fixed(P.Y);
  1411. end;
  1412. {$ENDIF}
  1413. constructor TFixedPoint.Create(P: TFloatPoint);
  1414. begin
  1415. Self.X := Fixed(P.X);
  1416. Self.Y := Fixed(P.Y);
  1417. end;
  1418. constructor TFixedPoint.Create(X, Y: TFixed);
  1419. begin
  1420. Self.X := X;
  1421. Self.Y := Y;
  1422. end;
  1423. constructor TFixedPoint.Create(X, Y: Integer);
  1424. begin
  1425. Self.X := Fixed(X);
  1426. Self.Y := Fixed(Y);
  1427. end;
  1428. constructor TFixedPoint.Create(X, Y: TFloat);
  1429. begin
  1430. Self.X := Fixed(X);
  1431. Self.Y := Fixed(Y);
  1432. end;
  1433. {$ENDIF}
  1434. // operator overloads
  1435. class operator TFixedPoint.Equal(const Lhs, Rhs: TFixedPoint): Boolean;
  1436. begin
  1437. Result := (Lhs.X = Rhs.X) and (Lhs.Y = Rhs.Y);
  1438. end;
  1439. class operator TFixedPoint.NotEqual(const Lhs, Rhs: TFixedPoint): Boolean;
  1440. begin
  1441. Result := (Lhs.X <> Rhs.X) or (Lhs.Y <> Rhs.Y);
  1442. end;
  1443. class operator TFixedPoint.Add(const Lhs, Rhs: TFixedPoint): TFixedPoint;
  1444. begin
  1445. Result.X := Lhs.X + Rhs.X;
  1446. Result.Y := Lhs.Y + Rhs.Y;
  1447. end;
  1448. class operator TFixedPoint.Subtract(const Lhs, Rhs: TFixedPoint): TFixedPoint;
  1449. begin
  1450. Result.X := Lhs.X - Rhs.X;
  1451. Result.Y := Lhs.Y - Rhs.Y;
  1452. end;
  1453. class function TFixedPoint.Zero: TFixedPoint;
  1454. begin
  1455. Result.X := 0;
  1456. Result.Y := 0;
  1457. end;
  1458. {$ENDIF}
  1459. function FixedPoint(X, Y: Integer): TFixedPoint; overload;
  1460. begin
  1461. Result.X := X shl 16;
  1462. Result.Y := Y shl 16;
  1463. end;
  1464. function FixedPoint(X, Y: Single): TFixedPoint; overload;
  1465. begin
  1466. Result.X := Round(X * FixedOne);
  1467. Result.Y := Round(Y * FixedOne);
  1468. end;
  1469. function FixedPoint(const P: TPoint): TFixedPoint; overload;
  1470. begin
  1471. Result.X := P.X shl 16;
  1472. Result.Y := P.Y shl 16;
  1473. end;
  1474. function FixedPoint(const FP: TFloatPoint): TFixedPoint; overload;
  1475. begin
  1476. Result.X := Round(FP.X * FixedOne);
  1477. Result.Y := Round(FP.Y * FixedOne);
  1478. end;
  1479. { Rectangles }
  1480. function MakeRect(const L, T, R, B: Integer): TRect;
  1481. begin
  1482. with Result do
  1483. begin
  1484. Left := L;
  1485. Top := T;
  1486. Right := R;
  1487. Bottom := B;
  1488. end;
  1489. end;
  1490. function MakeRect(const FR: TFloatRect; Rounding: TRectRounding): TRect;
  1491. begin
  1492. with FR do
  1493. case Rounding of
  1494. rrClosest:
  1495. begin
  1496. Result.Left := Round(Left);
  1497. Result.Top := Round(Top);
  1498. Result.Right := Round(Right);
  1499. Result.Bottom := Round(Bottom);
  1500. end;
  1501. rrInside:
  1502. begin
  1503. Result.Left := Ceil(Left);
  1504. Result.Top := Ceil(Top);
  1505. Result.Right := Floor(Right);
  1506. Result.Bottom := Floor(Bottom);
  1507. if Result.Right < Result.Left then Result.Right := Result.Left;
  1508. if Result.Bottom < Result.Top then Result.Bottom := Result.Top;
  1509. end;
  1510. rrOutside:
  1511. begin
  1512. Result.Left := Floor(Left);
  1513. Result.Top := Floor(Top);
  1514. Result.Right := Ceil(Right);
  1515. Result.Bottom := Ceil(Bottom);
  1516. end;
  1517. end;
  1518. end;
  1519. function MakeRect(const FXR: TFixedRect; Rounding: TRectRounding): TRect;
  1520. begin
  1521. with FXR do
  1522. case Rounding of
  1523. rrClosest:
  1524. begin
  1525. Result.Left := FixedRound(Left);
  1526. Result.Top := FixedRound(Top);
  1527. Result.Right := FixedRound(Right);
  1528. Result.Bottom := FixedRound(Bottom);
  1529. end;
  1530. rrInside:
  1531. begin
  1532. Result.Left := FixedCeil(Left);
  1533. Result.Top := FixedCeil(Top);
  1534. Result.Right := FixedFloor(Right);
  1535. Result.Bottom := FixedFloor(Bottom);
  1536. if Result.Right < Result.Left then Result.Right := Result.Left;
  1537. if Result.Bottom < Result.Top then Result.Bottom := Result.Top;
  1538. end;
  1539. rrOutside:
  1540. begin
  1541. Result.Left := FixedFloor(Left);
  1542. Result.Top := FixedFloor(Top);
  1543. Result.Right := FixedCeil(Right);
  1544. Result.Bottom := FixedCeil(Bottom);
  1545. end;
  1546. end;
  1547. end;
  1548. function FixedRect(const L, T, R, B: TFixed): TFixedRect;
  1549. begin
  1550. with Result do
  1551. begin
  1552. Left := L;
  1553. Top := T;
  1554. Right := R;
  1555. Bottom := B;
  1556. end;
  1557. end;
  1558. function FixedRect(const TopLeft, BottomRight: TFixedPoint): TFixedRect;
  1559. begin
  1560. Result.TopLeft := TopLeft;
  1561. Result.BottomRight := BottomRight;
  1562. end;
  1563. function FixedRect(const ARect: TRect): TFixedRect;
  1564. begin
  1565. with Result do
  1566. begin
  1567. Left := ARect.Left shl 16;
  1568. Top := ARect.Top shl 16;
  1569. Right := ARect.Right shl 16;
  1570. Bottom := ARect.Bottom shl 16;
  1571. end;
  1572. end;
  1573. function FixedRect(const FR: TFloatRect): TFixedRect;
  1574. begin
  1575. with Result do
  1576. begin
  1577. Left := Round(FR.Left * 65536);
  1578. Top := Round(FR.Top * 65536);
  1579. Right := Round(FR.Right * 65536);
  1580. Bottom := Round(FR.Bottom * 65536);
  1581. end;
  1582. end;
  1583. function FloatRect(const L, T, R, B: TFloat): TFloatRect;
  1584. begin
  1585. with Result do
  1586. begin
  1587. Left := L;
  1588. Top := T;
  1589. Right := R;
  1590. Bottom := B;
  1591. end;
  1592. end;
  1593. function FloatRect(const TopLeft, BottomRight: TFloatPoint): TFloatRect;
  1594. begin
  1595. Result.TopLeft := TopLeft;
  1596. Result.BottomRight := BottomRight;
  1597. end;
  1598. function FloatRect(const ARect: TRect): TFloatRect;
  1599. begin
  1600. with Result do
  1601. begin
  1602. Left := ARect.Left;
  1603. Top := ARect.Top;
  1604. Right := ARect.Right;
  1605. Bottom := ARect.Bottom;
  1606. end;
  1607. end;
  1608. function FloatRect(const FXR: TFixedRect): TFloatRect;
  1609. begin
  1610. with Result do
  1611. begin
  1612. Left := FXR.Left * FixedToFloat;
  1613. Top := FXR.Top * FixedToFloat;
  1614. Right := FXR.Right * FixedToFloat;
  1615. Bottom := FXR.Bottom * FixedToFloat;
  1616. end;
  1617. end;
  1618. function IntersectRect(out Dst: TRect; const R1, R2: TRect): Boolean;
  1619. begin
  1620. if R1.Left >= R2.Left then Dst.Left := R1.Left else Dst.Left := R2.Left;
  1621. if R1.Right <= R2.Right then Dst.Right := R1.Right else Dst.Right := R2.Right;
  1622. if R1.Top >= R2.Top then Dst.Top := R1.Top else Dst.Top := R2.Top;
  1623. if R1.Bottom <= R2.Bottom then Dst.Bottom := R1.Bottom else Dst.Bottom := R2.Bottom;
  1624. Result := (Dst.Right >= Dst.Left) and (Dst.Bottom >= Dst.Top);
  1625. if not Result then Dst := ZERO_RECT;
  1626. end;
  1627. function IntersectRect(out Dst: TFloatRect; const FR1, FR2: TFloatRect): Boolean;
  1628. begin
  1629. Dst.Left := Math.Max(FR1.Left, FR2.Left);
  1630. Dst.Right := Math.Min(FR1.Right, FR2.Right);
  1631. Dst.Top := Math.Max(FR1.Top, FR2.Top);
  1632. Dst.Bottom := Math.Min(FR1.Bottom, FR2.Bottom);
  1633. Result := (Dst.Right >= Dst.Left) and (Dst.Bottom >= Dst.Top);
  1634. if not Result then FillLongword(Dst, 4, 0);
  1635. end;
  1636. function UnionRect(out Rect: TRect; const R1, R2: TRect): Boolean;
  1637. begin
  1638. Rect := R1;
  1639. if not GR32.IsRectEmpty(R2) then
  1640. begin
  1641. if R2.Left < R1.Left then Rect.Left := R2.Left;
  1642. if R2.Top < R1.Top then Rect.Top := R2.Top;
  1643. if R2.Right > R1.Right then Rect.Right := R2.Right;
  1644. if R2.Bottom > R1.Bottom then Rect.Bottom := R2.Bottom;
  1645. end;
  1646. Result := not GR32.IsRectEmpty(Rect);
  1647. if not Result then Rect := ZERO_RECT;
  1648. end;
  1649. function UnionRect(out Rect: TFloatRect; const R1, R2: TFloatRect): Boolean;
  1650. begin
  1651. Rect := R1;
  1652. if not IsRectEmpty(R2) then
  1653. begin
  1654. if R2.Left < R1.Left then Rect.Left := R2.Left;
  1655. if R2.Top < R1.Top then Rect.Top := R2.Top;
  1656. if R2.Right > R1.Right then Rect.Right := R2.Right;
  1657. if R2.Bottom > R1.Bottom then Rect.Bottom := R2.Bottom;
  1658. end;
  1659. Result := not IsRectEmpty(Rect);
  1660. if not Result then FillLongword(Rect, 4, 0);
  1661. end;
  1662. function EqualRect(const R1, R2: TRect): Boolean;
  1663. begin
  1664. Result := CompareMem(@R1, @R2, SizeOf(TRect));
  1665. end;
  1666. function EqualRect(const R1, R2: TFloatRect): Boolean;
  1667. begin
  1668. Result := CompareMem(@R1, @R2, SizeOf(TFloatRect));
  1669. end;
  1670. function EqualRectSize(const R1, R2: TRect): Boolean;
  1671. begin
  1672. Result := ((R1.Right - R1.Left) = (R2.Right - R2.Left)) and
  1673. ((R1.Bottom - R1.Top) = (R2.Bottom - R2.Top));
  1674. end;
  1675. function EqualRectSize(const R1, R2: TFloatRect): Boolean;
  1676. var
  1677. _R1: TFixedRect;
  1678. _R2: TFixedRect;
  1679. begin
  1680. _R1 := FixedRect(R1);
  1681. _R2 := FixedRect(R2);
  1682. Result := ((_R1.Right - _R1.Left) = (_R2.Right - _R2.Left)) and
  1683. ((_R1.Bottom - _R1.Top) = (_R2.Bottom - _R2.Top));
  1684. end;
  1685. procedure InflateRect(var R: TRect; Dx, Dy: Integer);
  1686. begin
  1687. Dec(R.Left, Dx); Dec(R.Top, Dy);
  1688. Inc(R.Right, Dx); Inc(R.Bottom, Dy);
  1689. end;
  1690. procedure InflateRect(var FR: TFloatRect; Dx, Dy: TFloat);
  1691. begin
  1692. with FR do
  1693. begin
  1694. Left := Left - Dx; Top := Top - Dy;
  1695. Right := Right + Dx; Bottom := Bottom + Dy;
  1696. end;
  1697. end;
  1698. procedure OffsetRect(var R: TRect; Dx, Dy: Integer);
  1699. begin
  1700. Inc(R.Left, Dx); Inc(R.Top, Dy);
  1701. Inc(R.Right, Dx); Inc(R.Bottom, Dy);
  1702. end;
  1703. procedure OffsetRect(var FR: TFloatRect; Dx, Dy: TFloat);
  1704. begin
  1705. with FR do
  1706. begin
  1707. Left := Left + Dx; Top := Top + Dy;
  1708. Right := Right + Dx; Bottom := Bottom + Dy;
  1709. end;
  1710. end;
  1711. function IsRectEmpty(const R: TRect): Boolean;
  1712. begin
  1713. Result := (R.Right <= R.Left) or (R.Bottom <= R.Top);
  1714. end;
  1715. function IsRectEmpty(const FR: TFloatRect): Boolean;
  1716. begin
  1717. Result := (FR.Right <= FR.Left) or (FR.Bottom <= FR.Top);
  1718. end;
  1719. function PtInRect(const R: TRect; const P: TPoint): Boolean;
  1720. begin
  1721. Result := (P.X >= R.Left) and (P.X < R.Right) and
  1722. (P.Y >= R.Top) and (P.Y < R.Bottom);
  1723. end;
  1724. function PtInRect(const R: TFloatRect; const P: TPoint): Boolean;
  1725. begin
  1726. Result := (P.X >= R.Left) and (P.X < R.Right) and
  1727. (P.Y >= R.Top) and (P.Y < R.Bottom);
  1728. end;
  1729. function PtInRect(const R: TRect; const P: TFloatPoint): Boolean;
  1730. begin
  1731. Result := (P.X >= R.Left) and (P.X < R.Right) and
  1732. (P.Y >= R.Top) and (P.Y < R.Bottom);
  1733. end;
  1734. function PtInRect(const R: TFloatRect; const P: TFloatPoint): Boolean;
  1735. begin
  1736. Result := (P.X >= R.Left) and (P.X < R.Right) and
  1737. (P.Y >= R.Top) and (P.Y < R.Bottom);
  1738. end;
  1739. { Gamma / Pixel Shape Correction table }
  1740. procedure SetGamma(Gamma: Single);
  1741. var
  1742. i: Integer;
  1743. begin
  1744. for i := 0 to $FF do
  1745. GAMMA_TABLE[i] := Round($FF * Power(i * COne255th, Gamma));
  1746. end;
  1747. { TSimpleInterfacedPersistent }
  1748. function TPlainInterfacedPersistent._AddRef: Integer;
  1749. begin
  1750. if FRefCounted then
  1751. Result := InterlockedIncrement(FRefCount)
  1752. else
  1753. Result := -1;
  1754. end;
  1755. function TPlainInterfacedPersistent._Release: Integer;
  1756. begin
  1757. if FRefCounted then
  1758. begin
  1759. Result := InterlockedDecrement(FRefCount);
  1760. if Result = 0 then
  1761. Destroy;
  1762. end
  1763. else
  1764. Result := -1;
  1765. end;
  1766. function TPlainInterfacedPersistent.QueryInterface(
  1767. {$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF}IID: TGUID; out Obj): HResult;
  1768. const
  1769. E_NOINTERFACE = HResult($80004002);
  1770. begin
  1771. if GetInterface(IID, Obj) then
  1772. Result := 0
  1773. else
  1774. Result := E_NOINTERFACE;
  1775. end;
  1776. procedure TPlainInterfacedPersistent.AfterConstruction;
  1777. begin
  1778. inherited;
  1779. // Release the constructor's implicit refcount
  1780. InterlockedDecrement(FRefCount);
  1781. end;
  1782. procedure TPlainInterfacedPersistent.BeforeDestruction;
  1783. begin
  1784. if RefCounted and (RefCount <> 0) then
  1785. raise Exception.Create(RCStrUnmatchedReferenceCounting);
  1786. inherited;
  1787. end;
  1788. class function TPlainInterfacedPersistent.NewInstance: TObject; {$IFDEF AUTOREFCOUNT} unsafe; {$ENDIF} // FIX from aone for ios
  1789. begin
  1790. Result := inherited NewInstance;
  1791. // Set an implicit refcount so that refcounting
  1792. // during construction won't destroy the object.
  1793. TPlainInterfacedPersistent(Result).FRefCount := 1;
  1794. end;
  1795. { TNotifiablePersistent }
  1796. procedure TNotifiablePersistent.BeginUpdate;
  1797. begin
  1798. Inc(FUpdateCount);
  1799. end;
  1800. procedure TNotifiablePersistent.Changed;
  1801. begin
  1802. if (FUpdateCount = 0) and Assigned(FOnChange) then FOnChange(Self);
  1803. end;
  1804. procedure TNotifiablePersistent.EndUpdate;
  1805. begin
  1806. Assert(FUpdateCount > 0, 'Unpaired TThreadPersistent.EndUpdate');
  1807. Dec(FUpdateCount);
  1808. end;
  1809. { TThreadPersistent }
  1810. constructor TThreadPersistent.Create;
  1811. begin
  1812. FLock := TObject.Create;
  1813. TMonitor.Enter(FLock);
  1814. end;
  1815. destructor TThreadPersistent.Destroy;
  1816. begin
  1817. FLock.Free;
  1818. inherited;
  1819. end;
  1820. procedure TThreadPersistent.Lock;
  1821. begin
  1822. InterlockedIncrement(FLockCount);
  1823. TMonitor.Enter(FLock);
  1824. end;
  1825. procedure TThreadPersistent.Unlock;
  1826. begin
  1827. TMonitor.Exit(FLock);
  1828. InterlockedDecrement(FLockCount);
  1829. end;
  1830. { TCustomMap }
  1831. constructor TCustomMap.Create(Width, Height: Integer);
  1832. begin
  1833. Create;
  1834. SetSize(Width, Height);
  1835. end;
  1836. procedure TCustomMap.ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer);
  1837. begin
  1838. Width := NewWidth;
  1839. Height := NewHeight;
  1840. end;
  1841. procedure TCustomMap.Delete;
  1842. begin
  1843. SetSize(0, 0);
  1844. end;
  1845. function TCustomMap.Empty: Boolean;
  1846. begin
  1847. Result := (Width = 0) or (Height = 0);
  1848. end;
  1849. procedure TCustomMap.Resized;
  1850. begin
  1851. if Assigned(FOnResize) then FOnResize(Self);
  1852. end;
  1853. procedure TCustomMap.SetHeight(NewHeight: Integer);
  1854. begin
  1855. SetSize(Width, NewHeight);
  1856. end;
  1857. function TCustomMap.SetSize(NewWidth, NewHeight: Integer): Boolean;
  1858. begin
  1859. if NewWidth < 0 then NewWidth := 0;
  1860. if NewHeight < 0 then NewHeight := 0;
  1861. Result := (NewWidth <> FWidth) or (NewHeight <> FHeight);
  1862. if Result then
  1863. begin
  1864. ChangeSize(FWidth, FHeight, NewWidth, NewHeight);
  1865. Changed;
  1866. Resized;
  1867. end;
  1868. end;
  1869. function TCustomMap.SetSizeFrom(Source: TPersistent): Boolean;
  1870. begin
  1871. if Source is TCustomMap then
  1872. Result := SetSize(TCustomMap(Source).Width, TCustomMap(Source).Height)
  1873. else if Source = nil then
  1874. Result := SetSize(0, 0)
  1875. else
  1876. raise Exception.CreateFmt(RCStrCannotSetSize, [Source.ClassName]);
  1877. end;
  1878. procedure TCustomMap.SetWidth(NewWidth: Integer);
  1879. begin
  1880. SetSize(NewWidth, Height);
  1881. end;
  1882. { TCustomBitmap32 }
  1883. constructor TCustomBitmap32.Create(Backend: TCustomBackendClass);
  1884. begin
  1885. inherited Create;
  1886. InitializeBackend(Backend);
  1887. FOuterColor := $00000000; // by default as full transparency black
  1888. FMasterAlpha := $FF;
  1889. FPenColor := clWhite32;
  1890. FStippleStep := 1;
  1891. FCombineMode := cmBlend;
  1892. BlendProc := @BLEND_MEM[FCombineMode]^;
  1893. WrapProcHorz := GetWrapProcEx(WrapMode);
  1894. WrapProcVert := GetWrapProcEx(WrapMode);
  1895. FResampler := TNearestResampler.Create(Self);
  1896. end;
  1897. constructor TCustomBitmap32.Create;
  1898. begin
  1899. Create(GetPlatformBackendClass);
  1900. end;
  1901. destructor TCustomBitmap32.Destroy;
  1902. begin
  1903. BeginUpdate;
  1904. Lock;
  1905. try
  1906. SetSize(0, 0);
  1907. FResampler.Free;
  1908. FinalizeBackend;
  1909. finally
  1910. Unlock;
  1911. end;
  1912. inherited;
  1913. end;
  1914. procedure TCustomBitmap32.InitializeBackend(Backend: TCustomBackendClass);
  1915. begin
  1916. Backend.Create(Self);
  1917. end;
  1918. procedure TCustomBitmap32.FinalizeBackend;
  1919. begin
  1920. // Drop ownership of backend now:
  1921. // It's a zombie now.
  1922. FBackend.FOwner := nil;
  1923. FBackend.OnChange := nil;
  1924. FBackend.OnChanging := nil;
  1925. (*
  1926. Release our reference to the backend
  1927. Note: The backend won't necessarily be freed immediately.
  1928. This is required to circumvent a problem with the magic procedure cleanup
  1929. of interfaces that have ref-counting forcefully disabled:
  1930. Quality Central report #9157 and #9500:
  1931. http://qc.codegear.com/wc/qcmain.aspx?d=9157
  1932. http://qc.codegear.com/wc/qcmain.aspx?d=9500
  1933. if any backend interface is used within the same procedure in which
  1934. the owner bitmap is also freed, the magic procedure cleanup will
  1935. clear that particular interface long after the bitmap and its backend
  1936. are gone. This will result in all sorts of madness - mostly heap corruption
  1937. and AVs.
  1938. Here is an example:
  1939. procedure Test;
  1940. var
  1941. MyBitmap: TBitmap32;
  1942. begin
  1943. MyBitmap := TBitmap32.Create;
  1944. MyBitmap.SetSize(100, 100);
  1945. (MyBitmap.Backend as ICanvasSupport).Canvas;
  1946. MyBitmap.Free;
  1947. end; // _IntfClear will try to clear (MyBitmap.Backend as ICanvasSupport)
  1948. // which points to the interface at the previous location of MyBitmap.Backend in memory.
  1949. // MyBitmap.Backend is gone and the _Release call is invalid, so raise hell .
  1950. Here is an example for a correct workaround:
  1951. procedure Test;
  1952. var
  1953. MyBitmap: TBitmap32;
  1954. CanvasIntf: ICanvasSupport;
  1955. begin
  1956. MyBitmap := TBitmap32.Create;
  1957. MyBitmap.SetSize(100, 100);
  1958. CanvasIntf := MyBitmap.Backend as ICanvasSupport;
  1959. CanvasIntf.Canvas;
  1960. CanvasIntf := nil; // this will call _IntfClear and IInterface._Release
  1961. MyBitmap.Free;
  1962. end; // _IntfClear will try to clear CanvasIntf,
  1963. // it's nil, no _Release is called, everything is fine.
  1964. Since the above code is pretty fiddly, we introduce ref-counting for the
  1965. backend. That way the backend will be released once all references are dropped.
  1966. So, release our reference to the backend now:
  1967. *)
  1968. FBackend._Release;
  1969. FBackend := nil;
  1970. end;
  1971. procedure TCustomBitmap32.SetBackend(const Backend: TCustomBackend);
  1972. begin
  1973. if Assigned(Backend) and (Backend <> FBackend) then
  1974. begin
  1975. BeginUpdate;
  1976. Backend.FOwner := Self;
  1977. if Assigned(FBackend) then
  1978. begin
  1979. Backend.Assign(FBackend);
  1980. FinalizeBackend;
  1981. end;
  1982. FBackend := Backend;
  1983. FBackend.OnChange := BackendChangedHandler;
  1984. FBackend.OnChanging := BackendChangingHandler;
  1985. EndUpdate;
  1986. FBackend.Changed;
  1987. Changed;
  1988. end;
  1989. end;
  1990. function TCustomBitmap32.ReleaseBackend: TCustomBackend;
  1991. begin
  1992. FBackend._AddRef; // Increase ref-count for external use
  1993. Result := FBackend;
  1994. end;
  1995. function TCustomBitmap32.QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} IID: TGUID; out Obj): HResult;
  1996. begin
  1997. Result := FBackend.QueryInterface(IID, Obj);
  1998. if Result <> S_OK then
  1999. Result := inherited QueryInterface(IID, Obj);
  2000. end;
  2001. procedure TCustomBitmap32.ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer);
  2002. begin
  2003. FBackend.ChangeSize(Width, Height, NewWidth, NewHeight);
  2004. end;
  2005. procedure TCustomBitmap32.BackendChangingHandler(Sender: TObject);
  2006. begin
  2007. // descendants can override this method.
  2008. end;
  2009. procedure TCustomBitmap32.Assign(Source: TPersistent);
  2010. procedure AssignFromBitmap(TargetBitmap: TCustomBitmap32; SrcBmp: TBitmap);
  2011. var
  2012. Data: TBitmapData;
  2013. I: Integer;
  2014. P1,P2: Pointer;
  2015. begin
  2016. TargetBitmap.SetSize(SrcBmp.Width, SrcBmp.Height);
  2017. SrcBmp.Map(TMapAccess.Read, Data);
  2018. try
  2019. for I := 0 to SrcBmp.Height-1 do
  2020. begin
  2021. P1 := Data.GetScanline(I);
  2022. P2 := Self.GetScanline(I);
  2023. Move(P1^, P2^, Data.BytesPerLine);
  2024. end;
  2025. finally
  2026. SrcBmp.Unmap(Data);
  2027. end;
  2028. end;
  2029. begin
  2030. BeginUpdate;
  2031. try
  2032. if not Assigned(Source) then
  2033. SetSize(0, 0)
  2034. else if Source is TCustomBitmap32 then
  2035. begin
  2036. TCustomBitmap32(Source).CopyMapTo(Self);
  2037. TCustomBitmap32(Source).CopyPropertiesTo(Self);
  2038. end
  2039. else if Source is TBitmap then
  2040. AssignFromBitmap(Self, TBitmap(Source))
  2041. else
  2042. inherited; // default handler
  2043. finally;
  2044. EndUpdate;
  2045. Changed;
  2046. end;
  2047. end;
  2048. procedure TCustomBitmap32.AssignTo(Dst: TPersistent);
  2049. procedure AssignToBitmap(Bmp: TBitmap; SrcBitmap: TCustomBitmap32);
  2050. var
  2051. Data: TBitmapData;
  2052. I: Integer;
  2053. P1, P2: Pointer;
  2054. begin
  2055. Bmp.SetSize(SrcBitmap.Width, SrcBitmap.Height);
  2056. if SrcBitmap.Empty then Exit;
  2057. Bmp.Map(TMapAccess.Write, Data);
  2058. try
  2059. for I := 0 to SrcBitmap.Height-1 do
  2060. begin
  2061. P1 := SrcBitmap.GetScanLine(I);
  2062. P2 := Data.GetScanline(I);
  2063. Move(P1^, P2^, Data.BytesPerLine);
  2064. end;
  2065. finally
  2066. Bmp.Unmap(Data);
  2067. end;
  2068. end;
  2069. begin
  2070. if Dst is TBitmap then
  2071. AssignToBitmap(TBitmap(Dst), Self)
  2072. else
  2073. inherited;
  2074. end;
  2075. procedure TCustomBitmap32.BackendChangedHandler(Sender: TObject);
  2076. begin
  2077. FBits := FBackend.Bits;
  2078. ResetClipRect;
  2079. end;
  2080. function TCustomBitmap32.Empty: Boolean;
  2081. begin
  2082. Result := FBackend.Empty or inherited Empty;
  2083. end;
  2084. procedure TCustomBitmap32.Clear;
  2085. begin
  2086. Clear(clBlack32);
  2087. end;
  2088. procedure TCustomBitmap32.Clear(FillColor: TColor32);
  2089. begin
  2090. if Empty then Exit;
  2091. if not MeasuringMode then
  2092. if Clipping then
  2093. FillRect(FClipRect.Left, FClipRect.Top, FClipRect.Right, FClipRect.Bottom, FillColor)
  2094. else
  2095. FillLongword(Bits[0], Width * Height, FillColor);
  2096. Changed;
  2097. end;
  2098. procedure TCustomBitmap32.Delete;
  2099. begin
  2100. SetSize(0, 0);
  2101. end;
  2102. procedure TCustomBitmap32.CopyMapTo(Dst: TCustomBitmap32);
  2103. begin
  2104. Dst.SetSize(Width, Height);
  2105. if not Empty then
  2106. MoveLongword(Bits[0], Dst.Bits[0], Width * Height);
  2107. end;
  2108. procedure TCustomBitmap32.CopyPropertiesTo(Dst: TCustomBitmap32);
  2109. begin
  2110. with Dst do
  2111. begin
  2112. DrawMode := Self.DrawMode;
  2113. CombineMode := Self.CombineMode;
  2114. WrapMode := Self.WrapMode;
  2115. MasterAlpha := Self.MasterAlpha;
  2116. OuterColor := Self.OuterColor;
  2117. {$IFDEF DEPRECATEDMODE}
  2118. StretchFilter := Self.StretchFilter;
  2119. {$ENDIF}
  2120. ResamplerClassName := Self.ResamplerClassName;
  2121. if Assigned(Resampler) and Assigned(Self.Resampler) then
  2122. Resampler.Assign(Self.Resampler);
  2123. end;
  2124. end;
  2125. {$IFDEF BITS_GETTER}
  2126. function TCustomBitmap32.GetBits: PColor32Array;
  2127. begin
  2128. Result := FBackend.Bits;
  2129. end;
  2130. {$ENDIF}
  2131. procedure TCustomBitmap32.SetPixel(X, Y: Integer; Value: TColor32);
  2132. begin
  2133. Bits[X + Y * Width] := Value;
  2134. end;
  2135. procedure TCustomBitmap32.SetPixelS(X, Y: Integer; Value: TColor32);
  2136. begin
  2137. if {$IFDEF CHANGED_IN_PIXELS}not FMeasuringMode and{$ENDIF}
  2138. (X >= FClipRect.Left) and (X < FClipRect.Right) and
  2139. (Y >= FClipRect.Top) and (Y < FClipRect.Bottom) then
  2140. Bits[X + Y * Width] := Value;
  2141. {$IFDEF CHANGED_IN_PIXELS}
  2142. Changed(MakeRect(X, Y, X + 1, Y + 1));
  2143. {$ENDIF}
  2144. end;
  2145. function TCustomBitmap32.GetScanLine(Y: Integer): PColor32Array;
  2146. begin
  2147. Result := @Bits[Y * FWidth];
  2148. end;
  2149. function TCustomBitmap32.GetPixel(X, Y: Integer): TColor32;
  2150. begin
  2151. Result := Bits[X + Y * Width];
  2152. end;
  2153. function TCustomBitmap32.GetPixelS(X, Y: Integer): TColor32;
  2154. begin
  2155. if (X >= FClipRect.Left) and (X < FClipRect.Right) and
  2156. (Y >= FClipRect.Top) and (Y < FClipRect.Bottom) then
  2157. Result := Bits[X + Y * Width]
  2158. else
  2159. Result := OuterColor;
  2160. end;
  2161. function TCustomBitmap32.GetPixelPtr(X, Y: Integer): PColor32;
  2162. begin
  2163. Result := @Bits[X + Y * Width];
  2164. end;
  2165. procedure TCustomBitmap32.Draw(DstX, DstY: Integer; Src: TCustomBitmap32);
  2166. begin
  2167. if Assigned(Src) then Src.DrawTo(Self, DstX, DstY);
  2168. end;
  2169. procedure TCustomBitmap32.Draw(DstX, DstY: Integer; const SrcRect: TRect;
  2170. Src: TCustomBitmap32);
  2171. begin
  2172. if Assigned(Src) then Src.DrawTo(Self, DstX, DstY, SrcRect);
  2173. end;
  2174. procedure TCustomBitmap32.Draw(const DstRect, SrcRect: TRect; Src: TCustomBitmap32);
  2175. begin
  2176. if Assigned(Src) then Src.DrawTo(Self, DstRect, SrcRect);
  2177. end;
  2178. procedure TCustomBitmap32.DrawTo(Dst: TCustomBitmap32);
  2179. begin
  2180. BlockTransfer(Dst, 0, 0, Dst.ClipRect, Self, BoundsRect, DrawMode,
  2181. FOnPixelCombine);
  2182. end;
  2183. procedure TCustomBitmap32.DrawTo(Dst: TCustomBitmap32; DstX, DstY: Integer);
  2184. begin
  2185. BlockTransfer(Dst, DstX, DstY, Dst.ClipRect, Self, BoundsRect, DrawMode,
  2186. FOnPixelCombine);
  2187. end;
  2188. procedure TCustomBitmap32.DrawTo(Dst: TCustomBitmap32; DstX, DstY: Integer;
  2189. const SrcRect: TRect);
  2190. begin
  2191. BlockTransfer(Dst, DstX, DstY, Dst.ClipRect, Self, SrcRect,
  2192. DrawMode, FOnPixelCombine);
  2193. end;
  2194. procedure TCustomBitmap32.DrawTo(Dst: TCustomBitmap32; const DstRect: TRect);
  2195. begin
  2196. StretchTransfer(Dst, DstRect, Dst.ClipRect, Self, BoundsRect, Resampler,
  2197. DrawMode, FOnPixelCombine);
  2198. end;
  2199. procedure TCustomBitmap32.DrawTo(Dst: TCustomBitmap32; const DstRect,
  2200. SrcRect: TRect);
  2201. begin
  2202. StretchTransfer(Dst, DstRect, Dst.ClipRect, Self, SrcRect, Resampler,
  2203. DrawMode, FOnPixelCombine);
  2204. end;
  2205. procedure TCustomBitmap32.ResetAlpha;
  2206. begin
  2207. ResetAlpha($FF);
  2208. end;
  2209. procedure TCustomBitmap32.ResetAlpha(const AlphaValue: Byte);
  2210. var
  2211. I: Integer;
  2212. P: PByteArray;
  2213. begin
  2214. if not FMeasuringMode then
  2215. begin
  2216. {$IFDEF FPC}
  2217. P := Pointer(Bits);
  2218. for I := 0 to Width * Height - 1 do
  2219. begin
  2220. P^[3] := AlphaValue;
  2221. Inc(P, 4);
  2222. end
  2223. {$ELSE}
  2224. P := Pointer(Bits);
  2225. Inc(P, 3); //shift the pointer to 'alpha' component of the first pixel
  2226. I := Width * Height;
  2227. if I > 16 then
  2228. begin
  2229. I := I * 4 - 64;
  2230. Inc(P, I);
  2231. //16x enrolled loop
  2232. I := - I;
  2233. repeat
  2234. P^[I] := AlphaValue;
  2235. P^[I + 4] := AlphaValue;
  2236. P^[I + 8] := AlphaValue;
  2237. P^[I + 12] := AlphaValue;
  2238. P^[I + 16] := AlphaValue;
  2239. P^[I + 20] := AlphaValue;
  2240. P^[I + 24] := AlphaValue;
  2241. P^[I + 28] := AlphaValue;
  2242. P^[I + 32] := AlphaValue;
  2243. P^[I + 36] := AlphaValue;
  2244. P^[I + 40] := AlphaValue;
  2245. P^[I + 44] := AlphaValue;
  2246. P^[I + 48] := AlphaValue;
  2247. P^[I + 52] := AlphaValue;
  2248. P^[I + 56] := AlphaValue;
  2249. P^[I + 60] := AlphaValue;
  2250. Inc(I, 64)
  2251. until I > 0;
  2252. //eventually remaining bits
  2253. Dec(I, 64);
  2254. while I < 0 do
  2255. begin
  2256. P^[I + 64] := AlphaValue;
  2257. Inc(I, 4);
  2258. end;
  2259. end
  2260. else
  2261. begin
  2262. Dec(I);
  2263. I := I * 4;
  2264. while I >= 0 do
  2265. begin
  2266. P^[I] := AlphaValue;
  2267. Dec(I, 4);
  2268. end;
  2269. end;
  2270. {$ENDIF}
  2271. end;
  2272. Changed;
  2273. end;
  2274. function TCustomBitmap32.GetPixelB(X, Y: Integer): TColor32;
  2275. begin
  2276. // WARNING: this function should never be used on empty bitmaps !!!
  2277. if X < 0 then X := 0
  2278. else if X >= Width then X := Width - 1;
  2279. if Y < 0 then Y := 0
  2280. else if Y >= Height then Y := Height - 1;
  2281. Result := Bits[X + Y * Width];
  2282. end;
  2283. procedure TCustomBitmap32.SetPixelT(X, Y: Integer; Value: TColor32);
  2284. begin
  2285. TBlendMem(BlendProc)(Value, Bits[X + Y * Width]);
  2286. EMMS;
  2287. end;
  2288. procedure TCustomBitmap32.SetPixelT(var Ptr: PColor32; Value: TColor32);
  2289. begin
  2290. TBlendMem(BlendProc)(Value, Ptr^);
  2291. Inc(Ptr);
  2292. EMMS;
  2293. end;
  2294. procedure TCustomBitmap32.SetPixelTS(X, Y: Integer; Value: TColor32);
  2295. begin
  2296. if {$IFDEF CHANGED_IN_PIXELS}not FMeasuringMode and{$ENDIF}
  2297. (X >= FClipRect.Left) and (X < FClipRect.Right) and
  2298. (Y >= FClipRect.Top) and (Y < FClipRect.Bottom) then
  2299. begin
  2300. TBlendMem(BlendProc)(Value, Bits[X + Y * Width]);
  2301. EMMS;
  2302. end;
  2303. {$IFDEF CHANGED_IN_PIXELS}
  2304. Changed(MakeRect(X, Y, X + 1, Y + 1));
  2305. {$ENDIF}
  2306. end;
  2307. procedure TCustomBitmap32.SET_T256(X, Y: Integer; C: TColor32);
  2308. var
  2309. flrx, flry, celx, cely: Longword;
  2310. P: PColor32;
  2311. A: TColor32;
  2312. begin
  2313. { Warning: EMMS should be called after using this method }
  2314. flrx := X and $FF;
  2315. flry := Y and $FF;
  2316. {$IFDEF USENATIVECODE}
  2317. X := X div 256;
  2318. Y := Y div 256;
  2319. {$ELSE}
  2320. asm
  2321. SAR X, 8
  2322. SAR Y, 8
  2323. end;
  2324. {$ENDIF}
  2325. P := @Bits[X + Y * FWidth];
  2326. if FCombineMode = cmBlend then
  2327. begin
  2328. A := C shr 24; // opacity
  2329. celx := A * GAMMA_TABLE[flrx xor $FF];
  2330. cely := GAMMA_TABLE[flry xor $FF];
  2331. flrx := A * GAMMA_TABLE[flrx];
  2332. flry := GAMMA_TABLE[flry];
  2333. CombineMem(C, P^, celx * cely shr 16); Inc(P);
  2334. CombineMem(C, P^, flrx * cely shr 16); Inc(P, FWidth);
  2335. CombineMem(C, P^, flrx * flry shr 16); Dec(P);
  2336. CombineMem(C, P^, celx * flry shr 16);
  2337. end
  2338. else
  2339. begin
  2340. celx := GAMMA_TABLE[flrx xor $FF];
  2341. cely := GAMMA_TABLE[flry xor $FF];
  2342. flrx := GAMMA_TABLE[flrx];
  2343. flry := GAMMA_TABLE[flry];
  2344. CombineMem(MergeReg(C, P^), P^, celx * cely shr 8); Inc(P);
  2345. CombineMem(MergeReg(C, P^), P^, flrx * cely shr 8); Inc(P, FWidth);
  2346. CombineMem(MergeReg(C, P^), P^, flrx * flry shr 8); Dec(P);
  2347. CombineMem(MergeReg(C, P^), P^, celx * flry shr 8);
  2348. end;
  2349. end;
  2350. procedure TCustomBitmap32.SET_TS256(X, Y: Integer; C: TColor32);
  2351. var
  2352. flrx, flry, celx, cely: Longword;
  2353. P: PColor32;
  2354. A: TColor32;
  2355. begin
  2356. { Warning: EMMS should be called after using this method }
  2357. // we're checking against Left - 1 and Top - 1 due to antialiased values...
  2358. if (X < F256ClipRect.Left - 256) or (X >= F256ClipRect.Right) or
  2359. (Y < F256ClipRect.Top - 256) or (Y >= F256ClipRect.Bottom) then Exit;
  2360. flrx := X and $FF;
  2361. flry := Y and $FF;
  2362. {$IFDEF USENATIVECODE}
  2363. X := X div 256;
  2364. Y := Y div 256;
  2365. {$ELSE}
  2366. asm
  2367. SAR X, 8
  2368. SAR Y, 8
  2369. end;
  2370. {$ENDIF}
  2371. P := @Bits[X + Y * FWidth];
  2372. if FCombineMode = cmBlend then
  2373. begin
  2374. A := C shr 24; // opacity
  2375. celx := A * GAMMA_TABLE[flrx xor $FF];
  2376. cely := GAMMA_TABLE[flry xor $FF];
  2377. flrx := A * GAMMA_TABLE[flrx];
  2378. flry := GAMMA_TABLE[flry];
  2379. if (X >= FClipRect.Left) and (Y >= FClipRect.Top) and
  2380. (X < FClipRect.Right - 1) and (Y < FClipRect.Bottom - 1) then
  2381. begin
  2382. CombineMem(C, P^, celx * cely shr 16); Inc(P);
  2383. CombineMem(C, P^, flrx * cely shr 16); Inc(P, FWidth);
  2384. CombineMem(C, P^, flrx * flry shr 16); Dec(P);
  2385. CombineMem(C, P^, celx * flry shr 16);
  2386. end
  2387. else // "pixel" lies on the edge of the bitmap
  2388. with FClipRect do
  2389. begin
  2390. if (X >= Left) and (Y >= Top) then CombineMem(C, P^, celx * cely shr 16); Inc(P);
  2391. if (X < Right - 1) and (Y >= Top) then CombineMem(C, P^, flrx * cely shr 16); Inc(P, FWidth);
  2392. if (X < Right - 1) and (Y < Bottom - 1) then CombineMem(C, P^, flrx * flry shr 16); Dec(P);
  2393. if (X >= Left) and (Y < Bottom - 1) then CombineMem(C, P^, celx * flry shr 16);
  2394. end;
  2395. end
  2396. else
  2397. begin
  2398. celx := GAMMA_TABLE[flrx xor $FF];
  2399. cely := GAMMA_TABLE[flry xor $FF];
  2400. flrx := GAMMA_TABLE[flrx];
  2401. flry := GAMMA_TABLE[flry];
  2402. if (X >= FClipRect.Left) and (Y >= FClipRect.Top) and
  2403. (X < FClipRect.Right - 1) and (Y < FClipRect.Bottom - 1) then
  2404. begin
  2405. CombineMem(MergeReg(C, P^), P^, celx * cely shr 8); Inc(P);
  2406. CombineMem(MergeReg(C, P^), P^, flrx * cely shr 8); Inc(P, FWidth);
  2407. CombineMem(MergeReg(C, P^), P^, flrx * flry shr 8); Dec(P);
  2408. CombineMem(MergeReg(C, P^), P^, celx * flry shr 8);
  2409. end
  2410. else // "pixel" lies on the edge of the bitmap
  2411. with FClipRect do
  2412. begin
  2413. if (X >= Left) and (Y >= Top) then CombineMem(MergeReg(C, P^), P^, celx * cely shr 8); Inc(P);
  2414. if (X < Right - 1) and (Y >= Top) then CombineMem(MergeReg(C, P^), P^, flrx * cely shr 8); Inc(P, FWidth);
  2415. if (X < Right - 1) and (Y < Bottom - 1) then CombineMem(MergeReg(C, P^), P^, flrx * flry shr 8); Dec(P);
  2416. if (X >= Left) and (Y < Bottom - 1) then CombineMem(MergeReg(C, P^), P^, celx * flry shr 8);
  2417. end;
  2418. end;
  2419. end;
  2420. procedure TCustomBitmap32.SetPixelF(X, Y: Single; Value: TColor32);
  2421. begin
  2422. SET_T256(Round(X * 256), Round(Y * 256), Value);
  2423. {$IFNDEF OMIT_MMX}
  2424. EMMS;
  2425. {$ENDIF}
  2426. end;
  2427. procedure TCustomBitmap32.SetPixelX(X, Y: TFixed; Value: TColor32);
  2428. begin
  2429. X := (X + $7F) shr 8;
  2430. Y := (Y + $7F) shr 8;
  2431. SET_T256(X, Y, Value);
  2432. {$IFNDEF OMIT_MMX}
  2433. EMMS;
  2434. {$ENDIF}
  2435. end;
  2436. procedure TCustomBitmap32.SetPixelFS(X, Y: Single; Value: TColor32);
  2437. begin
  2438. {$IFDEF CHANGED_IN_PIXELS}
  2439. if not FMeasuringMode then
  2440. begin
  2441. {$ENDIF}
  2442. SET_TS256(Round(X * 256), Round(Y * 256), Value);
  2443. EMMS;
  2444. {$IFDEF CHANGED_IN_PIXELS}
  2445. end;
  2446. Changed(MakeRect(FloatRect(X, Y, X + 1, Y + 1)));
  2447. {$ENDIF}
  2448. end;
  2449. procedure TCustomBitmap32.SetPixelFW(X, Y: Single; Value: TColor32);
  2450. begin
  2451. {$IFDEF CHANGED_IN_PIXELS}
  2452. if not FMeasuringMode then
  2453. begin
  2454. {$ENDIF}
  2455. SetPixelXW(Round(X * FixedOne), Round(Y * FixedOne), Value);
  2456. EMMS;
  2457. {$IFDEF CHANGED_IN_PIXELS}
  2458. end;
  2459. Changed(MakeRect(FloatRect(X, Y, X + 1, Y + 1)));
  2460. {$ENDIF}
  2461. end;
  2462. procedure TCustomBitmap32.SetPixelXS(X, Y: TFixed; Value: TColor32);
  2463. begin
  2464. {$IFDEF CHANGED_IN_PIXELS}
  2465. if not FMeasuringMode then
  2466. begin
  2467. {$ENDIF}
  2468. {$IFDEF USENATIVECODE}
  2469. X := (X + $7F) div 256;
  2470. Y := (Y + $7F) div 256;
  2471. {$ELSE}
  2472. asm
  2473. ADD X, $7F
  2474. ADD Y, $7F
  2475. SAR X, 8
  2476. SAR Y, 8
  2477. end;
  2478. {$ENDIF}
  2479. SET_TS256(X, Y, Value);
  2480. EMMS;
  2481. {$IFDEF CHANGED_IN_PIXELS}
  2482. end;
  2483. Changed(MakeRect(X, Y, X + 1, Y + 1));
  2484. {$ENDIF}
  2485. end;
  2486. function TCustomBitmap32.GET_T256(X, Y: Integer): TColor32;
  2487. // When using this, remember that it interpolates towards next x and y!
  2488. var
  2489. Pos: Integer;
  2490. begin
  2491. Pos := (X shr 8) + (Y shr 8) * FWidth;
  2492. Result := Interpolator(GAMMA_TABLE[X and $FF xor $FF],
  2493. GAMMA_TABLE[Y and $FF xor $FF],
  2494. @Bits[Pos], @Bits[Pos + FWidth]);
  2495. end;
  2496. function TCustomBitmap32.GET_TS256(X, Y: Integer): TColor32;
  2497. var
  2498. Width256, Height256: Integer;
  2499. begin
  2500. if (X >= F256ClipRect.Left) and (Y >= F256ClipRect.Top) then
  2501. begin
  2502. Width256 := (FClipRect.Right - 1) shl 8;
  2503. Height256 := (FClipRect.Bottom - 1) shl 8;
  2504. if (X < Width256) and (Y < Height256) then
  2505. Result := GET_T256(X,Y)
  2506. else if (X = Width256) and (Y <= Height256) then
  2507. // We're exactly on the right border: no need to interpolate.
  2508. Result := Pixel[FClipRect.Right - 1, Y shr 8]
  2509. else if (X <= Width256) and (Y = Height256) then
  2510. // We're exactly on the bottom border: no need to interpolate.
  2511. Result := Pixel[X shr 8, FClipRect.Bottom - 1]
  2512. else
  2513. Result := FOuterColor;
  2514. end
  2515. else
  2516. Result := FOuterColor;
  2517. end;
  2518. function TCustomBitmap32.GetPixelF(X, Y: Single): TColor32;
  2519. begin
  2520. Result := GET_T256(Round(X * 256), Round(Y * 256));
  2521. {$IFNDEF OMIT_MMX}
  2522. EMMS;
  2523. {$ENDIF}
  2524. end;
  2525. function TCustomBitmap32.GetPixelFS(X, Y: Single): TColor32;
  2526. begin
  2527. Result := GET_TS256(Round(X * 256), Round(Y * 256));
  2528. {$IFNDEF OMIT_MMX}
  2529. EMMS;
  2530. {$ENDIF}
  2531. end;
  2532. function TCustomBitmap32.GetPixelFW(X, Y: Single): TColor32;
  2533. begin
  2534. Result := GetPixelXW(Round(X * FixedOne), Round(Y * FixedOne));
  2535. {$IFNDEF OMIT_MMX}
  2536. EMMS;
  2537. {$ENDIF}
  2538. end;
  2539. function TCustomBitmap32.GetPixelX(X, Y: TFixed): TColor32;
  2540. begin
  2541. X := (X + $7F) shr 8;
  2542. Y := (Y + $7F) shr 8;
  2543. Result := GET_T256(X, Y);
  2544. {$IFNDEF OMIT_MMX}
  2545. EMMS;
  2546. {$ENDIF}
  2547. end;
  2548. function TCustomBitmap32.GetPixelXS(X, Y: TFixed): TColor32;
  2549. {$IFDEF PUREPASCAL}
  2550. begin
  2551. X := (X + $7F) div 256;
  2552. Y := (Y + $7F) div 256;
  2553. Result := GET_TS256(X, Y);
  2554. EMMS;
  2555. {$ELSE}
  2556. asm
  2557. {$IFDEF TARGET_x64}
  2558. PUSH RBP
  2559. SUB RSP,$30
  2560. {$ENDIF}
  2561. ADD X, $7F
  2562. ADD Y, $7F
  2563. SAR X, 8
  2564. SAR Y, 8
  2565. CALL TCustomBitmap32.GET_TS256
  2566. {$IFNDEF OMIT_MMX}
  2567. CMP MMX_ACTIVE.Integer, $00
  2568. JZ @Exit
  2569. DB $0F, $77 /// EMMS
  2570. @Exit:
  2571. {$ENDIF}
  2572. {$IFDEF TARGET_x64}
  2573. LEA RSP,[RBP+$30]
  2574. POP RBP
  2575. {$ENDIF}
  2576. {$ENDIF}
  2577. end;
  2578. function TCustomBitmap32.GetPixelFR(X, Y: Single): TColor32;
  2579. begin
  2580. Result := FResampler.GetSampleFloat(X, Y);
  2581. end;
  2582. function TCustomBitmap32.GetPixelXR(X, Y: TFixed): TColor32;
  2583. begin
  2584. Result := FResampler.GetSampleFixed(X, Y);
  2585. end;
  2586. function TCustomBitmap32.GetPixelW(X, Y: Integer): TColor32;
  2587. begin
  2588. with FClipRect do
  2589. Result := Bits[FWidth * WrapProcVert(Y, Top, Bottom - 1) + WrapProcHorz(X, Left, Right - 1)];
  2590. end;
  2591. procedure TCustomBitmap32.SetPixelW(X, Y: Integer; Value: TColor32);
  2592. begin
  2593. with FClipRect do
  2594. Bits[FWidth * WrapProcVert(Y, Top, Bottom - 1) + WrapProcHorz(X, Left, Right - 1)] := Value;
  2595. end;
  2596. function TCustomBitmap32.GetPixelXW(X, Y: TFixed): TColor32;
  2597. var
  2598. X1, X2, Y1, Y2 :Integer;
  2599. W: Integer;
  2600. begin
  2601. X2 := TFixedRec(X).Int;
  2602. Y2 := TFixedRec(Y).Int;
  2603. with FClipRect do
  2604. begin
  2605. W := Right - 1;
  2606. X1 := WrapProcHorz(X2, Left, W);
  2607. X2 := WrapProcHorz(X2 + 1, Left, W);
  2608. W := Bottom - 1;
  2609. Y1 := WrapProcVert(Y2, Top, W) * Width;
  2610. Y2 := WrapProcVert(Y2 + 1, Top, W) * Width;
  2611. end;
  2612. W := WordRec(TFixedRec(X).Frac).Hi;
  2613. Result := CombineReg(CombineReg(Bits[X2 + Y2], Bits[X1 + Y2], W),
  2614. CombineReg(Bits[X2 + Y1], Bits[X1 + Y1], W),
  2615. WordRec(TFixedRec(Y).Frac).Hi);
  2616. EMMS;
  2617. end;
  2618. class function TCustomBitmap32.GetPlatformBackendClass: TCustomBackendClass;
  2619. begin
  2620. Result := TMemoryBackend;
  2621. end;
  2622. procedure TCustomBitmap32.SetPixelXW(X, Y: TFixed; Value: TColor32);
  2623. begin
  2624. {$IFDEF USENATIVECODE}
  2625. X := (X + $7F) div 256;
  2626. Y := (Y + $7F) div 256;
  2627. {$ELSE}
  2628. asm
  2629. ADD X, $7F
  2630. ADD Y, $7F
  2631. SAR X, 8
  2632. SAR Y, 8
  2633. end;
  2634. {$ENDIF}
  2635. with F256ClipRect do
  2636. SET_T256(WrapProcHorz(X, Left, Right - 128), WrapProcVert(Y, Top, Bottom - 128), Value);
  2637. EMMS;
  2638. end;
  2639. procedure TCustomBitmap32.SetStipple(NewStipple: TArrayOfColor32);
  2640. begin
  2641. FStippleCounter := 0;
  2642. FStipplePattern := Copy(NewStipple, 0, Length(NewStipple));
  2643. end;
  2644. procedure TCustomBitmap32.SetStipple(NewStipple: array of TColor32);
  2645. var
  2646. L: Integer;
  2647. begin
  2648. FStippleCounter := 0;
  2649. L := High(NewStipple) + 1;
  2650. SetLength(FStipplePattern, L);
  2651. MoveLongword(NewStipple[0], FStipplePattern[0], L);
  2652. end;
  2653. procedure TCustomBitmap32.AdvanceStippleCounter(LengthPixels: Single);
  2654. var
  2655. L: Integer;
  2656. Delta: Single;
  2657. begin
  2658. L := Length(FStipplePattern);
  2659. Delta := LengthPixels * FStippleStep;
  2660. if (L = 0) or (Delta = 0) then Exit;
  2661. FStippleCounter := FStippleCounter + Delta;
  2662. FStippleCounter := FStippleCounter - Floor(FStippleCounter / L) * L;
  2663. end;
  2664. function TCustomBitmap32.GetStippleColor: TColor32;
  2665. var
  2666. L: Integer;
  2667. NextIndex, PrevIndex: Integer;
  2668. PrevWeight: Integer;
  2669. begin
  2670. L := Length(FStipplePattern);
  2671. if L = 0 then
  2672. begin
  2673. // no pattern defined, just return something and exit
  2674. Result := clBlack32;
  2675. Exit;
  2676. end;
  2677. FStippleCounter := Wrap(FStippleCounter, L);
  2678. {$IFDEF FPC}
  2679. PrevIndex := Trunc(FStippleCounter);
  2680. {$ELSE}
  2681. PrevIndex := Round(FStippleCounter - 0.5);
  2682. {$ENDIF}
  2683. PrevWeight := $FF - Round($FF * (FStippleCounter - PrevIndex));
  2684. if PrevIndex < 0 then FStippleCounter := L - 1;
  2685. NextIndex := PrevIndex + 1;
  2686. if NextIndex >= L then NextIndex := 0;
  2687. if PrevWeight = $FF then Result := FStipplePattern[PrevIndex]
  2688. else
  2689. begin
  2690. Result := CombineReg(
  2691. FStipplePattern[PrevIndex],
  2692. FStipplePattern[NextIndex],
  2693. PrevWeight);
  2694. EMMS;
  2695. end;
  2696. FStippleCounter := FStippleCounter + FStippleStep;
  2697. end;
  2698. procedure TCustomBitmap32.HorzLine(X1, Y, X2: Integer; Value: TColor32);
  2699. begin
  2700. FillLongword(Bits[X1 + Y * Width], X2 - X1 + 1, Value);
  2701. end;
  2702. procedure TCustomBitmap32.HorzLineS(X1, Y, X2: Integer; Value: TColor32);
  2703. begin
  2704. if FMeasuringMode then
  2705. Changed(MakeRect(X1, Y, X2, Y + 1))
  2706. else if (Y >= FClipRect.Top) and (Y < FClipRect.Bottom) and
  2707. TestClip(X1, X2, FClipRect.Left, FClipRect.Right) then
  2708. begin
  2709. HorzLine(X1, Y, X2, Value);
  2710. Changed(MakeRect(X1, Y, X2, Y + 1));
  2711. end;
  2712. end;
  2713. procedure TCustomBitmap32.HorzLineT(X1, Y, X2: Integer; Value: TColor32);
  2714. var
  2715. i: Integer;
  2716. P: PColor32;
  2717. BlendMem: TBlendMem;
  2718. begin
  2719. if X2 < X1 then Exit;
  2720. P := PixelPtr[X1, Y];
  2721. BlendMem := TBlendMem(BlendProc);
  2722. for i := X1 to X2 do
  2723. begin
  2724. BlendMem(Value, P^);
  2725. Inc(P);
  2726. end;
  2727. EMMS;
  2728. end;
  2729. procedure TCustomBitmap32.HorzLineTS(X1, Y, X2: Integer; Value: TColor32);
  2730. begin
  2731. if FMeasuringMode then
  2732. Changed(MakeRect(X1, Y, X2, Y + 1))
  2733. else if (Y >= FClipRect.Top) and (Y < FClipRect.Bottom) and
  2734. TestClip(X1, X2, FClipRect.Left, FClipRect.Right) then
  2735. begin
  2736. HorzLineT(X1, Y, X2, Value);
  2737. Changed(MakeRect(X1, Y, X2, Y + 1));
  2738. end;
  2739. end;
  2740. procedure TCustomBitmap32.HorzLineTSP(X1, Y, X2: Integer);
  2741. var
  2742. I, N: Integer;
  2743. begin
  2744. if FMeasuringMode then
  2745. Changed(MakeRect(X1, Y, X2, Y + 1))
  2746. else
  2747. begin
  2748. if Empty then Exit;
  2749. if (Y >= FClipRect.Top) and (Y < FClipRect.Bottom) then
  2750. begin
  2751. if ((X1 < FClipRect.Left) and (X2 < FClipRect.Left)) or
  2752. ((X1 >= FClipRect.Right) and (X2 >= FClipRect.Right)) then
  2753. begin
  2754. AdvanceStippleCounter(Abs(X2 - X1) + 1);
  2755. Exit;
  2756. end;
  2757. if X1 < FClipRect.Left then
  2758. begin
  2759. AdvanceStippleCounter(FClipRect.Left - X1);
  2760. X1 := FClipRect.Left;
  2761. end
  2762. else if X1 >= FClipRect.Right then
  2763. begin
  2764. AdvanceStippleCounter(X1 - (FClipRect.Right - 1));
  2765. X1 := FClipRect.Right - 1;
  2766. end;
  2767. N := 0;
  2768. if X2 < FClipRect.Left then
  2769. begin
  2770. N := FClipRect.Left - X2;
  2771. X2 := FClipRect.Left;
  2772. end
  2773. else if X2 >= FClipRect.Right then
  2774. begin
  2775. N := X2 - (FClipRect.Right - 1);
  2776. X2 := FClipRect.Right - 1;
  2777. end;
  2778. if X2 >= X1 then
  2779. for I := X1 to X2 do SetPixelT(I, Y, GetStippleColor)
  2780. else
  2781. for I := X1 downto X2 do SetPixelT(I, Y, GetStippleColor);
  2782. Changed(MakeRect(X1, Y, X2, Y + 1));
  2783. if N > 0 then AdvanceStippleCounter(N);
  2784. end
  2785. else
  2786. AdvanceStippleCounter(Abs(X2 - X1) + 1);
  2787. end;
  2788. end;
  2789. procedure TCustomBitmap32.HorzLineX(X1, Y, X2: TFixed; Value: TColor32);
  2790. //Author: Michael Hansen
  2791. var
  2792. I: Integer;
  2793. ChangedRect: TFixedRect;
  2794. X1F, X2F, YF, Count: Integer;
  2795. Wx1, Wx2, Wy, Wt: TColor32;
  2796. PDst: PColor32;
  2797. begin
  2798. if X1 > X2 then Swap(X1, X2);
  2799. ChangedRect := FixedRect(X1, Y, X2, Y + 1);
  2800. try
  2801. X1F := X1 shr 16;
  2802. X2F := X2 shr 16;
  2803. YF := Y shr 16;
  2804. PDst := PixelPtr[X1F, YF];
  2805. Wy := Y and $ffff xor $ffff;
  2806. Wx1 := X1 and $ffff xor $ffff;
  2807. Wx2 := X2 and $ffff;
  2808. Count := X2F - X1F - 1;
  2809. if Wy > 0 then
  2810. begin
  2811. CombineMem(Value, PDst^, GAMMA_TABLE[(Wy * Wx1) shr 24]);
  2812. Wt := GAMMA_TABLE[Wy shr 8];
  2813. Inc(PDst);
  2814. for I := 0 to Count - 1 do
  2815. begin
  2816. CombineMem(Value, PDst^, Wt);
  2817. Inc(PDst);
  2818. end;
  2819. CombineMem(Value, PDst^, GAMMA_TABLE[(Wy * Wx2) shr 24]);
  2820. end;
  2821. PDst := PixelPtr[X1F, YF + 1];
  2822. Wy := Wy xor $ffff;
  2823. if Wy > 0 then
  2824. begin
  2825. CombineMem(Value, PDst^, GAMMA_TABLE[(Wy * Wx1) shr 24]);
  2826. Inc(PDst);
  2827. Wt := GAMMA_TABLE[Wy shr 8];
  2828. for I := 0 to Count - 1 do
  2829. begin
  2830. CombineMem(Value, PDst^, Wt);
  2831. Inc(PDst);
  2832. end;
  2833. CombineMem(Value, PDst^, GAMMA_TABLE[(Wy * Wx2) shr 24]);
  2834. end;
  2835. finally
  2836. EMMS;
  2837. Changed(MakeRect(ChangedRect), AREAINFO_LINE + 2);
  2838. end;
  2839. end;
  2840. procedure TCustomBitmap32.HorzLineXS(X1, Y, X2: TFixed; Value: TColor32);
  2841. //author: Michael Hansen
  2842. var
  2843. ChangedRect: TFixedRect;
  2844. begin
  2845. if X1 > X2 then Swap(X1, X2);
  2846. ChangedRect := FixedRect(X1, Y, X2, Y + 1);
  2847. if not FMeasuringMode then
  2848. begin
  2849. X1 := Constrain(X1, FFixedClipRect.Left, FFixedClipRect.Right);
  2850. X2 := Constrain(X2, FFixedClipRect.Left, FFixedClipRect.Right);
  2851. if (Abs(X2 - X1) > FIXEDONE) and InRange(Y, FFixedClipRect.Top, FFixedClipRect.Bottom - FIXEDONE) then
  2852. HorzLineX(X1, Y, X2, Value)
  2853. else
  2854. LineXS(X1, Y, X2, Y, Value);
  2855. end;
  2856. Changed(MakeRect(ChangedRect), AREAINFO_LINE + 2);
  2857. end;
  2858. procedure TCustomBitmap32.VertLine(X, Y1, Y2: Integer; Value: TColor32);
  2859. var
  2860. I, NH, NL: Integer;
  2861. P: PColor32;
  2862. begin
  2863. if Y2 < Y1 then Exit;
  2864. P := PixelPtr[X, Y1];
  2865. I := Y2 - Y1 + 1;
  2866. NH := I shr 2;
  2867. NL := I and $03;
  2868. for I := 0 to NH - 1 do
  2869. begin
  2870. P^ := Value; Inc(P, Width);
  2871. P^ := Value; Inc(P, Width);
  2872. P^ := Value; Inc(P, Width);
  2873. P^ := Value; Inc(P, Width);
  2874. end;
  2875. for I := 0 to NL - 1 do
  2876. begin
  2877. P^ := Value; Inc(P, Width);
  2878. end;
  2879. end;
  2880. procedure TCustomBitmap32.VertLineS(X, Y1, Y2: Integer; Value: TColor32);
  2881. begin
  2882. if FMeasuringMode then
  2883. Changed(MakeRect(X, Y1, X + 1, Y2))
  2884. else if (X >= FClipRect.Left) and (X < FClipRect.Right) and
  2885. TestClip(Y1, Y2, FClipRect.Top, FClipRect.Bottom) then
  2886. begin
  2887. VertLine(X, Y1, Y2, Value);
  2888. Changed(MakeRect(X, Y1, X + 1, Y2));
  2889. end;
  2890. end;
  2891. procedure TCustomBitmap32.VertLineT(X, Y1, Y2: Integer; Value: TColor32);
  2892. var
  2893. i: Integer;
  2894. P: PColor32;
  2895. BlendMem: TBlendMem;
  2896. begin
  2897. P := PixelPtr[X, Y1];
  2898. BlendMem := TBlendMem(BlendProc);
  2899. for i := Y1 to Y2 do
  2900. begin
  2901. BlendMem(Value, P^);
  2902. Inc(P, Width);
  2903. end;
  2904. EMMS;
  2905. end;
  2906. procedure TCustomBitmap32.VertLineTS(X, Y1, Y2: Integer; Value: TColor32);
  2907. begin
  2908. if FMeasuringMode then
  2909. Changed(MakeRect(X, Y1, X + 1, Y2))
  2910. else if (X >= FClipRect.Left) and (X < FClipRect.Right) and
  2911. TestClip(Y1, Y2, FClipRect.Top, FClipRect.Bottom) then
  2912. begin
  2913. VertLineT(X, Y1, Y2, Value);
  2914. Changed(MakeRect(X, Y1, X + 1, Y2));
  2915. end;
  2916. end;
  2917. procedure TCustomBitmap32.VertLineTSP(X, Y1, Y2: Integer);
  2918. var
  2919. I, N: Integer;
  2920. begin
  2921. if FMeasuringMode then
  2922. Changed(MakeRect(X, Y1, X + 1, Y2))
  2923. else
  2924. begin
  2925. if Empty then Exit;
  2926. if (X >= FClipRect.Left) and (X < FClipRect.Right) then
  2927. begin
  2928. if ((Y1 < FClipRect.Top) and (Y2 < FClipRect.Top)) or
  2929. ((Y1 >= FClipRect.Bottom) and (Y2 >= FClipRect.Bottom)) then
  2930. begin
  2931. AdvanceStippleCounter(Abs(Y2 - Y1) + 1);
  2932. Exit;
  2933. end;
  2934. if Y1 < FClipRect.Top then
  2935. begin
  2936. AdvanceStippleCounter(FClipRect.Top - Y1);
  2937. Y1 := FClipRect.Top;
  2938. end
  2939. else if Y1 >= FClipRect.Bottom then
  2940. begin
  2941. AdvanceStippleCounter(Y1 - (FClipRect.Bottom - 1));
  2942. Y1 := FClipRect.Bottom - 1;
  2943. end;
  2944. N := 0;
  2945. if Y2 < FClipRect.Top then
  2946. begin
  2947. N := FClipRect.Top - Y2;
  2948. Y2 := FClipRect.Top;
  2949. end
  2950. else if Y2 >= FClipRect.Bottom then
  2951. begin
  2952. N := Y2 - (FClipRect.Bottom - 1);
  2953. Y2 := FClipRect.Bottom - 1;
  2954. end;
  2955. if Y2 >= Y1 then
  2956. for I := Y1 to Y2 do SetPixelT(X, I, GetStippleColor)
  2957. else
  2958. for I := Y1 downto Y2 do SetPixelT(X, I, GetStippleColor);
  2959. Changed(MakeRect(X, Y1, X + 1, Y2));
  2960. if N > 0 then AdvanceStippleCounter(N);
  2961. end
  2962. else
  2963. AdvanceStippleCounter(Abs(Y2 - Y1) + 1);
  2964. end;
  2965. end;
  2966. procedure TCustomBitmap32.VertLineX(X, Y1, Y2: TFixed; Value: TColor32);
  2967. //Author: Michael Hansen
  2968. var
  2969. I: Integer;
  2970. ChangedRect: TFixedRect;
  2971. Y1F, Y2F, XF, Count: Integer;
  2972. Wy1, Wy2, Wx, Wt: TColor32;
  2973. PDst: PColor32;
  2974. begin
  2975. if Y1 > Y2 then Swap(Y1, Y2);
  2976. ChangedRect := FixedRect(X, Y1, X + 1, Y2);
  2977. try
  2978. Y1F := Y1 shr 16;
  2979. Y2F := Y2 shr 16;
  2980. XF := X shr 16;
  2981. PDst := PixelPtr[XF, Y1F];
  2982. Wx := X and $ffff xor $ffff;
  2983. Wy1 := Y1 and $ffff xor $ffff;
  2984. Wy2 := Y2 and $ffff;
  2985. Count := Y2F - Y1F - 1;
  2986. if Wx > 0 then
  2987. begin
  2988. CombineMem(Value, PDst^, GAMMA_TABLE[(Wx * Wy1) shr 24]);
  2989. Wt := GAMMA_TABLE[Wx shr 8];
  2990. Inc(PDst, FWidth);
  2991. for I := 0 to Count - 1 do
  2992. begin
  2993. CombineMem(Value, PDst^, Wt);
  2994. Inc(PDst, FWidth);
  2995. end;
  2996. CombineMem(Value, PDst^, GAMMA_TABLE[(Wx * Wy2) shr 24]);
  2997. end;
  2998. PDst := PixelPtr[XF + 1, Y1F];
  2999. Wx := Wx xor $ffff;
  3000. if Wx > 0 then
  3001. begin
  3002. CombineMem(Value, PDst^, GAMMA_TABLE[(Wx * Wy1) shr 24]);
  3003. Inc(PDst, FWidth);
  3004. Wt := GAMMA_TABLE[Wx shr 8];
  3005. for I := 0 to Count - 1 do
  3006. begin
  3007. CombineMem(Value, PDst^, Wt);
  3008. Inc(PDst, FWidth);
  3009. end;
  3010. CombineMem(Value, PDst^, GAMMA_TABLE[(Wx * Wy2) shr 24]);
  3011. end;
  3012. finally
  3013. EMMS;
  3014. Changed(MakeRect(ChangedRect), AREAINFO_LINE + 2);
  3015. end;
  3016. end;
  3017. procedure TCustomBitmap32.VertLineXS(X, Y1, Y2: TFixed; Value: TColor32);
  3018. //author: Michael Hansen
  3019. var
  3020. ChangedRect: TFixedRect;
  3021. begin
  3022. if Y1 > Y2 then Swap(Y1, Y2);
  3023. ChangedRect := FixedRect(X, Y1, X + 1, Y2);
  3024. if not FMeasuringMode then
  3025. begin
  3026. Y1 := Constrain(Y1, FFixedClipRect.Top, FFixedClipRect.Bottom - FIXEDONE);
  3027. Y2 := Constrain(Y2, FFixedClipRect.Top, FFixedClipRect.Bottom - FIXEDONE);
  3028. if (Abs(Y2 - Y1) > FIXEDONE) and InRange(X, FFixedClipRect.Left, FFixedClipRect.Right - FIXEDONE) then
  3029. VertLineX(X, Y1, Y2, Value)
  3030. else
  3031. LineXS(X, Y1, X, Y2, Value);
  3032. end;
  3033. Changed(MakeRect(ChangedRect), AREAINFO_LINE + 2);
  3034. end;
  3035. procedure TCustomBitmap32.Line(X1, Y1, X2, Y2: Integer; Value: TColor32; L: Boolean);
  3036. var
  3037. Dy, Dx, Sy, Sx, I, Delta: Integer;
  3038. P: PColor32;
  3039. ChangedRect: TRect;
  3040. begin
  3041. ChangedRect := MakeRect(X1, Y1, X2, Y2);
  3042. try
  3043. Dx := X2 - X1;
  3044. Dy := Y2 - Y1;
  3045. if Dx > 0 then Sx := 1
  3046. else if Dx < 0 then
  3047. begin
  3048. Dx := -Dx;
  3049. Sx := -1;
  3050. end
  3051. else // Dx = 0
  3052. begin
  3053. if Dy > 0 then VertLine(X1, Y1, Y2 - 1, Value)
  3054. else if Dy < 0 then VertLine(X1, Y2 + 1, Y1, Value);
  3055. if L then Pixel[X2, Y2] := Value;
  3056. Exit;
  3057. end;
  3058. if Dy > 0 then Sy := 1
  3059. else if Dy < 0 then
  3060. begin
  3061. Dy := -Dy;
  3062. Sy := -1;
  3063. end
  3064. else // Dy = 0
  3065. begin
  3066. if X2 > X1 then HorzLine(X1, Y1, X2 - 1, Value)
  3067. else HorzLine(X2 + 1, Y1, X1, Value);
  3068. if L then Pixel[X2, Y2] := Value;
  3069. Exit;
  3070. end;
  3071. P := PixelPtr[X1, Y1];
  3072. Sy := Sy * Width;
  3073. if Dx > Dy then
  3074. begin
  3075. Delta := Dx shr 1;
  3076. for I := 0 to Dx - 1 do
  3077. begin
  3078. P^ := Value;
  3079. Inc(P, Sx);
  3080. Inc(Delta, Dy);
  3081. if Delta >= Dx then
  3082. begin
  3083. Inc(P, Sy);
  3084. Dec(Delta, Dx);
  3085. end;
  3086. end;
  3087. end
  3088. else // Dx < Dy
  3089. begin
  3090. Delta := Dy shr 1;
  3091. for I := 0 to Dy - 1 do
  3092. begin
  3093. P^ := Value;
  3094. Inc(P, Sy);
  3095. Inc(Delta, Dx);
  3096. if Delta >= Dy then
  3097. begin
  3098. Inc(P, Sx);
  3099. Dec(Delta, Dy);
  3100. end;
  3101. end;
  3102. end;
  3103. if L then P^ := Value;
  3104. finally
  3105. Changed(ChangedRect, AREAINFO_LINE + 2);
  3106. end;
  3107. end;
  3108. procedure TCustomBitmap32.LineS(X1, Y1, X2, Y2: Integer; Value: TColor32; L: Boolean);
  3109. var
  3110. Dx2, Dy2,Cx1, Cx2, Cy1, Cy2, PI, Sx, Sy, Dx, Dy, xd, yd, rem, term, e: Integer;
  3111. OC: Int64;
  3112. Swapped, CheckAux: Boolean;
  3113. P: PColor32;
  3114. ChangedRect: TRect;
  3115. begin
  3116. ChangedRect := MakeRect(X1, Y1, X2, Y2);
  3117. if not FMeasuringMode then
  3118. begin
  3119. Dx := X2 - X1; Dy := Y2 - Y1;
  3120. // check for trivial cases...
  3121. if Dx = 0 then // vertical line?
  3122. begin
  3123. if Dy > 0 then VertLineS(X1, Y1, Y2 - 1, Value)
  3124. else if Dy < 0 then VertLineS(X1, Y2 + 1, Y1, Value);
  3125. if L then PixelS[X2, Y2] := Value;
  3126. Changed;
  3127. Exit;
  3128. end
  3129. else if Dy = 0 then // horizontal line?
  3130. begin
  3131. if Dx > 0 then HorzLineS(X1, Y1, X2 - 1, Value)
  3132. else if Dx < 0 then HorzLineS(X2 + 1, Y1, X1, Value);
  3133. if L then PixelS[X2, Y2] := Value;
  3134. Changed;
  3135. Exit;
  3136. end;
  3137. Cx1 := FClipRect.Left; Cx2 := FClipRect.Right - 1;
  3138. Cy1 := FClipRect.Top; Cy2 := FClipRect.Bottom - 1;
  3139. if Dx > 0 then
  3140. begin
  3141. if (X1 > Cx2) or (X2 < Cx1) then Exit; // segment not visible
  3142. Sx := 1;
  3143. end
  3144. else
  3145. begin
  3146. if (X2 > Cx2) or (X1 < Cx1) then Exit; // segment not visible
  3147. Sx := -1;
  3148. X1 := -X1; X2 := -X2; Dx := -Dx;
  3149. Cx1 := -Cx1; Cx2 := -Cx2;
  3150. Swap(Cx1, Cx2);
  3151. end;
  3152. if Dy > 0 then
  3153. begin
  3154. if (Y1 > Cy2) or (Y2 < Cy1) then Exit; // segment not visible
  3155. Sy := 1;
  3156. end
  3157. else
  3158. begin
  3159. if (Y2 > Cy2) or (Y1 < Cy1) then Exit; // segment not visible
  3160. Sy := -1;
  3161. Y1 := -Y1; Y2 := -Y2; Dy := -Dy;
  3162. Cy1 := -Cy1; Cy2 := -Cy2;
  3163. Swap(Cy1, Cy2);
  3164. end;
  3165. if Dx < Dy then
  3166. begin
  3167. Swapped := True;
  3168. Swap(X1, Y1); Swap(X2, Y2); Swap(Dx, Dy);
  3169. Swap(Cx1, Cy1); Swap(Cx2, Cy2); Swap(Sx, Sy);
  3170. end
  3171. else
  3172. Swapped := False;
  3173. // Bresenham's set up:
  3174. Dx2 := Dx shl 1; Dy2 := Dy shl 1;
  3175. xd := X1; yd := Y1; e := Dy2 - Dx; term := X2;
  3176. CheckAux := True;
  3177. // clipping rect horizontal entry
  3178. if Y1 < Cy1 then
  3179. begin
  3180. OC := Int64(Dx2) * (Cy1 - Y1) - Dx;
  3181. Inc(xd, OC div Dy2);
  3182. rem := OC mod Dy2;
  3183. if xd > Cx2 then Exit;
  3184. if xd >= Cx1 then
  3185. begin
  3186. yd := Cy1;
  3187. Dec(e, rem + Dx);
  3188. if rem > 0 then
  3189. begin
  3190. Inc(xd);
  3191. Inc(e, Dy2);
  3192. end;
  3193. CheckAux := False; // to avoid ugly labels we set this to omit the next check
  3194. end;
  3195. end;
  3196. // clipping rect vertical entry
  3197. if CheckAux and (X1 < Cx1) then
  3198. begin
  3199. OC := Int64(Dy2) * (Cx1 - X1);
  3200. Inc(yd, OC div Dx2);
  3201. rem := OC mod Dx2;
  3202. if (yd > Cy2) or (yd = Cy2) and (rem >= Dx) then Exit;
  3203. xd := Cx1;
  3204. Inc(e, rem);
  3205. if (rem >= Dx) then
  3206. begin
  3207. Inc(yd);
  3208. Dec(e, Dx2);
  3209. end;
  3210. end;
  3211. // set auxiliary var to indicate that temp is not clipped, since
  3212. // temp still has the unclipped value assigned at setup.
  3213. CheckAux := False;
  3214. // is the segment exiting the clipping rect?
  3215. if Y2 > Cy2 then
  3216. begin
  3217. OC := Dx2 * (Cy2 - Y1) + Dx;
  3218. term := X1 + OC div Dy2;
  3219. rem := OC mod Dy2;
  3220. if rem = 0 then Dec(term);
  3221. CheckAux := True; // set auxiliary var to indicate that temp is clipped
  3222. end;
  3223. if term > Cx2 then
  3224. begin
  3225. term := Cx2;
  3226. CheckAux := True; // set auxiliary var to indicate that temp is clipped
  3227. end;
  3228. Inc(term);
  3229. if Sy = -1 then
  3230. yd := -yd;
  3231. if Sx = -1 then
  3232. begin
  3233. xd := -xd;
  3234. term := -term;
  3235. end;
  3236. Dec(Dx2, Dy2);
  3237. if Swapped then
  3238. begin
  3239. PI := Sx * Width;
  3240. P := @Bits[yd + xd * Width];
  3241. end
  3242. else
  3243. begin
  3244. PI := Sx;
  3245. Sy := Sy * Width;
  3246. P := @Bits[xd + yd * Width];
  3247. end;
  3248. // do we need to skip the last pixel of the line and is temp not clipped?
  3249. if not(L or CheckAux) then
  3250. begin
  3251. if xd < term then
  3252. Dec(term)
  3253. else
  3254. Inc(term);
  3255. end;
  3256. while xd <> term do
  3257. begin
  3258. Inc(xd, Sx);
  3259. P^ := Value;
  3260. Inc(P, PI);
  3261. if e >= 0 then
  3262. begin
  3263. Inc(P, Sy);
  3264. Dec(e, Dx2);
  3265. end
  3266. else
  3267. Inc(e, Dy2);
  3268. end;
  3269. end;
  3270. Changed(ChangedRect, AREAINFO_LINE + 2);
  3271. end;
  3272. procedure TCustomBitmap32.LineT(X1, Y1, X2, Y2: Integer; Value: TColor32; L: Boolean);
  3273. var
  3274. Dy, Dx, Sy, Sx, I, Delta: Integer;
  3275. P: PColor32;
  3276. BlendMem: TBlendMem;
  3277. ChangedRect: TRect;
  3278. begin
  3279. ChangedRect := MakeRect(X1, Y1, X2, Y2);
  3280. try
  3281. Dx := X2 - X1;
  3282. Dy := Y2 - Y1;
  3283. if Dx > 0 then Sx := 1
  3284. else if Dx < 0 then
  3285. begin
  3286. Dx := -Dx;
  3287. Sx := -1;
  3288. end
  3289. else // Dx = 0
  3290. begin
  3291. if Dy > 0 then VertLineT(X1, Y1, Y2 - 1, Value)
  3292. else if Dy < 0 then VertLineT(X1, Y2 + 1, Y1, Value);
  3293. if L then SetPixelT(X2, Y2, Value);
  3294. Exit;
  3295. end;
  3296. if Dy > 0 then Sy := 1
  3297. else if Dy < 0 then
  3298. begin
  3299. Dy := -Dy;
  3300. Sy := -1;
  3301. end
  3302. else // Dy = 0
  3303. begin
  3304. if X2 > X1 then HorzLineT(X1, Y1, X2 - 1, Value)
  3305. else HorzLineT(X2 + 1, Y1, X1, Value);
  3306. if L then SetPixelT(X2, Y2, Value);
  3307. Exit;
  3308. end;
  3309. P := PixelPtr[X1, Y1];
  3310. Sy := Sy * Width;
  3311. try
  3312. BlendMem := TBlendMem(BlendProc);
  3313. if Dx > Dy then
  3314. begin
  3315. Delta := Dx shr 1;
  3316. for I := 0 to Dx - 1 do
  3317. begin
  3318. BlendMem(Value, P^);
  3319. Inc(P, Sx);
  3320. Inc(Delta, Dy);
  3321. if Delta >= Dx then
  3322. begin
  3323. Inc(P, Sy);
  3324. Dec(Delta, Dx);
  3325. end;
  3326. end;
  3327. end
  3328. else // Dx < Dy
  3329. begin
  3330. Delta := Dy shr 1;
  3331. for I := 0 to Dy - 1 do
  3332. begin
  3333. BlendMem(Value, P^);
  3334. Inc(P, Sy);
  3335. Inc(Delta, Dx);
  3336. if Delta >= Dy then
  3337. begin
  3338. Inc(P, Sx);
  3339. Dec(Delta, Dy);
  3340. end;
  3341. end;
  3342. end;
  3343. if L then BlendMem(Value, P^);
  3344. finally
  3345. EMMS;
  3346. end;
  3347. finally
  3348. Changed(ChangedRect, AREAINFO_LINE + 2);
  3349. end;
  3350. end;
  3351. procedure TCustomBitmap32.LineTS(X1, Y1, X2, Y2: Integer; Value: TColor32; L: Boolean);
  3352. var
  3353. Cx1, Cx2, Cy1, Cy2, PI, Sx, Sy, Dx, Dy, xd, yd, Dx2, Dy2, rem, term, e: Integer;
  3354. OC: Int64;
  3355. Swapped, CheckAux: Boolean;
  3356. P: PColor32;
  3357. BlendMem: TBlendMem;
  3358. ChangedRect: TRect;
  3359. begin
  3360. ChangedRect := MakeRect(X1, Y1, X2, Y2);
  3361. if not FMeasuringMode then
  3362. begin
  3363. Dx := X2 - X1; Dy := Y2 - Y1;
  3364. // check for trivial cases...
  3365. if Dx = 0 then // vertical line?
  3366. begin
  3367. if Dy > 0 then VertLineTS(X1, Y1, Y2 - 1, Value)
  3368. else if Dy < 0 then VertLineTS(X1, Y2 + 1, Y1, Value);
  3369. if L then SetPixelTS(X2, Y2, Value);
  3370. Exit;
  3371. end
  3372. else if Dy = 0 then // horizontal line?
  3373. begin
  3374. if Dx > 0 then HorzLineTS(X1, Y1, X2 - 1, Value)
  3375. else if Dx < 0 then HorzLineTS(X2 + 1, Y1, X1, Value);
  3376. if L then SetPixelTS(X2, Y2, Value);
  3377. Exit;
  3378. end;
  3379. Cx1 := FClipRect.Left; Cx2 := FClipRect.Right - 1;
  3380. Cy1 := FClipRect.Top; Cy2 := FClipRect.Bottom - 1;
  3381. if Dx > 0 then
  3382. begin
  3383. if (X1 > Cx2) or (X2 < Cx1) then Exit; // segment not visible
  3384. Sx := 1;
  3385. end
  3386. else
  3387. begin
  3388. if (X2 > Cx2) or (X1 < Cx1) then Exit; // segment not visible
  3389. Sx := -1;
  3390. X1 := -X1; X2 := -X2; Dx := -Dx;
  3391. Cx1 := -Cx1; Cx2 := -Cx2;
  3392. Swap(Cx1, Cx2);
  3393. end;
  3394. if Dy > 0 then
  3395. begin
  3396. if (Y1 > Cy2) or (Y2 < Cy1) then Exit; // segment not visible
  3397. Sy := 1;
  3398. end
  3399. else
  3400. begin
  3401. if (Y2 > Cy2) or (Y1 < Cy1) then Exit; // segment not visible
  3402. Sy := -1;
  3403. Y1 := -Y1; Y2 := -Y2; Dy := -Dy;
  3404. Cy1 := -Cy1; Cy2 := -Cy2;
  3405. Swap(Cy1, Cy2);
  3406. end;
  3407. if Dx < Dy then
  3408. begin
  3409. Swapped := True;
  3410. Swap(X1, Y1); Swap(X2, Y2); Swap(Dx, Dy);
  3411. Swap(Cx1, Cy1); Swap(Cx2, Cy2); Swap(Sx, Sy);
  3412. end
  3413. else
  3414. Swapped := False;
  3415. // Bresenham's set up:
  3416. Dx2 := Dx shl 1; Dy2 := Dy shl 1;
  3417. xd := X1; yd := Y1; e := Dy2 - Dx; term := X2;
  3418. CheckAux := True;
  3419. // clipping rect horizontal entry
  3420. if Y1 < Cy1 then
  3421. begin
  3422. OC := Int64(Dx2) * (Cy1 - Y1) - Dx;
  3423. Inc(xd, OC div Dy2);
  3424. rem := OC mod Dy2;
  3425. if xd > Cx2 then Exit;
  3426. if xd >= Cx1 then
  3427. begin
  3428. yd := Cy1;
  3429. Dec(e, rem + Dx);
  3430. if rem > 0 then
  3431. begin
  3432. Inc(xd);
  3433. Inc(e, Dy2);
  3434. end;
  3435. CheckAux := False; // to avoid ugly labels we set this to omit the next check
  3436. end;
  3437. end;
  3438. // clipping rect vertical entry
  3439. if CheckAux and (X1 < Cx1) then
  3440. begin
  3441. OC := Int64(Dy2) * (Cx1 - X1);
  3442. Inc(yd, OC div Dx2);
  3443. rem := OC mod Dx2;
  3444. if (yd > Cy2) or (yd = Cy2) and (rem >= Dx) then Exit;
  3445. xd := Cx1;
  3446. Inc(e, rem);
  3447. if (rem >= Dx) then
  3448. begin
  3449. Inc(yd);
  3450. Dec(e, Dx2);
  3451. end;
  3452. end;
  3453. // set auxiliary var to indicate that temp is not clipped, since
  3454. // temp still has the unclipped value assigned at setup.
  3455. CheckAux := False;
  3456. // is the segment exiting the clipping rect?
  3457. if Y2 > Cy2 then
  3458. begin
  3459. OC := Int64(Dx2) * (Cy2 - Y1) + Dx;
  3460. term := X1 + OC div Dy2;
  3461. rem := OC mod Dy2;
  3462. if rem = 0 then Dec(term);
  3463. CheckAux := True; // set auxiliary var to indicate that temp is clipped
  3464. end;
  3465. if term > Cx2 then
  3466. begin
  3467. term := Cx2;
  3468. CheckAux := True; // set auxiliary var to indicate that temp is clipped
  3469. end;
  3470. Inc(term);
  3471. if Sy = -1 then
  3472. yd := -yd;
  3473. if Sx = -1 then
  3474. begin
  3475. xd := -xd;
  3476. term := -term;
  3477. end;
  3478. Dec(Dx2, Dy2);
  3479. if Swapped then
  3480. begin
  3481. PI := Sx * Width;
  3482. P := @Bits[yd + xd * Width];
  3483. end
  3484. else
  3485. begin
  3486. PI := Sx;
  3487. Sy := Sy * Width;
  3488. P := @Bits[xd + yd * Width];
  3489. end;
  3490. // do we need to skip the last pixel of the line and is temp not clipped?
  3491. if not(L or CheckAux) then
  3492. begin
  3493. if xd < term then
  3494. Dec(term)
  3495. else
  3496. Inc(term);
  3497. end;
  3498. try
  3499. BlendMem := BLEND_MEM[FCombineMode]^;
  3500. while xd <> term do
  3501. begin
  3502. Inc(xd, Sx);
  3503. BlendMem(Value, P^);
  3504. Inc(P, PI);
  3505. if e >= 0 then
  3506. begin
  3507. Inc(P, Sy);
  3508. Dec(e, Dx2);
  3509. end
  3510. else
  3511. Inc(e, Dy2);
  3512. end;
  3513. finally
  3514. EMMS;
  3515. end;
  3516. end;
  3517. Changed(ChangedRect, AREAINFO_LINE + 2);
  3518. end;
  3519. procedure TCustomBitmap32.LineX(X1, Y1, X2, Y2: TFixed; Value: TColor32; L: Boolean);
  3520. var
  3521. n, i: Integer;
  3522. nx, ny, hyp, hypl: Integer;
  3523. A: TColor32;
  3524. h: Single;
  3525. ChangedRect: TFixedRect;
  3526. begin
  3527. ChangedRect := FixedRect(X1, Y1, X2, Y2);
  3528. try
  3529. nx := X2 - X1; ny := Y2 - Y1;
  3530. Inc(X1, 127); Inc(Y1, 127); Inc(X2, 127); Inc(Y2, 127);
  3531. hyp := Hypot(nx, ny);
  3532. hypl := hyp + (Integer(L) * FixedOne);
  3533. if (hypl < 256) then Exit;
  3534. n := hypl shr 16;
  3535. if n > 0 then
  3536. begin
  3537. h := 65536 / hyp;
  3538. nx := Round(nx * h); ny := Round(ny * h);
  3539. for i := 0 to n - 1 do
  3540. begin
  3541. SET_T256(X1 shr 8, Y1 shr 8, Value);
  3542. Inc(X1, nx);
  3543. Inc(Y1, ny);
  3544. end;
  3545. end;
  3546. A := Value shr 24;
  3547. hyp := hypl - n shl 16;
  3548. A := A * Cardinal(hyp) shl 8 and $FF000000;
  3549. SET_T256((X1 + X2 - nx) shr 9, (Y1 + Y2 - ny) shr 9, Value and $00FFFFFF + A);
  3550. finally
  3551. EMMS;
  3552. Changed(MakeRect(ChangedRect), AREAINFO_LINE + 2);
  3553. end;
  3554. end;
  3555. procedure TCustomBitmap32.LineF(X1, Y1, X2, Y2: Single; Value: TColor32; L: Boolean);
  3556. begin
  3557. LineX(Fixed(X1), Fixed(Y1), Fixed(X2), Fixed(Y2), Value, L);
  3558. end;
  3559. procedure TCustomBitmap32.LineXS(X1, Y1, X2, Y2: TFixed; Value: TColor32; L: Boolean);
  3560. var
  3561. n, i: Integer;
  3562. ex, ey, nx, ny, hyp, hypl: Integer;
  3563. A: TColor32;
  3564. h: Single;
  3565. ChangedRect: TFixedRect;
  3566. begin
  3567. ChangedRect := FixedRect(X1, Y1, X2, Y2);
  3568. if not FMeasuringMode then
  3569. begin
  3570. ex := X2; ey := Y2;
  3571. // Check for visibility and clip the coordinates
  3572. if not ClipLine(Integer(X1), Integer(Y1), Integer(X2), Integer(Y2),
  3573. FFixedClipRect.Left - $10000,
  3574. FFixedClipRect.Top - $10000,
  3575. FFixedClipRect.Right, FFixedClipRect.Bottom) then Exit;
  3576. { TODO : Handle L on clipping here... }
  3577. if (ex <> X2) or (ey <> Y2) then L := True;
  3578. // Check if it lies entirely in the bitmap area. Even after clipping
  3579. // some pixels may lie outside the bitmap due to antialiasing
  3580. if (X1 > FFixedClipRect.Left) and (X1 < FFixedClipRect.Right - $20000) and
  3581. (Y1 > FFixedClipRect.Top) and (Y1 < FFixedClipRect.Bottom - $20000) and
  3582. (X2 > FFixedClipRect.Left) and (X2 < FFixedClipRect.Right - $20000) and
  3583. (Y2 > FFixedClipRect.Top) and (Y2 < FFixedClipRect.Bottom - $20000) then
  3584. begin
  3585. LineX(X1, Y1, X2, Y2, Value, L);
  3586. Exit;
  3587. end;
  3588. // if we are still here, it means that the line touches one or several bitmap
  3589. // boundaries. Use the safe version of antialiased pixel routine
  3590. try
  3591. nx := X2 - X1; ny := Y2 - Y1;
  3592. Inc(X1, 127); Inc(Y1, 127); Inc(X2, 127); Inc(Y2, 127);
  3593. hyp := Hypot(nx, ny);
  3594. if hyp = 0 then Exit;
  3595. hypl := hyp + (Integer(L) * FixedOne);
  3596. if hypl < 256 then Exit;
  3597. n := hypl shr 16;
  3598. if n > 0 then
  3599. begin
  3600. h := 65536 / hyp;
  3601. nx := Round(nx * h); ny := Round(ny * h);
  3602. for i := 0 to n - 1 do
  3603. begin
  3604. SET_TS256(SAR_8(X1), SAR_8(Y1), Value);
  3605. X1 := X1 + nx;
  3606. Y1 := Y1 + ny;
  3607. end;
  3608. end;
  3609. A := Value shr 24;
  3610. hyp := hypl - n shl 16;
  3611. A := A * Cardinal(hyp) shl 8 and $FF000000;
  3612. SET_TS256(SAR_9(X1 + X2 - nx), SAR_9(Y1 + Y2 - ny), Value and $00FFFFFF + A);
  3613. finally
  3614. EMMS;
  3615. end;
  3616. end;
  3617. Changed(MakeRect(ChangedRect), AREAINFO_LINE + 2);
  3618. end;
  3619. procedure TCustomBitmap32.LineFS(X1, Y1, X2, Y2: Single; Value: TColor32; L: Boolean);
  3620. begin
  3621. LineXS(Fixed(X1), Fixed(Y1), Fixed(X2), Fixed(Y2), Value, L);
  3622. end;
  3623. procedure TCustomBitmap32.LineXP(X1, Y1, X2, Y2: TFixed; L: Boolean);
  3624. var
  3625. n, i: Integer;
  3626. nx, ny, hyp, hypl: Integer;
  3627. A, C: TColor32;
  3628. ChangedRect: TRect;
  3629. begin
  3630. ChangedRect := MakeRect(FixedRect(X1, Y1, X2, Y2));
  3631. try
  3632. nx := X2 - X1; ny := Y2 - Y1;
  3633. Inc(X1, 127); Inc(Y1, 127); Inc(X2, 127); Inc(Y2, 127);
  3634. hyp := Hypot(nx, ny);
  3635. hypl := hyp + (Integer(L) * FixedOne);
  3636. if hypl < 256 then Exit;
  3637. n := hypl shr 16;
  3638. if n > 0 then
  3639. begin
  3640. nx := Round(nx / hyp * 65536);
  3641. ny := Round(ny / hyp * 65536);
  3642. for i := 0 to n - 1 do
  3643. begin
  3644. C := GetStippleColor;
  3645. SET_T256(X1 shr 8, Y1 shr 8, C);
  3646. EMMS;
  3647. X1 := X1 + nx;
  3648. Y1 := Y1 + ny;
  3649. end;
  3650. end;
  3651. C := GetStippleColor;
  3652. A := C shr 24;
  3653. hyp := hypl - n shl 16;
  3654. A := A * Longword(hyp) shl 8 and $FF000000;
  3655. SET_T256((X1 + X2 - nx) shr 9, (Y1 + Y2 - ny) shr 9, C and $00FFFFFF + A);
  3656. EMMS;
  3657. finally
  3658. Changed(ChangedRect, AREAINFO_LINE + 2);
  3659. end;
  3660. end;
  3661. procedure TCustomBitmap32.LineFP(X1, Y1, X2, Y2: Single; L: Boolean);
  3662. begin
  3663. LineXP(Fixed(X1), Fixed(Y1), Fixed(X2), Fixed(Y2), L);
  3664. end;
  3665. procedure TCustomBitmap32.LineXSP(X1, Y1, X2, Y2: TFixed; L: Boolean);
  3666. const
  3667. StippleInc: array [Boolean] of Single = (0, 1);
  3668. var
  3669. n, i: Integer;
  3670. sx, sy, ex, ey, nx, ny, hyp, hypl: Integer;
  3671. A, C: TColor32;
  3672. ChangedRect: TRect;
  3673. begin
  3674. ChangedRect := MakeRect(FixedRect(X1, Y1, X2, Y2));
  3675. if not FMeasuringMode then
  3676. begin
  3677. sx := X1; sy := Y1; ex := X2; ey := Y2;
  3678. // Check for visibility and clip the coordinates
  3679. if not ClipLine(Integer(X1), Integer(Y1), Integer(X2), Integer(Y2),
  3680. FFixedClipRect.Left - $10000, FFixedClipRect.Top - $10000,
  3681. FFixedClipRect.Right, FFixedClipRect.Bottom) then
  3682. begin
  3683. AdvanceStippleCounter(GR32_Math.Hypot(Integer((X2 - X1) shr 16),
  3684. Integer((Y2 - Y1) shr 16) - StippleInc[L]));
  3685. Exit;
  3686. end;
  3687. if (ex <> X2) or (ey <> Y2) then L := True;
  3688. // Check if it lies entirely in the bitmap area. Even after clipping
  3689. // some pixels may lie outside the bitmap due to antialiasing
  3690. if (X1 > FFixedClipRect.Left) and (X1 < FFixedClipRect.Right - $20000) and
  3691. (Y1 > FFixedClipRect.Top) and (Y1 < FFixedClipRect.Bottom - $20000) and
  3692. (X2 > FFixedClipRect.Left) and (X2 < FFixedClipRect.Right - $20000) and
  3693. (Y2 > FFixedClipRect.Top) and (Y2 < FFixedClipRect.Bottom - $20000) then
  3694. begin
  3695. LineXP(X1, Y1, X2, Y2, L);
  3696. Exit;
  3697. end;
  3698. if (sx <> X1) or (sy <> Y1) then
  3699. AdvanceStippleCounter(GR32_Math.Hypot(Integer((X1 - sx) shr 16),
  3700. Integer((Y1 - sy) shr 16)));
  3701. // if we are still here, it means that the line touches one or several bitmap
  3702. // boundaries. Use the safe version of antialiased pixel routine
  3703. nx := X2 - X1; ny := Y2 - Y1;
  3704. Inc(X1, 127); Inc(Y1, 127); Inc(X2, 127); Inc(Y2, 127);
  3705. hyp := GR32_Math.Hypot(nx, ny);
  3706. if hyp = 0 then Exit;
  3707. hypl := hyp + (Integer(L) * FixedOne);
  3708. if hypl < 256 then Exit;
  3709. n := hypl shr 16;
  3710. if n > 0 then
  3711. begin
  3712. nx := Round(nx / hyp * 65536); ny := Round(ny / hyp * 65536);
  3713. for i := 0 to n - 1 do
  3714. begin
  3715. C := GetStippleColor;
  3716. SET_TS256(SAR_8(X1), SAR_8(Y1), C);
  3717. EMMS;
  3718. X1 := X1 + nx;
  3719. Y1 := Y1 + ny;
  3720. end;
  3721. end;
  3722. C := GetStippleColor;
  3723. A := C shr 24;
  3724. hyp := hypl - n shl 16;
  3725. A := A * Longword(hyp) shl 8 and $FF000000;
  3726. SET_TS256(SAR_9(X1 + X2 - nx), SAR_9(Y1 + Y2 - ny), C and $00FFFFFF + A);
  3727. EMMS;
  3728. if (ex <> X2) or (ey <> Y2) then
  3729. AdvanceStippleCounter(GR32_Math.Hypot(Integer((X2 - ex) shr 16),
  3730. Integer((Y2 - ey) shr 16) - StippleInc[L]));
  3731. end;
  3732. Changed(ChangedRect, AREAINFO_LINE + 4);
  3733. end;
  3734. procedure TCustomBitmap32.LineFSP(X1, Y1, X2, Y2: Single; L: Boolean);
  3735. begin
  3736. LineXSP(Fixed(X1), Fixed(Y1), Fixed(X2), Fixed(Y2), L);
  3737. end;
  3738. procedure TCustomBitmap32.LineA(X1, Y1, X2, Y2: Integer; Value: TColor32; L: Boolean);
  3739. var
  3740. Dx, Dy, Sx, Sy, D: Integer;
  3741. EC, EA: Word;
  3742. CI: Byte;
  3743. P: PColor32;
  3744. BlendMemEx: TBlendMemEx;
  3745. begin
  3746. if (X1 = X2) or (Y1 = Y2) then
  3747. begin
  3748. LineT(X1, Y1, X2, Y2, Value, L);
  3749. Exit;
  3750. end;
  3751. Dx := X2 - X1;
  3752. Dy := Y2 - Y1;
  3753. if Dx > 0 then Sx := 1
  3754. else
  3755. begin
  3756. Sx := -1;
  3757. Dx := -Dx;
  3758. end;
  3759. if Dy > 0 then Sy := 1
  3760. else
  3761. begin
  3762. Sy := -1;
  3763. Dy := -Dy;
  3764. end;
  3765. try
  3766. EC := 0;
  3767. BLEND_MEM[FCombineMode]^(Value, Bits[X1 + Y1 * Width]);
  3768. BlendMemEx := BLEND_MEM_EX[FCombineMode]^;
  3769. if Dy > Dx then
  3770. begin
  3771. EA := Dx shl 16 div Dy;
  3772. if not L then Dec(Dy);
  3773. while Dy > 0 do
  3774. begin
  3775. Dec(Dy);
  3776. D := EC;
  3777. Inc(EC, EA);
  3778. if EC <= D then Inc(X1, Sx);
  3779. Inc(Y1, Sy);
  3780. CI := EC shr 8;
  3781. P := @Bits[X1 + Y1 * Width];
  3782. BlendMemEx(Value, P^, GAMMA_TABLE[CI xor $FF]);
  3783. Inc(P, Sx);
  3784. BlendMemEx(Value, P^, GAMMA_TABLE[CI]);
  3785. end;
  3786. end
  3787. else // DY <= DX
  3788. begin
  3789. EA := Dy shl 16 div Dx;
  3790. if not L then Dec(Dx);
  3791. while Dx > 0 do
  3792. begin
  3793. Dec(Dx);
  3794. D := EC;
  3795. Inc(EC, EA);
  3796. if EC <= D then Inc(Y1, Sy);
  3797. Inc(X1, Sx);
  3798. CI := EC shr 8;
  3799. P := @Bits[X1 + Y1 * Width];
  3800. BlendMemEx(Value, P^, GAMMA_TABLE[CI xor $FF]);
  3801. if Sy = 1 then Inc(P, Width) else Dec(P, Width);
  3802. BlendMemEx(Value, P^, GAMMA_TABLE[CI]);
  3803. end;
  3804. end;
  3805. finally
  3806. EMMS;
  3807. Changed(MakeRect(X1, Y1, X2, Y2), AREAINFO_LINE + 2);
  3808. end;
  3809. end;
  3810. procedure TCustomBitmap32.LineAS(X1, Y1, X2, Y2: Integer; Value: TColor32; L: Boolean);
  3811. var
  3812. Cx1, Cx2, Cy1, Cy2, PI, Sx, Sy, Dx, Dy, xd, yd, rem, term, tmp: Integer;
  3813. CheckVert, CornerAA, TempClipped: Boolean;
  3814. D1, D2: PInteger;
  3815. EC, EA, ED, D: Word;
  3816. CI: Byte;
  3817. P: PColor32;
  3818. BlendMemEx: TBlendMemEx;
  3819. ChangedRect: TRect;
  3820. begin
  3821. ChangedRect := MakeRect(X1, Y1, X2, Y2);
  3822. if not FMeasuringMode then
  3823. begin
  3824. if (FClipRect.Right - FClipRect.Left = 0) or
  3825. (FClipRect.Bottom - FClipRect.Top = 0) then Exit;
  3826. Dx := X2 - X1; Dy := Y2 - Y1;
  3827. // check for trivial cases...
  3828. if Abs(Dx) = Abs(Dy) then // diagonal line?
  3829. begin
  3830. LineTS(X1, Y1, X2, Y2, Value, L);
  3831. Exit;
  3832. end
  3833. else if Dx = 0 then // vertical line?
  3834. begin
  3835. if Dy > 0 then VertLineTS(X1, Y1, Y2 - 1, Value)
  3836. else if Dy < 0 then VertLineTS(X1, Y2 + 1, Y1, Value);
  3837. if L then SetPixelTS(X2, Y2, Value);
  3838. Exit;
  3839. end
  3840. else if Dy = 0 then // horizontal line?
  3841. begin
  3842. if Dx > 0 then HorzLineTS(X1, Y1, X2 - 1, Value)
  3843. else if Dx < 0 then HorzLineTS(X2 + 1, Y1, X1, Value);
  3844. if L then SetPixelTS(X2, Y2, Value);
  3845. Exit;
  3846. end;
  3847. Cx1 := FClipRect.Left; Cx2 := FClipRect.Right - 1;
  3848. Cy1 := FClipRect.Top; Cy2 := FClipRect.Bottom - 1;
  3849. if Dx > 0 then
  3850. begin
  3851. if (X1 > Cx2) or (X2 < Cx1) then Exit; // segment not visible
  3852. Sx := 1;
  3853. end
  3854. else
  3855. begin
  3856. if (X2 > Cx2) or (X1 < Cx1) then Exit; // segment not visible
  3857. Sx := -1;
  3858. X1 := -X1; X2 := -X2; Dx := -Dx;
  3859. Cx1 := -Cx1; Cx2 := -Cx2;
  3860. Swap(Cx1, Cx2);
  3861. end;
  3862. if Dy > 0 then
  3863. begin
  3864. if (Y1 > Cy2) or (Y2 < Cy1) then Exit; // segment not visible
  3865. Sy := 1;
  3866. end
  3867. else
  3868. begin
  3869. if (Y2 > Cy2) or (Y1 < Cy1) then Exit; // segment not visible
  3870. Sy := -1;
  3871. Y1 := -Y1; Y2 := -Y2; Dy := -Dy;
  3872. Cy1 := -Cy1; Cy2 := -Cy2;
  3873. Swap(Cy1, Cy2);
  3874. end;
  3875. if Dx < Dy then
  3876. begin
  3877. Swap(X1, Y1); Swap(X2, Y2); Swap(Dx, Dy);
  3878. Swap(Cx1, Cy1); Swap(Cx2, Cy2); Swap(Sx, Sy);
  3879. D1 := @yd; D2 := @xd;
  3880. PI := Sy;
  3881. end
  3882. else
  3883. begin
  3884. D1 := @xd; D2 := @yd;
  3885. PI := Sy * Width;
  3886. end;
  3887. rem := 0;
  3888. EA := Dy shl 16 div Dx;
  3889. EC := 0;
  3890. xd := X1; yd := Y1;
  3891. CheckVert := True;
  3892. CornerAA := False;
  3893. BlendMemEx := BLEND_MEM_EX[FCombineMode]^;
  3894. // clipping rect horizontal entry
  3895. if Y1 < Cy1 then
  3896. begin
  3897. tmp := (Cy1 - Y1) * 65536;
  3898. rem := tmp - 65536; // rem := (Cy1 - Y1 - 1) * 65536;
  3899. if tmp mod EA > 0 then
  3900. tmp := tmp div EA + 1
  3901. else
  3902. tmp := tmp div EA;
  3903. xd := Math.Min(xd + tmp, X2 + 1);
  3904. EC := tmp * EA;
  3905. if rem mod EA > 0 then
  3906. rem := rem div EA + 1
  3907. else
  3908. rem := rem div EA;
  3909. tmp := tmp - rem;
  3910. // check whether the line is partly visible
  3911. if xd > Cx2 then
  3912. // do we need to draw an antialiased part on the corner of the clip rect?
  3913. if xd <= Cx2 + tmp then
  3914. CornerAA := True
  3915. else
  3916. Exit;
  3917. if (xd {+ 1} >= Cx1) or CornerAA then
  3918. begin
  3919. yd := Cy1;
  3920. rem := xd; // save old xd
  3921. ED := EC - EA;
  3922. term := SwapConstrain(xd - tmp, Cx1, Cx2);
  3923. if CornerAA then
  3924. begin
  3925. Dec(ED, (xd - Cx2 - 1) * EA);
  3926. xd := Cx2 + 1;
  3927. end;
  3928. // do we need to negate the vars?
  3929. if Sy = -1 then yd := -yd;
  3930. if Sx = -1 then
  3931. begin
  3932. xd := -xd;
  3933. term := -term;
  3934. end;
  3935. // draw special case horizontal line entry (draw only last half of entering segment)
  3936. try
  3937. while xd <> term do
  3938. begin
  3939. Inc(xd, -Sx);
  3940. BlendMemEx(Value, Bits[D1^ + D2^ * Width], GAMMA_TABLE[ED shr 8]);
  3941. Dec(ED, EA);
  3942. end;
  3943. finally
  3944. EMMS;
  3945. end;
  3946. if CornerAA then
  3947. begin
  3948. // we only needed to draw the visible antialiased part of the line,
  3949. // everything else is outside of our cliprect, so exit now since
  3950. // there is nothing more to paint...
  3951. { TODO : Handle Changed here... }
  3952. Changed;
  3953. Exit;
  3954. end;
  3955. if Sy = -1 then yd := -yd; // negate back
  3956. xd := rem; // restore old xd
  3957. CheckVert := False; // to avoid ugly labels we set this to omit the next check
  3958. end;
  3959. end;
  3960. // clipping rect vertical entry
  3961. if CheckVert and (X1 < Cx1) then
  3962. begin
  3963. tmp := (Cx1 - X1) * EA;
  3964. Inc(yd, tmp div 65536);
  3965. EC := tmp;
  3966. xd := Cx1;
  3967. if (yd > Cy2) then
  3968. Exit
  3969. else if (yd = Cy2) then
  3970. CornerAA := True;
  3971. end;
  3972. term := X2;
  3973. TempClipped := False;
  3974. CheckVert := False;
  3975. // horizontal exit?
  3976. if Y2 > Cy2 then
  3977. begin
  3978. tmp := (Cy2 - Y1) * 65536;
  3979. term := X1 + tmp div EA;
  3980. if not(tmp mod EA > 0) then
  3981. Dec(Term);
  3982. if term < Cx2 then
  3983. begin
  3984. rem := tmp + 65536; // was: rem := (Cy2 - Y1 + 1) * 65536;
  3985. if rem mod EA > 0 then
  3986. rem := X1 + rem div EA + 1
  3987. else
  3988. rem := X1 + rem div EA;
  3989. if rem > Cx2 then rem := Cx2;
  3990. CheckVert := True;
  3991. end;
  3992. TempClipped := True;
  3993. end;
  3994. if term > Cx2 then
  3995. begin
  3996. term := Cx2;
  3997. TempClipped := True;
  3998. end;
  3999. Inc(term);
  4000. if Sy = -1 then yd := -yd;
  4001. if Sx = -1 then
  4002. begin
  4003. xd := -xd;
  4004. term := -term;
  4005. rem := -rem;
  4006. end;
  4007. // draw line
  4008. if not CornerAA then
  4009. try
  4010. // do we need to skip the last pixel of the line and is temp not clipped?
  4011. if not(L or TempClipped) and not CheckVert then
  4012. begin
  4013. if xd < term then
  4014. Dec(term)
  4015. else if xd > term then
  4016. Inc(term);
  4017. end;
  4018. while xd <> term do
  4019. begin
  4020. CI := EC shr 8;
  4021. P := @Bits[D1^ + D2^ * Width];
  4022. BlendMemEx(Value, P^, GAMMA_TABLE[CI xor $FF]);
  4023. Inc(P, PI);
  4024. BlendMemEx(Value, P^, GAMMA_TABLE[CI]);
  4025. // check for overflow and jump to next line...
  4026. D := EC;
  4027. Inc(EC, EA);
  4028. if EC <= D then
  4029. Inc(yd, Sy);
  4030. Inc(xd, Sx);
  4031. end;
  4032. finally
  4033. EMMS;
  4034. end;
  4035. // draw special case horizontal line exit (draw only first half of exiting segment)
  4036. if CheckVert then
  4037. try
  4038. while xd <> rem do
  4039. begin
  4040. BlendMemEx(Value, Bits[D1^ + D2^ * Width], GAMMA_TABLE[EC shr 8 xor $FF]);
  4041. Inc(EC, EA);
  4042. Inc(xd, Sx);
  4043. end;
  4044. finally
  4045. EMMS;
  4046. end;
  4047. end;
  4048. Changed(ChangedRect, AREAINFO_LINE + 2);
  4049. end;
  4050. procedure TCustomBitmap32.MoveTo(X, Y: Integer);
  4051. begin
  4052. RasterX := X;
  4053. RasterY := Y;
  4054. end;
  4055. procedure TCustomBitmap32.LineToS(X, Y: Integer);
  4056. begin
  4057. LineS(RasterX, RasterY, X, Y, PenColor);
  4058. RasterX := X;
  4059. RasterY := Y;
  4060. end;
  4061. procedure TCustomBitmap32.LineToTS(X, Y: Integer);
  4062. begin
  4063. LineTS(RasterX, RasterY, X, Y, PenColor);
  4064. RasterX := X;
  4065. RasterY := Y;
  4066. end;
  4067. procedure TCustomBitmap32.LineToAS(X, Y: Integer);
  4068. begin
  4069. LineAS(RasterX, RasterY, X, Y, PenColor);
  4070. RasterX := X;
  4071. RasterY := Y;
  4072. end;
  4073. procedure TCustomBitmap32.MoveToX(X, Y: TFixed);
  4074. begin
  4075. RasterXF := X;
  4076. RasterYF := Y;
  4077. end;
  4078. procedure TCustomBitmap32.MoveToF(X, Y: Single);
  4079. begin
  4080. RasterXF := Fixed(X);
  4081. RasterYF := Fixed(Y);
  4082. end;
  4083. procedure TCustomBitmap32.LineToXS(X, Y: TFixed);
  4084. begin
  4085. LineXS(RasterXF, RasterYF, X, Y, PenColor);
  4086. RasterXF := X;
  4087. RasterYF := Y;
  4088. end;
  4089. procedure TCustomBitmap32.LineToFS(X, Y: Single);
  4090. begin
  4091. LineToXS(Fixed(X), Fixed(Y));
  4092. end;
  4093. procedure TCustomBitmap32.LineToXSP(X, Y: TFixed);
  4094. begin
  4095. LineXSP(RasterXF, RasterYF, X, Y);
  4096. RasterXF := X;
  4097. RasterYF := Y;
  4098. end;
  4099. procedure TCustomBitmap32.LineToFSP(X, Y: Single);
  4100. begin
  4101. LineToXSP(Fixed(X), Fixed(Y));
  4102. end;
  4103. procedure TCustomBitmap32.FillRect(X1, Y1, X2, Y2: Integer; Value: TColor32);
  4104. var
  4105. j: Integer;
  4106. P: PColor32Array;
  4107. begin
  4108. if Assigned(FBits) then
  4109. for j := Y1 to Y2 - 1 do
  4110. begin
  4111. P := Pointer(@Bits[j * FWidth]);
  4112. FillLongword(P[X1], X2 - X1, Value);
  4113. end;
  4114. Changed(MakeRect(X1, Y1, X2, Y2));
  4115. end;
  4116. procedure TCustomBitmap32.FillRectS(X1, Y1, X2, Y2: Integer; Value: TColor32);
  4117. begin
  4118. if not FMeasuringMode and
  4119. (X2 > X1) and (Y2 > Y1) and
  4120. (X1 < FClipRect.Right) and (Y1 < FClipRect.Bottom) and
  4121. (X2 > FClipRect.Left) and (Y2 > FClipRect.Top) then
  4122. begin
  4123. if X1 < FClipRect.Left then X1 := FClipRect.Left;
  4124. if Y1 < FClipRect.Top then Y1 := FClipRect.Top;
  4125. if X2 > FClipRect.Right then X2 := FClipRect.Right;
  4126. if Y2 > FClipRect.Bottom then Y2 := FClipRect.Bottom;
  4127. FillRect(X1, Y1, X2, Y2, Value);
  4128. end;
  4129. Changed(MakeRect(X1, Y1, X2, Y2));
  4130. end;
  4131. procedure TCustomBitmap32.FillRectT(X1, Y1, X2, Y2: Integer; Value: TColor32);
  4132. var
  4133. i, j: Integer;
  4134. P: PColor32;
  4135. A: Integer;
  4136. begin
  4137. A := Value shr 24;
  4138. if A = $FF then
  4139. FillRect(X1, Y1, X2, Y2, Value) // calls Changed...
  4140. else if A <> 0 then
  4141. try
  4142. Dec(Y2);
  4143. Dec(X2);
  4144. for j := Y1 to Y2 do
  4145. begin
  4146. P := GetPixelPtr(X1, j);
  4147. if CombineMode = cmBlend then
  4148. begin
  4149. for i := X1 to X2 do
  4150. begin
  4151. CombineMem(Value, P^, A);
  4152. Inc(P);
  4153. end;
  4154. end
  4155. else
  4156. begin
  4157. for i := X1 to X2 do
  4158. begin
  4159. MergeMem(Value, P^);
  4160. Inc(P);
  4161. end;
  4162. end;
  4163. end;
  4164. finally
  4165. EMMS;
  4166. Changed(MakeRect(X1, Y1, X2 + 1, Y2 + 1));
  4167. end;
  4168. end;
  4169. procedure TCustomBitmap32.FillRectTS(X1, Y1, X2, Y2: Integer; Value: TColor32);
  4170. begin
  4171. if not FMeasuringMode and
  4172. (X2 > X1) and (Y2 > Y1) and
  4173. (X1 < FClipRect.Right) and (Y1 < FClipRect.Bottom) and
  4174. (X2 > FClipRect.Left) and (Y2 > FClipRect.Top) then
  4175. begin
  4176. if X1 < FClipRect.Left then X1 := FClipRect.Left;
  4177. if Y1 < FClipRect.Top then Y1 := FClipRect.Top;
  4178. if X2 > FClipRect.Right then X2 := FClipRect.Right;
  4179. if Y2 > FClipRect.Bottom then Y2 := FClipRect.Bottom;
  4180. FillRectT(X1, Y1, X2, Y2, Value);
  4181. end;
  4182. Changed(MakeRect(X1, Y1, X2, Y2));
  4183. end;
  4184. procedure TCustomBitmap32.FillRectS(const ARect: TRect; Value: TColor32);
  4185. begin
  4186. if FMeasuringMode then // shortcut...
  4187. Changed(ARect)
  4188. else
  4189. with ARect do FillRectS(Left, Top, Right, Bottom, Value);
  4190. end;
  4191. procedure TCustomBitmap32.FillRectTS(const ARect: TRect; Value: TColor32);
  4192. begin
  4193. if FMeasuringMode then // shortcut...
  4194. Changed(ARect)
  4195. else
  4196. with ARect do FillRectTS(Left, Top, Right, Bottom, Value);
  4197. end;
  4198. procedure TCustomBitmap32.FrameRectS(X1, Y1, X2, Y2: Integer; Value: TColor32);
  4199. begin
  4200. // measuring is handled in inner drawing operations...
  4201. if (X2 > X1) and (Y2 > Y1) and
  4202. (X1 < FClipRect.Right) and (Y1 < FClipRect.Bottom) and
  4203. (X2 > FClipRect.Left) and (Y2 > FClipRect.Top) then
  4204. begin
  4205. Dec(Y2);
  4206. Dec(X2);
  4207. HorzLineS(X1, Y1, X2, Value);
  4208. if Y2 > Y1 then HorzLineS(X1, Y2, X2, Value);
  4209. if Y2 > Y1 + 1 then
  4210. begin
  4211. VertLineS(X1, Y1 + 1, Y2 - 1, Value);
  4212. if X2 > X1 then VertLineS(X2, Y1 + 1, Y2 - 1, Value);
  4213. end;
  4214. end;
  4215. end;
  4216. procedure TCustomBitmap32.FrameRectTS(X1, Y1, X2, Y2: Integer; Value: TColor32);
  4217. begin
  4218. // measuring is handled in inner drawing operations...
  4219. if (X2 > X1) and (Y2 > Y1) and
  4220. (X1 < FClipRect.Right) and (Y1 < FClipRect.Bottom) and
  4221. (X2 > FClipRect.Left) and (Y2 > FClipRect.Top) then
  4222. begin
  4223. Dec(Y2);
  4224. Dec(X2);
  4225. HorzLineTS(X1, Y1, X2, Value);
  4226. if Y2 > Y1 then HorzLineTS(X1, Y2, X2, Value);
  4227. if Y2 > Y1 + 1 then
  4228. begin
  4229. VertLineTS(X1, Y1 + 1, Y2 - 1, Value);
  4230. if X2 > X1 then VertLineTS(X2, Y1 + 1, Y2 - 1, Value);
  4231. end;
  4232. end;
  4233. end;
  4234. procedure TCustomBitmap32.FrameRectTSP(X1, Y1, X2, Y2: Integer);
  4235. begin
  4236. // measuring is handled in inner drawing operations...
  4237. if (X2 > X1) and (Y2 > Y1) and
  4238. (X1 < Width) and (Y1 < Height) and // don't check against ClipRect here
  4239. (X2 > 0) and (Y2 > 0) then // due to StippleCounter
  4240. begin
  4241. Dec(X2);
  4242. Dec(Y2);
  4243. if X1 = X2 then
  4244. if Y1 = Y2 then
  4245. begin
  4246. SetPixelT(X1, Y1, GetStippleColor);
  4247. Changed(MakeRect(X1, Y1, X1 + 1, Y1 + 1));
  4248. end
  4249. else
  4250. VertLineTSP(X1, Y1, Y2)
  4251. else
  4252. if Y1 = Y2 then HorzLineTSP(X1, Y1, X2)
  4253. else
  4254. begin
  4255. HorzLineTSP(X1, Y1, X2 - 1);
  4256. VertLineTSP(X2, Y1, Y2 - 1);
  4257. HorzLineTSP(X2, Y2, X1 + 1);
  4258. VertLineTSP(X1, Y2, Y1 + 1);
  4259. end;
  4260. end;
  4261. end;
  4262. procedure TCustomBitmap32.FrameRectS(const ARect: TRect; Value: TColor32);
  4263. begin
  4264. with ARect do FrameRectS(Left, Top, Right, Bottom, Value);
  4265. end;
  4266. procedure TCustomBitmap32.FrameRectTS(const ARect: TRect; Value: TColor32);
  4267. begin
  4268. with ARect do FrameRectTS(Left, Top, Right, Bottom, Value);
  4269. end;
  4270. procedure TCustomBitmap32.RaiseRectTS(X1, Y1, X2, Y2: Integer; Contrast: Integer);
  4271. var
  4272. C1, C2: TColor32;
  4273. begin
  4274. // measuring is handled in inner drawing operations...
  4275. if (X2 > X1) and (Y2 > Y1) and
  4276. (X1 < FClipRect.Right) and (Y1 < FClipRect.Bottom) and
  4277. (X2 > FClipRect.Left) and (Y2 > FClipRect.Top) then
  4278. begin
  4279. if (Contrast > 0) then
  4280. begin
  4281. C1 := SetAlpha(clWhite32, Clamp(Contrast * 512 div 100));
  4282. C2 := SetAlpha(clBlack32, Clamp(Contrast * $FF div 100));
  4283. end
  4284. else if Contrast < 0 then
  4285. begin
  4286. Contrast := -Contrast;
  4287. C1 := SetAlpha(clBlack32, Clamp(Contrast * $FF div 100));
  4288. C2 := SetAlpha(clWhite32, Clamp(Contrast * 512 div 100));
  4289. end
  4290. else Exit;
  4291. Dec(X2);
  4292. Dec(Y2);
  4293. HorzLineTS(X1, Y1, X2, C1);
  4294. HorzLineTS(X1, Y2, X2, C2);
  4295. Inc(Y1);
  4296. Dec(Y2);
  4297. VertLineTS(X1, Y1, Y2, C1);
  4298. VertLineTS(X2, Y1, Y2, C2);
  4299. end;
  4300. end;
  4301. procedure TCustomBitmap32.RaiseRectTS(const ARect: TRect; Contrast: Integer);
  4302. begin
  4303. with ARect do RaiseRectTS(Left, Top, Right, Bottom, Contrast);
  4304. end;
  4305. procedure TCustomBitmap32.LoadFromStream(Stream: TStream);
  4306. var
  4307. I, W: integer;
  4308. Header: TBmpHeader;
  4309. B: TBitmap;
  4310. begin
  4311. Stream.ReadBuffer(Header, SizeOf(TBmpHeader));
  4312. // Check for Windows bitmap magic bytes and general compatibility of the
  4313. // bitmap data that ought to be loaded...
  4314. if (Header.bfType = $4D42) and
  4315. (Header.biBitCount = 32) and (Header.biPlanes = 1) and
  4316. (Header.biCompression = 0) then
  4317. begin
  4318. SetSize(Header.biWidth, Abs(Header.biHeight));
  4319. // Check whether the bitmap is saved top-down
  4320. if Header.biHeight > 0 then
  4321. begin
  4322. W := Width shl 2;
  4323. for I := Height - 1 downto 0 do
  4324. Stream.ReadBuffer(Scanline[I]^, W);
  4325. end
  4326. else
  4327. Stream.ReadBuffer(Bits^, Width * Height shl 2);
  4328. end
  4329. else
  4330. begin
  4331. Stream.Seek(Int64(-SizeOf(TBmpHeader)), soFromCurrent); // patch from aone
  4332. B := TBitmap.Create;
  4333. try
  4334. B.LoadFromStream(Stream);
  4335. Assign(B);
  4336. finally
  4337. B.Free;
  4338. end;
  4339. end;
  4340. Changed;
  4341. end;
  4342. procedure TCustomBitmap32.SaveToStream(Stream: TStream; SaveTopDown: Boolean = False);
  4343. var
  4344. Header: TBmpHeader;
  4345. BitmapSize: Integer;
  4346. I, W: Integer;
  4347. begin
  4348. BitmapSize := Width * Height shl 2;
  4349. Header.bfType := $4D42; // Magic bytes for Windows Bitmap
  4350. Header.bfSize := BitmapSize + SizeOf(TBmpHeader);
  4351. Header.bfReserved := 0;
  4352. // Save offset relative. However, the spec says it has to be file absolute,
  4353. // which we can not do properly within a stream...
  4354. Header.bfOffBits := SizeOf(TBmpHeader);
  4355. Header.biSize := $28;
  4356. Header.biWidth := Width;
  4357. if SaveTopDown then
  4358. Header.biHeight := Height
  4359. else
  4360. Header.biHeight := -Height;
  4361. Header.biPlanes := 1;
  4362. Header.biBitCount := 32;
  4363. Header.biCompression := 0; // bi_rgb
  4364. Header.biSizeImage := BitmapSize;
  4365. Header.biXPelsPerMeter := 0;
  4366. Header.biYPelsPerMeter := 0;
  4367. Header.biClrUsed := 0;
  4368. Header.biClrImportant := 0;
  4369. Stream.WriteBuffer(Header, SizeOf(TBmpHeader));
  4370. if SaveTopDown then
  4371. begin
  4372. W := Width shl 2;
  4373. for I := Height - 1 downto 0 do
  4374. Stream.WriteBuffer(PixelPtr[0, I]^, W);
  4375. end
  4376. else
  4377. begin
  4378. // NOTE: We can save the whole buffer in one run because
  4379. // we do not support scanline strides (yet).
  4380. Stream.WriteBuffer(Bits^, BitmapSize);
  4381. end;
  4382. end;
  4383. function TCustomBitmap32.Equal(B: TCustomBitmap32): Boolean;
  4384. var
  4385. S1, S2: TMemoryStream;
  4386. begin
  4387. Result := (B <> nil) and (ClassType = B.ClassType);
  4388. if Empty or B.Empty then
  4389. begin
  4390. Result := Empty and B.Empty;
  4391. Exit;
  4392. end;
  4393. if Result then
  4394. begin
  4395. S1 := TMemoryStream.Create;
  4396. try
  4397. SaveToStream(S1);
  4398. S2 := TMemoryStream.Create;
  4399. try
  4400. B.SaveToStream(S2);
  4401. Result := (S1.Size = S2.Size) and CompareMem(S1.Memory, S2.Memory, S1.Size);
  4402. finally
  4403. S2.Free;
  4404. end;
  4405. finally
  4406. S1.Free;
  4407. end;
  4408. end;
  4409. end;
  4410. procedure TCustomBitmap32.DefineProperties(Filer: TFiler);
  4411. function DoWrite: Boolean;
  4412. begin
  4413. if Filer.Ancestor <> nil then
  4414. Result := not (Filer.Ancestor is TCustomBitmap32) or
  4415. not Equal(TCustomBitmap32(Filer.Ancestor))
  4416. else
  4417. Result := not Empty;
  4418. end;
  4419. begin
  4420. Filer.DefineBinaryProperty('Data', ReadData, WriteData, DoWrite);
  4421. end;
  4422. procedure TCustomBitmap32.ReadData(Stream: TStream);
  4423. var
  4424. Width, Height: Integer;
  4425. begin
  4426. try
  4427. Stream.ReadBuffer(Width, 4);
  4428. Stream.ReadBuffer(Height, 4);
  4429. SetSize(Width, Height);
  4430. Stream.ReadBuffer(Bits[0], FWidth * FHeight * 4);
  4431. finally
  4432. Changed;
  4433. end;
  4434. end;
  4435. procedure TCustomBitmap32.WriteData(Stream: TStream);
  4436. begin
  4437. Stream.WriteBuffer(FWidth, 4);
  4438. Stream.WriteBuffer(FHeight, 4);
  4439. Stream.WriteBuffer(Bits[0], FWidth * FHeight * 4);
  4440. end;
  4441. procedure TCustomBitmap32.SetCombineMode(const Value: TCombineMode);
  4442. begin
  4443. if FCombineMode <> Value then
  4444. begin
  4445. FCombineMode := Value;
  4446. BlendProc := @BLEND_MEM[FCombineMode]^;
  4447. Changed;
  4448. end;
  4449. end;
  4450. procedure TCustomBitmap32.SetDrawMode(Value: TDrawMode);
  4451. begin
  4452. if FDrawMode <> Value then
  4453. begin
  4454. FDrawMode := Value;
  4455. Changed;
  4456. end;
  4457. end;
  4458. procedure TCustomBitmap32.SetWrapMode(Value: TWrapMode);
  4459. begin
  4460. if FWrapMode <> Value then
  4461. begin
  4462. FWrapMode := Value;
  4463. WrapProcHorz := GetWrapProcEx(WrapMode, FClipRect.Left, FClipRect.Right - 1);
  4464. WrapProcVert := GetWrapProcEx(WrapMode, FClipRect.Top, FClipRect.Bottom - 1);
  4465. Changed;
  4466. end;
  4467. end;
  4468. procedure TCustomBitmap32.SetMasterAlpha(Value: Cardinal);
  4469. begin
  4470. if FMasterAlpha <> Value then
  4471. begin
  4472. FMasterAlpha := Value;
  4473. Changed;
  4474. end;
  4475. end;
  4476. {$IFDEF DEPRECATEDMODE}
  4477. procedure TCustomBitmap32.SetStretchFilter(Value: TStretchFilter);
  4478. begin
  4479. if FStretchFilter <> Value then
  4480. begin
  4481. FStretchFilter := Value;
  4482. case FStretchFilter of
  4483. sfNearest: TNearestResampler.Create(Self);
  4484. sfDraft: TDraftResampler.Create(Self);
  4485. sfLinear: TLinearResampler.Create(Self);
  4486. else
  4487. TKernelResampler.Create(Self);
  4488. with FResampler as TKernelResampler do
  4489. case FStretchFilter of
  4490. sfCosine: Kernel := TCosineKernel.Create;
  4491. sfSpline: Kernel := TSplineKernel.Create;
  4492. sfLanczos: Kernel := TLanczosKernel.Create;
  4493. sfMitchell: Kernel := TMitchellKernel.Create;
  4494. end;
  4495. end;
  4496. Changed;
  4497. end;
  4498. end;
  4499. {$ENDIF}
  4500. procedure TCustomBitmap32.Roll(Dx, Dy: Integer; FillBack: Boolean; FillColor: TColor32);
  4501. var
  4502. Shift, L: Integer;
  4503. R: TRect;
  4504. begin
  4505. if Empty or ((Dx = 0) and (Dy = 0)) then Exit;
  4506. if (Abs(Dx) >= Width) or (Abs(Dy) >= Height) then
  4507. begin
  4508. if FillBack then Clear(FillColor);
  4509. Exit;
  4510. end;
  4511. Shift := Dx + Dy * Width;
  4512. L := (Width * Height - Abs(Shift));
  4513. if Shift > 0 then
  4514. Move(Bits[0], Bits[Shift], L shl 2)
  4515. else
  4516. MoveLongword(Bits[-Shift], Bits[0], L);
  4517. if FillBack then
  4518. begin
  4519. R := MakeRect(0, 0, Width, Height);
  4520. GR32.OffsetRect(R, Dx, Dy);
  4521. GR32.IntersectRect(R, R, MakeRect(0, 0, Width, Height));
  4522. if R.Top > 0 then
  4523. FillRect(0, 0, Width, R.Top, FillColor)
  4524. else
  4525. if R.Top = 0 then
  4526. FillRect(0, R.Bottom, Width, Height, FillColor);
  4527. if R.Left > 0 then
  4528. FillRect(0, R.Top, R.Left, R.Bottom, FillColor)
  4529. else
  4530. if R.Left = 0 then
  4531. FillRect(R.Right, R.Top, Width, R.Bottom, FillColor);
  4532. end;
  4533. Changed;
  4534. end;
  4535. procedure TCustomBitmap32.FlipHorz(Dst: TCustomBitmap32);
  4536. var
  4537. i, j: Integer;
  4538. P1, P2: PColor32;
  4539. tmp: TColor32;
  4540. W, W2: Integer;
  4541. begin
  4542. W := Width;
  4543. if (Dst = nil) or (Dst = Self) then
  4544. begin
  4545. { In-place flipping }
  4546. P1 := PColor32(Bits);
  4547. P2 := P1;
  4548. Inc(P2, Width - 1);
  4549. W2 := Width shr 1;
  4550. for J := 0 to Height - 1 do
  4551. begin
  4552. for I := 0 to W2 - 1 do
  4553. begin
  4554. tmp := P1^;
  4555. P1^ := P2^;
  4556. P2^ := tmp;
  4557. Inc(P1);
  4558. Dec(P2);
  4559. end;
  4560. Inc(P1, W - W2);
  4561. Inc(P2, W + W2);
  4562. end;
  4563. Changed;
  4564. end
  4565. else
  4566. begin
  4567. { Flip to Dst }
  4568. Dst.BeginUpdate;
  4569. Dst.SetSize(W, Height);
  4570. P1 := PColor32(Bits);
  4571. P2 := PColor32(Dst.Bits);
  4572. Inc(P2, W - 1);
  4573. for J := 0 to Height - 1 do
  4574. begin
  4575. for I := 0 to W - 1 do
  4576. begin
  4577. P2^ := P1^;
  4578. Inc(P1);
  4579. Dec(P2);
  4580. end;
  4581. Inc(P2, W shl 1);
  4582. end;
  4583. Dst.EndUpdate;
  4584. Dst.Changed;
  4585. end;
  4586. end;
  4587. procedure TCustomBitmap32.FlipVert(Dst: TCustomBitmap32);
  4588. var
  4589. J, J2: Integer;
  4590. Buffer: PColor32Array;
  4591. P1, P2: PColor32;
  4592. begin
  4593. if (Dst = nil) or (Dst = Self) then
  4594. begin
  4595. { in-place }
  4596. J2 := Height - 1;
  4597. GetMem(Buffer, Width shl 2);
  4598. for J := 0 to Height div 2 - 1 do
  4599. begin
  4600. P1 := PixelPtr[0, J];
  4601. P2 := PixelPtr[0, J2];
  4602. MoveLongword(P1^, Buffer^, Width);
  4603. MoveLongword(P2^, P1^, Width);
  4604. MoveLongword(Buffer^, P2^, Width);
  4605. Dec(J2);
  4606. end;
  4607. FreeMem(Buffer);
  4608. Changed;
  4609. end
  4610. else
  4611. begin
  4612. Dst.SetSize(Width, Height);
  4613. J2 := Height - 1;
  4614. for J := 0 to Height - 1 do
  4615. begin
  4616. MoveLongword(PixelPtr[0, J]^, Dst.PixelPtr[0, J2]^, Width);
  4617. Dec(J2);
  4618. end;
  4619. Dst.Changed;
  4620. end;
  4621. end;
  4622. procedure TCustomBitmap32.Rotate90(Dst: TCustomBitmap32);
  4623. var
  4624. Tmp: TCustomBitmap32;
  4625. X, Y, I, J: Integer;
  4626. begin
  4627. if Dst = nil then
  4628. begin
  4629. Tmp := TCustomBitmap32.Create;
  4630. Dst := Tmp;
  4631. end
  4632. else
  4633. begin
  4634. Tmp := nil;
  4635. Dst.BeginUpdate;
  4636. end;
  4637. Dst.SetSize(Height, Width);
  4638. I := 0;
  4639. for Y := 0 to Height - 1 do
  4640. begin
  4641. J := Height - 1 - Y;
  4642. for X := 0 to Width - 1 do
  4643. begin
  4644. Dst.Bits[J] := Bits[I];
  4645. Inc(I);
  4646. Inc(J, Height);
  4647. end;
  4648. end;
  4649. if Tmp <> nil then
  4650. begin
  4651. Tmp.CopyMapTo(Self);
  4652. Tmp.Free;
  4653. end
  4654. else
  4655. begin
  4656. Dst.EndUpdate;
  4657. Dst.Changed;
  4658. end;
  4659. end;
  4660. procedure TCustomBitmap32.Rotate180(Dst: TCustomBitmap32);
  4661. var
  4662. I, I2: Integer;
  4663. Tmp: TColor32;
  4664. begin
  4665. if Dst <> nil then
  4666. begin
  4667. Dst.SetSize(Width, Height);
  4668. I2 := Width * Height - 1;
  4669. for I := 0 to Width * Height - 1 do
  4670. begin
  4671. Dst.Bits[I2] := Bits[I];
  4672. Dec(I2);
  4673. end;
  4674. Dst.Changed;
  4675. end
  4676. else
  4677. begin
  4678. I2 := Width * Height - 1;
  4679. for I := 0 to Width * Height div 2 - 1 do
  4680. begin
  4681. Tmp := Bits[I2];
  4682. Bits[I2] := Bits[I];
  4683. Bits[I] := Tmp;
  4684. Dec(I2);
  4685. end;
  4686. Changed;
  4687. end;
  4688. end;
  4689. procedure TCustomBitmap32.Rotate270(Dst: TCustomBitmap32);
  4690. var
  4691. Tmp: TCustomBitmap32;
  4692. X, Y, I, J: Integer;
  4693. begin
  4694. if Dst = nil then
  4695. begin
  4696. Tmp := TCustomBitmap32.Create; { TODO : Revise creating of temporary bitmaps here... }
  4697. Dst := Tmp;
  4698. end
  4699. else
  4700. begin
  4701. Tmp := nil;
  4702. Dst.BeginUpdate;
  4703. end;
  4704. Dst.SetSize(Height, Width);
  4705. I := 0;
  4706. for Y := 0 to Height - 1 do
  4707. begin
  4708. J := (Width - 1) * Height + Y;
  4709. for X := 0 to Width - 1 do
  4710. begin
  4711. Dst.Bits[J] := Bits[I];
  4712. Inc(I);
  4713. Dec(J, Height);
  4714. end;
  4715. end;
  4716. if Tmp <> nil then
  4717. begin
  4718. Tmp.CopyMapTo(Self);
  4719. Tmp.Free;
  4720. end
  4721. else
  4722. begin
  4723. Dst.EndUpdate;
  4724. Dst.Changed;
  4725. end;
  4726. end;
  4727. function TCustomBitmap32.BoundsRect: TRect;
  4728. begin
  4729. Result.Left := 0;
  4730. Result.Top := 0;
  4731. Result.Right := Width;
  4732. Result.Bottom := Height;
  4733. end;
  4734. procedure TCustomBitmap32.SetClipRect(const Value: TRect);
  4735. begin
  4736. GR32.IntersectRect(FClipRect, Value, BoundsRect);
  4737. FFixedClipRect := FixedRect(FClipRect);
  4738. with FClipRect do
  4739. F256ClipRect := Rect(Left shl 8, Top shl 8, Right shl 8, Bottom shl 8);
  4740. FClipping := not GR32.EqualRect(FClipRect, BoundsRect);
  4741. WrapProcHorz := GetWrapProcEx(WrapMode, FClipRect.Left, FClipRect.Right - 1);
  4742. WrapProcVert := GetWrapProcEx(WrapMode, FClipRect.Top, FClipRect.Bottom - 1);
  4743. end;
  4744. procedure TCustomBitmap32.ResetClipRect;
  4745. begin
  4746. ClipRect := BoundsRect;
  4747. end;
  4748. procedure TCustomBitmap32.BeginMeasuring(const Callback: TAreaChangedEvent);
  4749. begin
  4750. FMeasuringMode := True;
  4751. FOldOnAreaChanged := FOnAreaChanged;
  4752. FOnAreaChanged := Callback;
  4753. end;
  4754. procedure TCustomBitmap32.EndMeasuring;
  4755. begin
  4756. FMeasuringMode := False;
  4757. FOnAreaChanged := FOldOnAreaChanged;
  4758. end;
  4759. procedure TCustomBitmap32.PropertyChanged;
  4760. begin
  4761. // don't force invalidation of whole bitmap area as this is unnecessary
  4762. inherited Changed;
  4763. end;
  4764. procedure TCustomBitmap32.Changed;
  4765. begin
  4766. if ((FUpdateCount = 0) or FMeasuringMode) and Assigned(FOnAreaChanged) then
  4767. FOnAreaChanged(Self, BoundsRect, AREAINFO_RECT);
  4768. if not FMeasuringMode then
  4769. inherited;
  4770. end;
  4771. procedure TCustomBitmap32.Changed(const Area: TRect; const Info: Cardinal);
  4772. begin
  4773. if ((FUpdateCount = 0) or FMeasuringMode) and Assigned(FOnAreaChanged) then
  4774. FOnAreaChanged(Self, Area, Info);
  4775. if not FMeasuringMode then
  4776. inherited Changed;
  4777. end;
  4778. procedure TCustomBitmap32.SetResampler(Resampler: TCustomResampler);
  4779. begin
  4780. if Assigned(Resampler) and (FResampler <> Resampler) then
  4781. begin
  4782. if Assigned(FResampler) then FResampler.Free;
  4783. FResampler := Resampler;
  4784. Changed;
  4785. end;
  4786. end;
  4787. function TCustomBitmap32.GetResamplerClassName: string;
  4788. begin
  4789. Result := FResampler.ClassName;
  4790. end;
  4791. procedure TCustomBitmap32.SetResamplerClassName(const Value: string);
  4792. var
  4793. ResamplerClass: TCustomResamplerClass;
  4794. begin
  4795. if (Value <> '') and (FResampler.ClassName <> Value) and Assigned(ResamplerList) then
  4796. begin
  4797. ResamplerClass := TCustomResamplerClass(ResamplerList.Find(Value));
  4798. if Assigned(ResamplerClass) then ResamplerClass.Create(Self);
  4799. end;
  4800. end;
  4801. { TBitmap32 }
  4802. procedure TBitmap32.FinalizeBackend;
  4803. begin
  4804. inherited;
  4805. end;
  4806. class function TBitmap32.GetPlatformBackendClass: TCustomBackendClass;
  4807. begin
  4808. Result := TMemoryBackend;
  4809. end;
  4810. procedure TBitmap32.CopyPropertiesTo(Dst: TCustomBitmap32);
  4811. begin
  4812. inherited;
  4813. end;
  4814. procedure TBitmap32.SetBackend(const Backend: TCustomBackend);
  4815. begin
  4816. if Assigned(Backend) and (Backend <> FBackend) then
  4817. begin
  4818. inherited;
  4819. end;
  4820. end;
  4821. procedure TextBlueToAlpha(const B: TCustomBitmap32; const Color: TColor32);
  4822. (*
  4823. asm
  4824. PUSH EDI
  4825. MOV ECX, [B+$44].Integer
  4826. IMUL ECX, [B+$40].Integer
  4827. MOV EDI, [B+$54].Integer
  4828. @PixelLoop:
  4829. MOV EAX, [EDI]
  4830. SHL EAX, 24
  4831. ADD EAX, Color
  4832. MOV [EDI], EAX
  4833. ADD EDI, 4
  4834. LOOP @PixelLoop
  4835. POP EDI
  4836. end;
  4837. *)
  4838. var
  4839. I: Integer;
  4840. P: PColor32;
  4841. C: TColor32;
  4842. begin
  4843. // convert blue channel to alpha and fill the color
  4844. P := @B.Bits[0];
  4845. for I := 0 to B.Width * B.Height - 1 do
  4846. begin
  4847. C := P^;
  4848. if C <> 0 then
  4849. begin
  4850. C := P^ shl 24; // transfer blue channel to alpha
  4851. C := C + Color;
  4852. P^ := C;
  4853. end;
  4854. Inc(P);
  4855. end;
  4856. end;
  4857. procedure TextScaleDown(const B, B2: TCustomBitmap32; const N: Integer;
  4858. const Color: TColor32); // use only the blue channel
  4859. var
  4860. I, J, X, Y, P, Q, Sz, S: Integer;
  4861. Src: PColor32;
  4862. Dst: PColor32;
  4863. begin
  4864. Sz := 1 shl N - 1;
  4865. Dst := B.PixelPtr[0, 0];
  4866. for J := 0 to B.Height - 1 do
  4867. begin
  4868. Y := J shl N;
  4869. for I := 0 to B.Width - 1 do
  4870. begin
  4871. X := I shl N;
  4872. S := 0;
  4873. for Q := Y to Y + Sz do
  4874. begin
  4875. Src := B2.PixelPtr[X, Q];
  4876. for P := X to X + Sz do
  4877. begin
  4878. S := S + Integer(Src^ and $000000FF);
  4879. Inc(Src);
  4880. end;
  4881. end;
  4882. S := S shr N shr N;
  4883. Dst^ := TColor32(S shl 24) + Color;
  4884. Inc(Dst);
  4885. end;
  4886. end;
  4887. end;
  4888. { TCustomBackend }
  4889. constructor TCustomBackend.Create;
  4890. begin
  4891. RefCounted := True;
  4892. _AddRef;
  4893. inherited;
  4894. end;
  4895. constructor TCustomBackend.Create(Owner: TCustomBitmap32);
  4896. begin
  4897. FOwner := Owner;
  4898. Create;
  4899. if Assigned(Owner) then
  4900. Owner.Backend := Self;
  4901. end;
  4902. destructor TCustomBackend.Destroy;
  4903. begin
  4904. Clear;
  4905. inherited;
  4906. end;
  4907. procedure TCustomBackend.Clear;
  4908. var
  4909. Width, Height: Integer;
  4910. begin
  4911. if Assigned(FOwner) then
  4912. ChangeSize(FOwner.FWidth, FOwner.FHeight, 0, 0, False)
  4913. else
  4914. ChangeSize(Width, Height, 0, 0, False);
  4915. end;
  4916. procedure TCustomBackend.Changing;
  4917. begin
  4918. if Assigned(FOnChanging) then
  4919. FOnChanging(Self);
  4920. end;
  4921. {$IFDEF BITS_GETTER}
  4922. function TCustomBackend.GetBits: PColor32Array;
  4923. begin
  4924. Result := FBits;
  4925. end;
  4926. {$ENDIF}
  4927. procedure TCustomBackend.ChangeSize(out Width, Height: Integer; NewWidth, NewHeight: Integer; ClearBuffer: Boolean);
  4928. begin
  4929. try
  4930. Changing;
  4931. FinalizeSurface;
  4932. Width := 0;
  4933. Height := 0;
  4934. if (NewWidth > 0) and (NewHeight > 0) then
  4935. InitializeSurface(NewWidth, NewHeight, ClearBuffer);
  4936. Width := NewWidth;
  4937. Height := NewHeight;
  4938. finally
  4939. Changed;
  4940. end;
  4941. end;
  4942. procedure TCustomBackend.Assign(Source: TPersistent);
  4943. var
  4944. SrcBackend: TCustomBackend;
  4945. begin
  4946. if Source is TCustomBackend then
  4947. begin
  4948. if Assigned(FOwner) then
  4949. begin
  4950. SrcBackend := TCustomBackend(Source);
  4951. ChangeSize(
  4952. FOwner.FWidth, FOwner.FHeight,
  4953. SrcBackend.FOwner.Width, SrcBackend.FOwner.Height,
  4954. False
  4955. );
  4956. if not SrcBackend.Empty then
  4957. MoveLongword(
  4958. SrcBackend.Bits[0], Bits[0],
  4959. SrcBackend.FOwner.Width * SrcBackend.FOwner.Height
  4960. );
  4961. end;
  4962. end
  4963. else
  4964. inherited;
  4965. end;
  4966. function TCustomBackend.Empty: Boolean;
  4967. begin
  4968. Result := False;
  4969. end;
  4970. procedure TCustomBackend.FinalizeSurface;
  4971. begin
  4972. // descendants override this method
  4973. end;
  4974. procedure TCustomBackend.InitializeSurface(NewWidth, NewHeight: Integer; ClearBuffer: Boolean);
  4975. begin
  4976. // descendants override this method
  4977. end;
  4978. { TCustomSampler }
  4979. function TCustomSampler.GetSampleInt(X, Y: Integer): TColor32;
  4980. begin
  4981. Result := GetSampleFixed(X * FixedOne, Y * FixedOne);
  4982. end;
  4983. function TCustomSampler.GetSampleFixed(X, Y: TFixed): TColor32;
  4984. begin
  4985. Result := GetSampleFloat(X * FixedToFloat, Y * FixedToFloat);
  4986. end;
  4987. function TCustomSampler.GetSampleFloat(X, Y: TFloat): TColor32;
  4988. begin
  4989. Result := GetSampleFixed(Fixed(X), Fixed(Y));
  4990. end;
  4991. procedure TCustomSampler.PrepareSampling;
  4992. begin
  4993. // descendants override this method
  4994. end;
  4995. procedure TCustomSampler.FinalizeSampling;
  4996. begin
  4997. // descendants override this method
  4998. end;
  4999. function TCustomSampler.HasBounds: Boolean;
  5000. begin
  5001. Result := False;
  5002. end;
  5003. function TCustomSampler.GetSampleBounds: TFloatRect;
  5004. const
  5005. InfRect: TFloatRect = (Left: -Infinity; Top: -Infinity; Right: Infinity; Bottom: Infinity);
  5006. begin
  5007. Result := InfRect;
  5008. end;
  5009. { TCustomResampler }
  5010. procedure TCustomResampler.AssignTo(Dst: TPersistent);
  5011. begin
  5012. if Dst is TCustomResampler then
  5013. SmartAssign(Self, Dst)
  5014. else
  5015. inherited;
  5016. end;
  5017. procedure TCustomResampler.Changed;
  5018. begin
  5019. if Assigned(FBitmap) then FBitmap.Changed;
  5020. end;
  5021. constructor TCustomResampler.Create;
  5022. begin
  5023. inherited;
  5024. FPixelAccessMode := pamSafe;
  5025. end;
  5026. constructor TCustomResampler.Create(ABitmap: TCustomBitmap32);
  5027. begin
  5028. Create;
  5029. FBitmap := ABitmap;
  5030. if Assigned(ABitmap) then ABitmap.Resampler := Self;
  5031. end;
  5032. function TCustomResampler.GetSampleBounds: TFloatRect;
  5033. begin
  5034. Result := FloatRect(FBitmap.ClipRect);
  5035. if PixelAccessMode = pamTransparentEdge then
  5036. InflateRect(Result, 1, 1);
  5037. end;
  5038. function TCustomResampler.GetWidth: TFloat;
  5039. begin
  5040. Result := 0;
  5041. end;
  5042. function TCustomResampler.HasBounds: Boolean;
  5043. begin
  5044. Result := FPixelAccessMode <> pamWrap;
  5045. end;
  5046. procedure TCustomResampler.PrepareSampling;
  5047. begin
  5048. FClipRect := FBitmap.ClipRect;
  5049. end;
  5050. procedure TCustomResampler.SetPixelAccessMode(
  5051. const Value: TPixelAccessMode);
  5052. begin
  5053. if FPixelAccessMode <> Value then
  5054. begin
  5055. FPixelAccessMode := Value;
  5056. Changed;
  5057. end;
  5058. end;
  5059. initialization
  5060. SetGamma;
  5061. StockBitmap := TBitmap.Create;
  5062. StockBitmap.Width := 8;
  5063. StockBitmap.Height := 8;
  5064. finalization
  5065. StockBitmap.Free;
  5066. end.