12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743 |
- /*
- SDL_gfxPrimitives.c: graphics primitives for SDL surfaces
- Copyright (C) 2001-2012 Andreas Schiffler
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source
- distribution.
- Andreas Schiffler -- aschiffler at ferzkopp dot net
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <string.h>
- #include "SDL_gfxPrimitives.h"
- #include "SDL_rotozoom.h"
- #include "SDL_gfxPrimitives_font.h"
- #include "SDL_gfxBlitFunc.h"
- /* -===================- */
- #define DEFAULT_ALPHA_PIXEL_ROUTINE
- #undef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE
- #define ALPHA_PIXEL_ADDITIVE_BLEND
- /* ---- Structures */
- /*!
- \brief The structure passed to the internal Bresenham iterator.
- */
- typedef struct {
- Sint16 x, y;
- int dx, dy, s1, s2, swapdir, error;
- Uint32 count;
- } SDL_gfxBresenhamIterator;
- /*!
- \brief The structure passed to the internal Murphy iterator.
- */
- typedef struct {
- Uint32 color;
- SDL_Surface *dst;
- int u, v; /* delta x , delta y */
- int ku, kt, kv, kd; /* loop constants */
- int oct2;
- int quad4;
- Sint16 last1x, last1y, last2x, last2y, first1x, first1y, first2x, first2y, tempx, tempy;
- } SDL_gfxMurphyIterator;
- /* ----- Defines for pixel clipping tests */
- #define clip_xmin(surface) surface->clip_rect.x
- #define clip_xmax(surface) surface->clip_rect.x+surface->clip_rect.w-1
- #define clip_ymin(surface) surface->clip_rect.y
- #define clip_ymax(surface) surface->clip_rect.y+surface->clip_rect.h-1
- /*!
- \brief Internal pixel drawing - fast, no blending, no locking, clipping.
- \param dst The surface to draw on.
- \param x The horizontal coordinate of the pixel.
- \param y The vertical position of the pixel.
- \param color The color value of the pixel to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int fastPixelColorNolock(SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color) {
- int bpp;
- Uint8 *p;
- /*
- * Honor clipping setup at pixel level
- */
- if ((x >= clip_xmin(dst)) && (x <= clip_xmax(dst)) && (y >= clip_ymin(dst)) && (y <= clip_ymax(dst))) {
- /*
- * Get destination format
- */
- bpp = dst->format->BytesPerPixel;
- p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
- switch (bpp) {
- case 1:
- *p = color;
- break;
- case 2:
- *(Uint16 *) p = color;
- break;
- case 3:
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
- p[0] = (color >> 16) & 0xff;
- p[1] = (color >> 8) & 0xff;
- p[2] = color & 0xff;
- } else {
- p[0] = color & 0xff;
- p[1] = (color >> 8) & 0xff;
- p[2] = (color >> 16) & 0xff;
- }
- break;
- case 4:
- *(Uint32 *) p = color;
- break;
- } /* switch */
- }
- return (0);
- }
- /*!
- \brief Internal pixel drawing - fast, no blending, no locking, no clipping.
- Function is faster but dangerous since no clipping check is done.
- Code needs to make sure we stay in surface bounds before calling.
- \param dst The surface to draw on.
- \param x The horizontal coordinate of the pixel.
- \param y The vertical position of the pixel.
- \param color The color value of the pixel to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int fastPixelColorNolockNoclip(SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color) {
- int bpp;
- Uint8 *p;
- /*
- * Get destination format
- */
- bpp = dst->format->BytesPerPixel;
- p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
- switch (bpp) {
- case 1:
- *p = color;
- break;
- case 2:
- *(Uint16 *) p = color;
- break;
- case 3:
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
- p[0] = (color >> 16) & 0xff;
- p[1] = (color >> 8) & 0xff;
- p[2] = color & 0xff;
- } else {
- p[0] = color & 0xff;
- p[1] = (color >> 8) & 0xff;
- p[2] = (color >> 16) & 0xff;
- }
- break;
- case 4:
- *(Uint32 *) p = color;
- break;
- } /* switch */
- return (0);
- }
- /*!
- \brief Internal pixel drawing - fast, no blending, locking, clipping.
- \param dst The surface to draw on.
- \param x The horizontal coordinate of the pixel.
- \param y The vertical position of the pixel.
- \param color The color value of the pixel to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int fastPixelColor(SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color) {
- int result;
- /*
- * Lock the surface
- */
- if (SDL_MUSTLOCK(dst)) {
- if (SDL_LockSurface(dst) < 0) {
- return (-1);
- }
- }
- result = fastPixelColorNolock(dst, x, y, color);
- /*
- * Unlock surface
- */
- if (SDL_MUSTLOCK(dst)) {
- SDL_UnlockSurface(dst);
- }
- return (result);
- }
- /*!
- \brief Internal pixel drawing - fast, no blending, locking, RGB input.
- \param dst The surface to draw on.
- \param x The horizontal coordinate of the pixel.
- \param y The vertical position of the pixel.
- \param r The red value of the pixel to draw.
- \param g The green value of the pixel to draw.
- \param b The blue value of the pixel to draw.
- \param a The alpha value of the pixel to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int fastPixelRGBA(SDL_Surface *dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- Uint32 color;
- /*
- * Setup color
- */
- color = SDL_MapRGBA(dst->format, r, g, b, a);
- /*
- * Draw
- */
- return (fastPixelColor(dst, x, y, color));
- }
- /*!
- \brief Internal pixel drawing - fast, no blending, no locking RGB input.
- \param dst The surface to draw on.
- \param x The horizontal coordinate of the pixel.
- \param y The vertical position of the pixel.
- \param r The red value of the pixel to draw.
- \param g The green value of the pixel to draw.
- \param b The blue value of the pixel to draw.
- \param a The alpha value of the pixel to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int fastPixelRGBANolock(SDL_Surface *dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- Uint32 color;
- /*
- * Setup color
- */
- color = SDL_MapRGBA(dst->format, r, g, b, a);
- /*
- * Draw
- */
- return (fastPixelColorNolock(dst, x, y, color));
- }
- /*!
- \brief Internal pixel drawing function with alpha blending where input color in in destination format.
- Contains two alternative 32 bit alpha blending routines which can be enabled at the source
- level with the defines DEFAULT_ALPHA_PIXEL_ROUTINE or EXPERIMENTAL_ALPHA_PIXEL_ROUTINE.
- Only the bits up to the surface depth are significant in the color value.
- \param dst The surface to draw on.
- \param x The horizontal coordinate of the pixel.
- \param y The vertical position of the pixel.
- \param color The color value of the pixel to draw.
- \param alpha The blend factor to apply while drawing.
- \returns Returns 0 on success, -1 on failure.
- */
- int _putPixelAlpha(SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha) {
- SDL_PixelFormat *format;
- Uint32 Rmask, Gmask, Bmask, Amask;
- Uint32 Rshift, Gshift, Bshift, Ashift;
- Uint32 sR, sG, sB;
- Uint32 dR, dG, dB, dA;
- if (dst == NULL) {
- return (-1);
- }
- if (x >= clip_xmin(dst) && x <= clip_xmax(dst) &&
- y >= clip_ymin(dst) && y <= clip_ymax(dst)) {
- format = dst->format;
- switch (format->BytesPerPixel) {
- case 1: { /* Assuming 8-bpp */
- Uint8 *pixel = (Uint8 *) dst->pixels + y * dst->pitch + x;
- if (alpha == 255) {
- *pixel = color;
- } else {
- Uint8 R, G, B;
- SDL_Palette *palette = format->palette;
- SDL_Color *colors = palette->colors;
- SDL_Color dColor = colors[*pixel];
- SDL_Color sColor = colors[color];
- dR = dColor.r;
- dG = dColor.g;
- dB = dColor.b;
- sR = sColor.r;
- sG = sColor.g;
- sB = sColor.b;
- R = dR + ((sR - dR) * alpha >> 8);
- G = dG + ((sG - dG) * alpha >> 8);
- B = dB + ((sB - dB) * alpha >> 8);
- *pixel = SDL_MapRGB(format, R, G, B);
- }
- }
- break;
- case 2: { /* Probably 15-bpp or 16-bpp */
- Uint16 *pixel = (Uint16 *) dst->pixels + y * dst->pitch / 2 + x;
- if (alpha == 255) {
- *pixel = color;
- } else {
- Uint16 R, G, B, A;
- Uint16 dc = *pixel;
- Rmask = format->Rmask;
- Gmask = format->Gmask;
- Bmask = format->Bmask;
- Amask = format->Amask;
- dR = (dc & Rmask);
- dG = (dc & Gmask);
- dB = (dc & Bmask);
- R = (dR + (((color & Rmask) - dR) * alpha >> 8)) & Rmask;
- G = (dG + (((color & Gmask) - dG) * alpha >> 8)) & Gmask;
- B = (dB + (((color & Bmask) - dB) * alpha >> 8)) & Bmask;
- *pixel = R | G | B;
- if (Amask != 0) {
- dA = (dc & Amask);
- A = (dA + (((color & Amask) - dA) * alpha >> 8)) & Amask;
- *pixel |= A;
- }
- }
- }
- break;
- case 3: { /* Slow 24-bpp mode, usually not used */
- Uint8 R, G, B;
- Uint8 Rshift8, Gshift8, Bshift8;
- Uint8 *pixel = (Uint8 *) dst->pixels + y * dst->pitch + x * 3;
- Rshift = format->Rshift;
- Gshift = format->Gshift;
- Bshift = format->Bshift;
- Rshift8 = Rshift >> 3;
- Gshift8 = Gshift >> 3;
- Bshift8 = Bshift >> 3;
- sR = (color >> Rshift) & 0xFF;
- sG = (color >> Gshift) & 0xFF;
- sB = (color >> Bshift) & 0xFF;
- if (alpha == 255) {
- *(pixel + Rshift8) = sR;
- *(pixel + Gshift8) = sG;
- *(pixel + Bshift8) = sB;
- } else {
- dR = *((pixel) + Rshift8);
- dG = *((pixel) + Gshift8);
- dB = *((pixel) + Bshift8);
- R = dR + ((sR - dR) * alpha >> 8);
- G = dG + ((sG - dG) * alpha >> 8);
- B = dB + ((sB - dB) * alpha >> 8);
- *((pixel) + Rshift8) = R;
- *((pixel) + Gshift8) = G;
- *((pixel) + Bshift8) = B;
- }
- }
- break;
- #ifdef DEFAULT_ALPHA_PIXEL_ROUTINE
- case 4: { /* Probably :-) 32-bpp */
- Uint32 R, G, B, A;
- Uint32 *pixel = (Uint32 *) dst->pixels + y * dst->pitch / 4 + x;
- if (alpha == 255) {
- *pixel = color;
- } else {
- Uint32 dc = *pixel;
- Rmask = format->Rmask;
- Gmask = format->Gmask;
- Bmask = format->Bmask;
- Amask = format->Amask;
- Rshift = format->Rshift;
- Gshift = format->Gshift;
- Bshift = format->Bshift;
- Ashift = format->Ashift;
- dR = (dc & Rmask) >> Rshift;
- dG = (dc & Gmask) >> Gshift;
- dB = (dc & Bmask) >> Bshift;
- R = ((dR + ((((color & Rmask) >> Rshift) - dR) * alpha >> 8)) << Rshift) & Rmask;
- G = ((dG + ((((color & Gmask) >> Gshift) - dG) * alpha >> 8)) << Gshift) & Gmask;
- B = ((dB + ((((color & Bmask) >> Bshift) - dB) * alpha >> 8)) << Bshift) & Bmask;
- *pixel = R | G | B;
- if (Amask != 0) {
- dA = (dc & Amask) >> Ashift;
- #ifdef ALPHA_PIXEL_ADDITIVE_BLEND
- A = (dA | GFX_ALPHA_ADJUST_ARRAY[alpha & 255])
- << Ashift; // make destination less transparent...
- #else
- A = ((dA + ((((color & Amask) >> Ashift) - dA) * alpha >> 8)) << Ashift) & Amask;
- #endif
- *pixel |= A;
- }
- }
- }
- break;
- #endif
- #ifdef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE
- case 4:{ /* Probably :-) 32-bpp */
- if (alpha == 255) {
- *((Uint32 *) dst->pixels + y * dst->pitch / 4 + x) = color;
- } else {
- Uint32 *pixel = (Uint32 *) dst->pixels + y * dst->pitch / 4 + x;
- Uint32 dR, dG, dB, dA;
- Uint32 dc = *pixel;
- Uint32 surfaceAlpha, preMultR, preMultG, preMultB;
- Uint32 aTmp;
- Rmask = format->Rmask;
- Gmask = format->Gmask;
- Bmask = format->Bmask;
- Amask = format->Amask;
- dR = (color & Rmask);
- dG = (color & Gmask);
- dB = (color & Bmask);
- dA = (color & Amask);
- Rshift = format->Rshift;
- Gshift = format->Gshift;
- Bshift = format->Bshift;
- Ashift = format->Ashift;
- preMultR = (alpha * (dR >> Rshift));
- preMultG = (alpha * (dG >> Gshift));
- preMultB = (alpha * (dB >> Bshift));
- surfaceAlpha = ((dc & Amask) >> Ashift);
- aTmp = (255 - alpha);
- if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) {
- aTmp *= surfaceAlpha;
- R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask;
- G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask;
- B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask;
- }
- *pixel = R | G | B | (A << Ashift & Amask);
- }
- }
- break;
- #endif
- }
- }
- return (0);
- }
- /*!
- \brief Pixel draw with blending enabled if a<255.
- \param dst The surface to draw on.
- \param x X (horizontal) coordinate of the pixel.
- \param y Y (vertical) coordinate of the pixel.
- \param color The color value of the pixel to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int pixelColor(SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color) {
- Uint8 alpha;
- Uint32 mcolor;
- int result = 0;
- /*
- * Lock the surface
- */
- if (SDL_MUSTLOCK(dst)) {
- if (SDL_LockSurface(dst) < 0) {
- return (-1);
- }
- }
- /*
- * Setup color
- */
- alpha = color & 0x000000ff;
- mcolor =
- SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
- (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
- /*
- * Draw
- */
- result = _putPixelAlpha(dst, x, y, mcolor, alpha);
- /*
- * Unlock the surface
- */
- if (SDL_MUSTLOCK(dst)) {
- SDL_UnlockSurface(dst);
- }
- return (result);
- }
- /*!
- \brief Pixel draw with blending enabled if a<255 - no surface locking.
- \param dst The surface to draw on.
- \param x X (horizontal) coordinate of the pixel.
- \param y Y (vertical) coordinate of the pixel.
- \param color The color value of the pixel to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int pixelColorNolock(SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color) {
- Uint8 alpha;
- Uint32 mcolor;
- int result = 0;
- /*
- * Setup color
- */
- alpha = color & 0x000000ff;
- mcolor =
- SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
- (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
- /*
- * Draw
- */
- result = _putPixelAlpha(dst, x, y, mcolor, alpha);
- return (result);
- }
- /*!
- \brief Internal function to draw filled rectangle with alpha blending.
- Assumes color is in destination format.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first corner (upper left) of the rectangle.
- \param y1 Y coordinate of the first corner (upper left) of the rectangle.
- \param x2 X coordinate of the second corner (lower right) of the rectangle.
- \param y2 Y coordinate of the second corner (lower right) of the rectangle.
- \param color The color value of the rectangle to draw (0xRRGGBBAA).
- \param alpha Alpha blending amount for pixels.
- \returns Returns 0 on success, -1 on failure.
- */
- int _filledRectAlpha(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha) {
- SDL_PixelFormat *format;
- Uint32 Rmask, Gmask, Bmask, Amask;
- Uint32 Rshift, Gshift, Bshift, Ashift;
- Uint32 sR, sG, sB, sA;
- Uint32 dR, dG, dB, dA;
- Sint16 x, y;
- if (dst == NULL) {
- return (-1);
- }
- format = dst->format;
- switch (format->BytesPerPixel) {
- case 1: { /* Assuming 8-bpp */
- Uint8 *row, *pixel;
- Uint8 R, G, B;
- SDL_Color *colors = format->palette->colors;
- SDL_Color dColor;
- SDL_Color sColor = colors[color];
- sR = sColor.r;
- sG = sColor.g;
- sB = sColor.b;
- for (y = y1; y <= y2; y++) {
- row = (Uint8 *) dst->pixels + y * dst->pitch;
- for (x = x1; x <= x2; x++) {
- if (alpha == 255) {
- *(row + x) = color;
- } else {
- pixel = row + x;
- dColor = colors[*pixel];
- dR = dColor.r;
- dG = dColor.g;
- dB = dColor.b;
- R = dR + ((sR - dR) * alpha >> 8);
- G = dG + ((sG - dG) * alpha >> 8);
- B = dB + ((sB - dB) * alpha >> 8);
- *pixel = SDL_MapRGB(format, R, G, B);
- }
- }
- }
- }
- break;
- case 2: { /* Probably 15-bpp or 16-bpp */
- Uint16 *row, *pixel;
- Uint16 R, G, B, A;
- Uint16 dc;
- Rmask = format->Rmask;
- Gmask = format->Gmask;
- Bmask = format->Bmask;
- Amask = format->Amask;
- sR = (color & Rmask);
- sG = (color & Gmask);
- sB = (color & Bmask);
- sA = (color & Amask);
- for (y = y1; y <= y2; y++) {
- row = (Uint16 *) dst->pixels + y * dst->pitch / 2;
- for (x = x1; x <= x2; x++) {
- if (alpha == 255) {
- *(row + x) = color;
- } else {
- pixel = row + x;
- dc = *pixel;
- dR = (dc & Rmask);
- dG = (dc & Gmask);
- dB = (dc & Bmask);
- R = (dR + ((sR - dR) * alpha >> 8)) & Rmask;
- G = (dG + ((sG - dG) * alpha >> 8)) & Gmask;
- B = (dB + ((sB - dB) * alpha >> 8)) & Bmask;
- *pixel = R | G | B;
- if (Amask != 0) {
- dA = (dc & Amask);
- A = (dA + ((sA - dA) * alpha >> 8)) & Amask;
- *pixel |= A;
- }
- }
- }
- }
- }
- break;
- case 3: { /* Slow 24-bpp mode, usually not used */
- Uint8 *row, *pixel;
- Uint8 R, G, B;
- Uint8 Rshift8, Gshift8, Bshift8;
- Rshift = format->Rshift;
- Gshift = format->Gshift;
- Bshift = format->Bshift;
- Rshift8 = Rshift >> 3;
- Gshift8 = Gshift >> 3;
- Bshift8 = Bshift >> 3;
- sR = (color >> Rshift) & 0xff;
- sG = (color >> Gshift) & 0xff;
- sB = (color >> Bshift) & 0xff;
- for (y = y1; y <= y2; y++) {
- row = (Uint8 *) dst->pixels + y * dst->pitch;
- for (x = x1; x <= x2; x++) {
- pixel = row + x * 3;
- if (alpha == 255) {
- *(pixel + Rshift8) = sR;
- *(pixel + Gshift8) = sG;
- *(pixel + Bshift8) = sB;
- } else {
- dR = *((pixel) + Rshift8);
- dG = *((pixel) + Gshift8);
- dB = *((pixel) + Bshift8);
- R = dR + ((sR - dR) * alpha >> 8);
- G = dG + ((sG - dG) * alpha >> 8);
- B = dB + ((sB - dB) * alpha >> 8);
- *((pixel) + Rshift8) = R;
- *((pixel) + Gshift8) = G;
- *((pixel) + Bshift8) = B;
- }
- }
- }
- }
- break;
- #ifdef DEFAULT_ALPHA_PIXEL_ROUTINE
- case 4: { /* Probably :-) 32-bpp */
- Uint32 *row, *pixel;
- Uint32 R, G, B, A;
- Uint32 dc;
- Rmask = format->Rmask;
- Gmask = format->Gmask;
- Bmask = format->Bmask;
- Amask = format->Amask;
- Rshift = format->Rshift;
- Gshift = format->Gshift;
- Bshift = format->Bshift;
- Ashift = format->Ashift;
- sR = (color & Rmask) >> Rshift;
- sG = (color & Gmask) >> Gshift;
- sB = (color & Bmask) >> Bshift;
- sA = (color & Amask) >> Ashift;
- for (y = y1; y <= y2; y++) {
- row = (Uint32 *) dst->pixels + y * dst->pitch / 4;
- for (x = x1; x <= x2; x++) {
- if (alpha == 255) {
- *(row + x) = color;
- } else {
- pixel = row + x;
- dc = *pixel;
- dR = (dc & Rmask) >> Rshift;
- dG = (dc & Gmask) >> Gshift;
- dB = (dc & Bmask) >> Bshift;
- R = ((dR + ((sR - dR) * alpha >> 8)) << Rshift) & Rmask;
- G = ((dG + ((sG - dG) * alpha >> 8)) << Gshift) & Gmask;
- B = ((dB + ((sB - dB) * alpha >> 8)) << Bshift) & Bmask;
- *pixel = R | G | B;
- if (Amask != 0) {
- dA = (dc & Amask) >> Ashift;
- #ifdef ALPHA_PIXEL_ADDITIVE_BLEND
- A = (dA | GFX_ALPHA_ADJUST_ARRAY[sA & 255])
- << Ashift; // make destination less transparent...
- #else
- A = ((dA + ((sA - dA) * alpha >> 8)) << Ashift) & Amask;
- #endif
- *pixel |= A;
- }
- }
- }
- }
- }
- break;
- #endif
- #ifdef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE
- case 4:{ /* Probably :-) 32-bpp */
- Uint32 *row, *pixel;
- Uint32 dR, dG, dB, dA;
- Uint32 dc;
- Uint32 surfaceAlpha, preMultR, preMultG, preMultB;
- Uint32 aTmp;
- Rmask = format->Rmask;
- Gmask = format->Gmask;
- Bmask = format->Bmask;
- Amask = format->Amask;
- dR = (color & Rmask);
- dG = (color & Gmask);
- dB = (color & Bmask);
- dA = (color & Amask);
- Rshift = format->Rshift;
- Gshift = format->Gshift;
- Bshift = format->Bshift;
- Ashift = format->Ashift;
- preMultR = (alpha * (dR >> Rshift));
- preMultG = (alpha * (dG >> Gshift));
- preMultB = (alpha * (dB >> Bshift));
- for (y = y1; y <= y2; y++) {
- row = (Uint32 *) dst->pixels + y * dst->pitch / 4;
- for (x = x1; x <= x2; x++) {
- if (alpha == 255) {
- *(row + x) = color;
- } else {
- pixel = row + x;
- dc = *pixel;
- surfaceAlpha = ((dc & Amask) >> Ashift);
- aTmp = (255 - alpha);
- if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) {
- aTmp *= surfaceAlpha;
- R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask;
- G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask;
- B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask;
- }
- *pixel = R | G | B | (A << Ashift & Amask);
- }
- }
- }
- }
- break;
- #endif
- }
- return (0);
- }
- /*!
- \brief Draw filled rectangle of RGBA color with alpha blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first corner (upper left) of the rectangle.
- \param y1 Y coordinate of the first corner (upper left) of the rectangle.
- \param x2 X coordinate of the second corner (lower right) of the rectangle.
- \param y2 Y coordinate of the second corner (lower right) of the rectangle.
- \param color The color value of the rectangle to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int filledRectAlpha(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color) {
- Uint8 alpha;
- Uint32 mcolor;
- int result = 0;
- /*
- * Lock the surface
- */
- if (SDL_MUSTLOCK(dst)) {
- if (SDL_LockSurface(dst) < 0) {
- return (-1);
- }
- }
- /*
- * Setup color
- */
- alpha = color & 0x000000ff;
- mcolor =
- SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
- (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
- /*
- * Draw
- */
- result = _filledRectAlpha(dst, x1, y1, x2, y2, mcolor, alpha);
- /*
- * Unlock the surface
- */
- if (SDL_MUSTLOCK(dst)) {
- SDL_UnlockSurface(dst);
- }
- return (result);
- }
- /*!
- \brief Internal function to draw horizontal line of RGBA color with alpha blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point (i.e. left) of the line.
- \param x2 X coordinate of the second point (i.e. right) of the line.
- \param y Y coordinate of the points of the line.
- \param color The color value of the line to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int _HLineAlpha(SDL_Surface *dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color) {
- return (filledRectAlpha(dst, x1, y, x2, y, color));
- }
- /*!
- \brief Internal function to draw vertical line of RGBA color with alpha blending.
- \param dst The surface to draw on.
- \param x X coordinate of the points of the line.
- \param y1 Y coordinate of the first point (top) of the line.
- \param y2 Y coordinate of the second point (bottom) of the line.
- \param color The color value of the line to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int _VLineAlpha(SDL_Surface *dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color) {
- return (filledRectAlpha(dst, x, y1, x, y2, color));
- }
- /*!
- \brief Pixel draw with blending enabled and using alpha weight on color.
- \param dst The surface to draw on.
- \param x The horizontal coordinate of the pixel.
- \param y The vertical position of the pixel.
- \param color The color value of the pixel to draw (0xRRGGBBAA).
- \param weight The weight multiplied into the alpha value of the pixel.
- \returns Returns 0 on success, -1 on failure.
- */
- int pixelColorWeight(SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight) {
- Uint32 a;
- /*
- * Get alpha
- */
- a = (color & (Uint32) 0x000000ff);
- /*
- * Modify Alpha by weight
- */
- a = ((a * weight) >> 8);
- return (pixelColor(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a));
- }
- /*!
- \brief Pixel draw with blending enabled and using alpha weight on color - no locking.
- \param dst The surface to draw on.
- \param x The horizontal coordinate of the pixel.
- \param y The vertical position of the pixel.
- \param color The color value of the pixel to draw (0xRRGGBBAA).
- \param weight The weight multiplied into the alpha value of the pixel.
- \returns Returns 0 on success, -1 on failure.
- */
- int pixelColorWeightNolock(SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight) {
- Uint32 a;
- /*
- * Get alpha
- */
- a = (color & (Uint32) 0x000000ff);
- /*
- * Modify Alpha by weight
- */
- a = ((a * weight) >> 8);
- return (pixelColorNolock(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a));
- }
- /*!
- \brief Pixel draw with blending enabled if a<255.
- \param dst The surface to draw on.
- \param x X (horizontal) coordinate of the pixel.
- \param y Y (vertical) coordinate of the pixel.
- \param r The red color value of the pixel to draw.
- \param g The green color value of the pixel to draw.
- \param b The blue color value of the pixel to draw.
- \param a The alpha value of the pixel to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int pixelRGBA(SDL_Surface *dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- Uint32 color;
- /*
- * Check Alpha
- */
- if (a == 255) {
- /*
- * No alpha blending required
- */
- /*
- * Setup color
- */
- color = SDL_MapRGBA(dst->format, r, g, b, a);
- /*
- * Draw
- */
- return (fastPixelColor(dst, x, y, color));
- } else {
- /*
- * Alpha blending required
- */
- /*
- * Draw
- */
- return (pixelColor(dst, x, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- }
- /*!
- \brief Draw horizontal line without blending;
- Just stores the color value (including the alpha component) without blending.
- Only the same number of bits of the destination surface are transfered
- from the input color value.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point (i.e. left) of the line.
- \param x2 X coordinate of the second point (i.e. right) of the line.
- \param y Y coordinate of the points of the line.
- \param color The color value of the line to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int hlineColorStore(SDL_Surface *dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color) {
- Sint16 left, right, top, bottom;
- Uint8 *pixel, *pixellast;
- int dx;
- int pixx, pixy;
- Sint16 w;
- Sint16 xtmp;
- int result = -1;
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return (0);
- }
- /*
- * Swap x1, x2 if required to ensure x1<=x2
- */
- if (x1 > x2) {
- xtmp = x1;
- x1 = x2;
- x2 = xtmp;
- }
- /*
- * Get clipping boundary and
- * check visibility of hline
- */
- left = dst->clip_rect.x;
- if (x2 < left) {
- return (0);
- }
- right = dst->clip_rect.x + dst->clip_rect.w - 1;
- if (x1 > right) {
- return (0);
- }
- top = dst->clip_rect.y;
- bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
- if ((y < top) || (y > bottom)) {
- return (0);
- }
- /*
- * Clip x
- */
- if (x1 < left) {
- x1 = left;
- }
- if (x2 > right) {
- x2 = right;
- }
- /*
- * Calculate width
- */
- w = x2 - x1;
- /*
- * Lock the surface
- */
- if (SDL_MUSTLOCK(dst)) {
- if (SDL_LockSurface(dst) < 0) {
- return (-1);
- }
- }
- /*
- * More variable setup
- */
- dx = w;
- pixx = dst->format->BytesPerPixel;
- pixy = dst->pitch;
- pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y;
- /*
- * Draw
- */
- switch (dst->format->BytesPerPixel) {
- case 1:
- memset(pixel, color, dx + 1);
- break;
- case 2:
- pixellast = pixel + dx + dx;
- for (; pixel <= pixellast; pixel += pixx) {
- *(Uint16 *) pixel = color;
- }
- break;
- case 3:
- pixellast = pixel + dx + dx + dx;
- for (; pixel <= pixellast; pixel += pixx) {
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
- pixel[0] = (color >> 16) & 0xff;
- pixel[1] = (color >> 8) & 0xff;
- pixel[2] = color & 0xff;
- } else {
- pixel[0] = color & 0xff;
- pixel[1] = (color >> 8) & 0xff;
- pixel[2] = (color >> 16) & 0xff;
- }
- }
- break;
- default: /* case 4 */
- dx = dx + dx;
- pixellast = pixel + dx + dx;
- for (; pixel <= pixellast; pixel += pixx) {
- *(Uint32 *) pixel = color;
- }
- break;
- }
- /*
- * Unlock surface
- */
- if (SDL_MUSTLOCK(dst)) {
- SDL_UnlockSurface(dst);
- }
- /*
- * Set result code
- */
- result = 0;
- return (result);
- }
- /*!
- \brief Draw horizontal line without blending
- Just stores the color value (including the alpha component) without blending.
- Function should only be used for 32 bit target surfaces.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point (i.e. left) of the line.
- \param x2 X coordinate of the second point (i.e. right) of the line.
- \param y Y coordinate of the points of the line.
- \param r The red value of the line to draw.
- \param g The green value of the line to draw.
- \param b The blue value of the line to draw.
- \param a The alpha value of the line to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int hlineRGBAStore(SDL_Surface *dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (hlineColorStore(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /*!
- \brief Draw horizontal line with blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point (i.e. left) of the line.
- \param x2 X coordinate of the second point (i.e. right) of the line.
- \param y Y coordinate of the points of the line.
- \param color The color value of the line to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int hlineColor(SDL_Surface *dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color) {
- Sint16 left, right, top, bottom;
- Uint8 *pixel, *pixellast;
- int dx;
- int pixx, pixy;
- Sint16 xtmp;
- int result = -1;
- Uint8 *colorptr;
- Uint8 color3[3];
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return (0);
- }
- /*
- * Swap x1, x2 if required to ensure x1<=x2
- */
- if (x1 > x2) {
- xtmp = x1;
- x1 = x2;
- x2 = xtmp;
- }
- /*
- * Get clipping boundary and
- * check visibility of hline
- */
- left = dst->clip_rect.x;
- if (x2 < left) {
- return (0);
- }
- right = dst->clip_rect.x + dst->clip_rect.w - 1;
- if (x1 > right) {
- return (0);
- }
- top = dst->clip_rect.y;
- bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
- if ((y < top) || (y > bottom)) {
- return (0);
- }
- /*
- * Clip x
- */
- if (x1 < left) {
- x1 = left;
- }
- if (x2 > right) {
- x2 = right;
- }
- /*
- * Calculate width difference
- */
- dx = x2 - x1;
- /*
- * Alpha check
- */
- if ((color & 255) == 255) {
- /*
- * No alpha-blending required
- */
- /*
- * Setup color
- */
- colorptr = (Uint8 *) &color;
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
- color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
- } else {
- color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
- }
- /*
- * Lock the surface
- */
- if (SDL_MUSTLOCK(dst)) {
- if (SDL_LockSurface(dst) < 0) {
- return (-1);
- }
- }
- /*
- * More variable setup
- */
- pixx = dst->format->BytesPerPixel;
- pixy = dst->pitch;
- pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y;
- /*
- * Draw
- */
- switch (dst->format->BytesPerPixel) {
- case 1:
- memset(pixel, color, dx + 1);
- break;
- case 2:
- pixellast = pixel + dx + dx;
- for (; pixel <= pixellast; pixel += pixx) {
- *(Uint16 *) pixel = color;
- }
- break;
- case 3:
- pixellast = pixel + dx + dx + dx;
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
- color3[0] = (color >> 16) & 0xff;
- color3[1] = (color >> 8) & 0xff;
- color3[2] = color & 0xff;
- } else {
- color3[0] = color & 0xff;
- color3[1] = (color >> 8) & 0xff;
- color3[2] = (color >> 16) & 0xff;
- }
- for (; pixel <= pixellast; pixel += pixx) {
- memcpy(pixel, color3, 3);
- }
- break;
- default: /* case 4 */
- dx = dx + dx;
- pixellast = pixel + dx + dx;
- for (; pixel <= pixellast; pixel += pixx) {
- *(Uint32 *) pixel = color;
- }
- break;
- }
- /*
- * Unlock surface
- */
- if (SDL_MUSTLOCK(dst)) {
- SDL_UnlockSurface(dst);
- }
- /*
- * Set result code
- */
- result = 0;
- } else {
- /*
- * Alpha blending blit
- */
- result = _HLineAlpha(dst, x1, x1 + dx, y, color);
- }
- return (result);
- }
- /*!
- \brief Draw horizontal line with blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point (i.e. left) of the line.
- \param x2 X coordinate of the second point (i.e. right) of the line.
- \param y Y coordinate of the points of the line.
- \param r The red value of the line to draw.
- \param g The green value of the line to draw.
- \param b The blue value of the line to draw.
- \param a The alpha value of the line to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int hlineRGBA(SDL_Surface *dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (hlineColor(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /*!
- \brief Draw vertical line with blending.
- \param dst The surface to draw on.
- \param x X coordinate of the points of the line.
- \param y1 Y coordinate of the first point (i.e. top) of the line.
- \param y2 Y coordinate of the second point (i.e. bottom) of the line.
- \param color The color value of the line to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int vlineColor(SDL_Surface *dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color) {
- Sint16 left, right, top, bottom;
- Uint8 *pixel, *pixellast;
- int dy;
- int pixx, pixy;
- Sint16 h;
- Sint16 ytmp;
- int result = -1;
- Uint8 *colorptr;
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return (0);
- }
- /*
- * Swap y1, y2 if required to ensure y1<=y2
- */
- if (y1 > y2) {
- ytmp = y1;
- y1 = y2;
- y2 = ytmp;
- }
- /*
- * Get clipping boundary and
- * check visibility of vline
- */
- left = dst->clip_rect.x;
- right = dst->clip_rect.x + dst->clip_rect.w - 1;
- if ((x < left) || (x > right)) {
- return (0);
- }
- top = dst->clip_rect.y;
- if (y2 < top) {
- return (0);
- }
- bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
- if (y1 > bottom) {
- return (0);
- }
- /*
- * Clip x
- */
- if (y1 < top) {
- y1 = top;
- }
- if (y2 > bottom) {
- y2 = bottom;
- }
- /*
- * Calculate height
- */
- h = y2 - y1;
- /*
- * Alpha check
- */
- if ((color & 255) == 255) {
- /*
- * No alpha-blending required
- */
- /*
- * Setup color
- */
- colorptr = (Uint8 *) &color;
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
- color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
- } else {
- color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
- }
- /*
- * Lock the surface
- */
- if (SDL_MUSTLOCK(dst)) {
- if (SDL_LockSurface(dst) < 0) {
- return (-1);
- }
- }
- /*
- * More variable setup
- */
- dy = h;
- pixx = dst->format->BytesPerPixel;
- pixy = dst->pitch;
- pixel = ((Uint8 *) dst->pixels) + pixx * (int) x + pixy * (int) y1;
- pixellast = pixel + pixy * dy;
- /*
- * Draw
- */
- switch (dst->format->BytesPerPixel) {
- case 1:
- for (; pixel <= pixellast; pixel += pixy) {
- *(Uint8 *) pixel = color;
- }
- break;
- case 2:
- for (; pixel <= pixellast; pixel += pixy) {
- *(Uint16 *) pixel = color;
- }
- break;
- case 3:
- for (; pixel <= pixellast; pixel += pixy) {
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
- pixel[0] = (color >> 16) & 0xff;
- pixel[1] = (color >> 8) & 0xff;
- pixel[2] = color & 0xff;
- } else {
- pixel[0] = color & 0xff;
- pixel[1] = (color >> 8) & 0xff;
- pixel[2] = (color >> 16) & 0xff;
- }
- }
- break;
- default: /* case 4 */
- for (; pixel <= pixellast; pixel += pixy) {
- *(Uint32 *) pixel = color;
- }
- break;
- }
- /* Unlock surface */
- if (SDL_MUSTLOCK(dst)) {
- SDL_UnlockSurface(dst);
- }
- /*
- * Set result code
- */
- result = 0;
- } else {
- /*
- * Alpha blending blit
- */
- result = _VLineAlpha(dst, x, y1, y1 + h, color);
- }
- return (result);
- }
- /*!
- \brief Draw vertical line with blending.
- \param dst The surface to draw on.
- \param x X coordinate of the points of the line.
- \param y1 Y coordinate of the first point (i.e. top) of the line.
- \param y2 Y coordinate of the second point (i.e. bottom) of the line.
- \param r The red value of the line to draw.
- \param g The green value of the line to draw.
- \param b The blue value of the line to draw.
- \param a The alpha value of the line to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int vlineRGBA(SDL_Surface *dst, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (vlineColor(dst, x, y1, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /*!
- \brief Draw rectangle with blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point (i.e. top right) of the rectangle.
- \param y1 Y coordinate of the first point (i.e. top right) of the rectangle.
- \param x2 X coordinate of the second point (i.e. bottom left) of the rectangle.
- \param y2 Y coordinate of the second point (i.e. bottom left) of the rectangle.
- \param color The color value of the rectangle to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int rectangleColor(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color) {
- int result;
- Sint16 tmp;
- /* Check destination surface */
- if (dst == NULL) {
- return -1;
- }
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return 0;
- }
- /*
- * Test for special cases of straight lines or single point
- */
- if (x1 == x2) {
- if (y1 == y2) {
- return (pixelColor(dst, x1, y1, color));
- } else {
- return (vlineColor(dst, x1, y1, y2, color));
- }
- } else {
- if (y1 == y2) {
- return (hlineColor(dst, x1, x2, y1, color));
- }
- }
- /*
- * Swap x1, x2 if required
- */
- if (x1 > x2) {
- tmp = x1;
- x1 = x2;
- x2 = tmp;
- }
- /*
- * Swap y1, y2 if required
- */
- if (y1 > y2) {
- tmp = y1;
- y1 = y2;
- y2 = tmp;
- }
- /*
- * Draw rectangle
- */
- result = 0;
- result |= hlineColor(dst, x1, x2, y1, color);
- result |= hlineColor(dst, x1, x2, y2, color);
- y1 += 1;
- y2 -= 1;
- if (y1 <= y2) {
- result |= vlineColor(dst, x1, y1, y2, color);
- result |= vlineColor(dst, x2, y1, y2, color);
- }
- return (result);
- }
- /*!
- \brief Draw rectangle with blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point (i.e. top right) of the rectangle.
- \param y1 Y coordinate of the first point (i.e. top right) of the rectangle.
- \param x2 X coordinate of the second point (i.e. bottom left) of the rectangle.
- \param y2 Y coordinate of the second point (i.e. bottom left) of the rectangle.
- \param r The red value of the rectangle to draw.
- \param g The green value of the rectangle to draw.
- \param b The blue value of the rectangle to draw.
- \param a The alpha value of the rectangle to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int rectangleRGBA(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (rectangleColor
- (dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /*!
- \brief Draw rounded-corner rectangle with blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point (i.e. top right) of the rectangle.
- \param y1 Y coordinate of the first point (i.e. top right) of the rectangle.
- \param x2 X coordinate of the second point (i.e. bottom left) of the rectangle.
- \param y2 Y coordinate of the second point (i.e. bottom left) of the rectangle.
- \param rad The radius of the corner arc.
- \param color The color value of the rectangle to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int roundedRectangleColor(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color) {
- int result;
- Sint16 w, h, tmp;
- Sint16 xx1, xx2, yy1, yy2;
- /*
- * Check destination surface
- */
- if (dst == NULL) {
- return -1;
- }
- /*
- * Check radius vor valid range
- */
- if (rad < 0) {
- return -1;
- }
- /*
- * Special case - no rounding
- */
- if (rad == 0) {
- return rectangleColor(dst, x1, y1, x2, y2, color);
- }
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return 0;
- }
- /*
- * Test for special cases of straight lines or single point
- */
- if (x1 == x2) {
- if (y1 == y2) {
- return (pixelColor(dst, x1, y1, color));
- } else {
- return (vlineColor(dst, x1, y1, y2, color));
- }
- } else {
- if (y1 == y2) {
- return (hlineColor(dst, x1, x2, y1, color));
- }
- }
- /*
- * Swap x1, x2 if required
- */
- if (x1 > x2) {
- tmp = x1;
- x1 = x2;
- x2 = tmp;
- }
- /*
- * Swap y1, y2 if required
- */
- if (y1 > y2) {
- tmp = y1;
- y1 = y2;
- y2 = tmp;
- }
- /*
- * Calculate width&height
- */
- w = x2 - x1;
- h = y2 - y1;
- /*
- * Maybe adjust radius
- */
- if ((rad * 2) > w) {
- rad = w / 2;
- }
- if ((rad * 2) > h) {
- rad = h / 2;
- }
- /*
- * Draw corners
- */
- result = 0;
- xx1 = x1 + rad;
- xx2 = x2 - rad;
- yy1 = y1 + rad;
- yy2 = y2 - rad;
- result |= arcColor(dst, xx1, yy1, rad, 180, 270, color);
- result |= arcColor(dst, xx2, yy1, rad, 270, 360, color);
- result |= arcColor(dst, xx1, yy2, rad, 90, 180, color);
- result |= arcColor(dst, xx2, yy2, rad, 0, 90, color);
- /*
- * Draw lines
- */
- if (xx1 <= xx2) {
- result |= hlineColor(dst, xx1, xx2, y1, color);
- result |= hlineColor(dst, xx1, xx2, y2, color);
- }
- if (yy1 <= yy2) {
- result |= vlineColor(dst, x1, yy1, yy2, color);
- result |= vlineColor(dst, x2, yy1, yy2, color);
- }
- return result;
- }
- /*!
- \brief Draw rounded-corner rectangle with blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point (i.e. top right) of the rectangle.
- \param y1 Y coordinate of the first point (i.e. top right) of the rectangle.
- \param x2 X coordinate of the second point (i.e. bottom left) of the rectangle.
- \param y2 Y coordinate of the second point (i.e. bottom left) of the rectangle.
- \param rad The radius of the corner arc.
- \param r The red value of the rectangle to draw.
- \param g The green value of the rectangle to draw.
- \param b The blue value of the rectangle to draw.
- \param a The alpha value of the rectangle to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int roundedRectangleRGBA(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint8 r, Uint8 g,
- Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (roundedRectangleColor
- (dst, x1, y1, x2, y2, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /*!
- \brief Draw rounded-corner box (filled rectangle) with blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point (i.e. top right) of the box.
- \param y1 Y coordinate of the first point (i.e. top right) of the box.
- \param x2 X coordinate of the second point (i.e. bottom left) of the box.
- \param y2 Y coordinate of the second point (i.e. bottom left) of the box.
- \param rad The radius of the corner arcs of the box.
- \param color The color value of the box to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int roundedBoxColor(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color) {
- int result;
- Sint16 w, h, tmp;
- Sint16 xx1, xx2, yy1, yy2;
- /*
- * Check destination surface
- */
- if (dst == NULL) {
- return -1;
- }
- /*
- * Check radius vor valid range
- */
- if (rad < 0) {
- return -1;
- }
- /*
- * Special case - no rounding
- */
- if (rad == 0) {
- return rectangleColor(dst, x1, y1, x2, y2, color);
- }
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return 0;
- }
- /*
- * Test for special cases of straight lines or single point
- */
- if (x1 == x2) {
- if (y1 == y2) {
- return (pixelColor(dst, x1, y1, color));
- } else {
- return (vlineColor(dst, x1, y1, y2, color));
- }
- } else {
- if (y1 == y2) {
- return (hlineColor(dst, x1, x2, y1, color));
- }
- }
- /*
- * Swap x1, x2 if required
- */
- if (x1 > x2) {
- tmp = x1;
- x1 = x2;
- x2 = tmp;
- }
- /*
- * Swap y1, y2 if required
- */
- if (y1 > y2) {
- tmp = y1;
- y1 = y2;
- y2 = tmp;
- }
- /*
- * Calculate width&height
- */
- w = x2 - x1;
- h = y2 - y1;
- /*
- * Maybe adjust radius
- */
- if ((rad * 2) > w) {
- rad = w / 2;
- }
- if ((rad * 2) > h) {
- rad = h / 2;
- }
- /*
- * Draw corners
- */
- result = 0;
- xx1 = x1 + rad;
- xx2 = x2 - rad;
- yy1 = y1 + rad;
- yy2 = y2 - rad;
- result |= filledPieColor(dst, xx1, yy1, rad, 180, 270, color);
- result |= filledPieColor(dst, xx2, yy1, rad, 270, 360, color);
- result |= filledPieColor(dst, xx1, yy2, rad, 90, 180, color);
- result |= filledPieColor(dst, xx2, yy2, rad, 0, 90, color);
- /*
- * Draw body
- */
- xx1++;
- xx2--;
- yy1++;
- yy2--;
- if (xx1 <= xx2) {
- result |= boxColor(dst, xx1, y1, xx2, y2, color);
- }
- if (yy1 <= yy2) {
- result |= boxColor(dst, x1, yy1, xx1 - 1, yy2, color);
- result |= boxColor(dst, xx2 + 1, yy1, x2, yy2, color);
- }
- return result;
- }
- /*!
- \brief Draw rounded-corner box (filled rectangle) with blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point (i.e. top right) of the box.
- \param y1 Y coordinate of the first point (i.e. top right) of the box.
- \param x2 X coordinate of the second point (i.e. bottom left) of the box.
- \param y2 Y coordinate of the second point (i.e. bottom left) of the box.
- \param rad The radius of the corner arcs of the box.
- \param r The red value of the box to draw.
- \param g The green value of the box to draw.
- \param b The blue value of the box to draw.
- \param a The alpha value of the box to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int roundedBoxRGBA(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2,
- Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (roundedBoxColor
- (dst, x1, y1, x2, y2, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /* --------- Clipping routines for line */
- /* Clipping based heavily on code from */
- /* http://www.ncsa.uiuc.edu/Vis/Graphics/src/clipCohSuth.c */
- #define CLIP_LEFT_EDGE 0x1
- #define CLIP_RIGHT_EDGE 0x2
- #define CLIP_BOTTOM_EDGE 0x4
- #define CLIP_TOP_EDGE 0x8
- #define CLIP_INSIDE(a) (!a)
- #define CLIP_REJECT(a, b) (a&b)
- #define CLIP_ACCEPT(a, b) (!(a|b))
- /*!
- \brief Internal clip-encoding routine.
- Calculates a segement-based clipping encoding for a point against a rectangle.
- \param x X coordinate of point.
- \param y Y coordinate of point.
- \param left X coordinate of left edge of the rectangle.
- \param top Y coordinate of top edge of the rectangle.
- \param right X coordinate of right edge of the rectangle.
- \param bottom Y coordinate of bottom edge of the rectangle.
- */
- static int _clipEncode(Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom) {
- int code = 0;
- if (x < left) {
- code |= CLIP_LEFT_EDGE;
- } else if (x > right) {
- code |= CLIP_RIGHT_EDGE;
- }
- if (y < top) {
- code |= CLIP_TOP_EDGE;
- } else if (y > bottom) {
- code |= CLIP_BOTTOM_EDGE;
- }
- return code;
- }
- /*!
- \brief Clip line to a the clipping rectangle of a surface.
- \param dst Target surface to draw on.
- \param x1 Pointer to X coordinate of first point of line.
- \param y1 Pointer to Y coordinate of first point of line.
- \param x2 Pointer to X coordinate of second point of line.
- \param y2 Pointer to Y coordinate of second point of line.
- */
- static int _clipLine(SDL_Surface *dst, Sint16 *x1, Sint16 *y1, Sint16 *x2, Sint16 *y2) {
- Sint16 left, right, top, bottom;
- int code1, code2;
- int draw = 0;
- Sint16 swaptmp;
- float m;
- /*
- * Get clipping boundary
- */
- left = dst->clip_rect.x;
- right = dst->clip_rect.x + dst->clip_rect.w - 1;
- top = dst->clip_rect.y;
- bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
- while (1) {
- code1 = _clipEncode(*x1, *y1, left, top, right, bottom);
- code2 = _clipEncode(*x2, *y2, left, top, right, bottom);
- if (CLIP_ACCEPT(code1, code2)) {
- draw = 1;
- break;
- } else if (CLIP_REJECT(code1, code2))
- break;
- else {
- if (CLIP_INSIDE(code1)) {
- swaptmp = *x2;
- *x2 = *x1;
- *x1 = swaptmp;
- swaptmp = *y2;
- *y2 = *y1;
- *y1 = swaptmp;
- swaptmp = code2;
- code2 = code1;
- code1 = swaptmp;
- }
- if (*x2 != *x1) {
- m = (float) (*y2 - *y1) / (float) (*x2 - *x1);
- } else {
- m = 1.0f;
- }
- if (code1 & CLIP_LEFT_EDGE) {
- *y1 += (Sint16) ((left - *x1) * m);
- *x1 = left;
- } else if (code1 & CLIP_RIGHT_EDGE) {
- *y1 += (Sint16) ((right - *x1) * m);
- *x1 = right;
- } else if (code1 & CLIP_BOTTOM_EDGE) {
- if (*x2 != *x1) {
- *x1 += (Sint16) ((bottom - *y1) / m);
- }
- *y1 = bottom;
- } else if (code1 & CLIP_TOP_EDGE) {
- if (*x2 != *x1) {
- *x1 += (Sint16) ((top - *y1) / m);
- }
- *y1 = top;
- }
- }
- }
- return draw;
- }
- /*!
- \brief Draw box (filled rectangle) with blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point (i.e. top right) of the box.
- \param y1 Y coordinate of the first point (i.e. top right) of the box.
- \param x2 X coordinate of the second point (i.e. bottom left) of the box.
- \param y2 Y coordinate of the second point (i.e. bottom left) of the box.
- \param color The color value of the box to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int boxColor(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color) {
- Sint16 left, right, top, bottom;
- Uint8 *pixel, *pixellast;
- int x, dx;
- int dy;
- int pixx, pixy;
- Sint16 w, h, tmp;
- int result;
- Uint8 *colorptr;
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return (0);
- }
- /*
- * Order coordinates to ensure that
- * x1<=x2 and y1<=y2
- */
- if (x1 > x2) {
- tmp = x1;
- x1 = x2;
- x2 = tmp;
- }
- if (y1 > y2) {
- tmp = y1;
- y1 = y2;
- y2 = tmp;
- }
- /*
- * Get clipping boundary and
- * check visibility
- */
- left = dst->clip_rect.x;
- if (x2 < left) {
- return (0);
- }
- right = dst->clip_rect.x + dst->clip_rect.w - 1;
- if (x1 > right) {
- return (0);
- }
- top = dst->clip_rect.y;
- if (y2 < top) {
- return (0);
- }
- bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
- if (y1 > bottom) {
- return (0);
- }
- /* Clip all points */
- if (x1 < left) {
- x1 = left;
- } else if (x1 > right) {
- x1 = right;
- }
- if (x2 < left) {
- x2 = left;
- } else if (x2 > right) {
- x2 = right;
- }
- if (y1 < top) {
- y1 = top;
- } else if (y1 > bottom) {
- y1 = bottom;
- }
- if (y2 < top) {
- y2 = top;
- } else if (y2 > bottom) {
- y2 = bottom;
- }
- /*
- * Test for special cases of straight line or single point
- */
- if (x1 == x2) {
- if (y1 == y2) {
- return (pixelColor(dst, x1, y1, color));
- } else {
- return (vlineColor(dst, x1, y1, y2, color));
- }
- }
- if (y1 == y2) {
- return (hlineColor(dst, x1, x2, y1, color));
- }
- /*
- * Calculate width&height
- */
- w = x2 - x1;
- h = y2 - y1;
- /*
- * Alpha check
- */
- if ((color & 255) == 255) {
- /*
- * No alpha-blending required
- */
- /*
- * Setup color
- */
- colorptr = (Uint8 *) &color;
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
- color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
- } else {
- color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
- }
- /*
- * Lock the surface
- */
- if (SDL_MUSTLOCK(dst)) {
- if (SDL_LockSurface(dst) < 0) {
- return (-1);
- }
- }
- /*
- * More variable setup
- */
- dx = w;
- dy = h;
- pixx = dst->format->BytesPerPixel;
- pixy = dst->pitch;
- pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1;
- pixellast = pixel + pixx * dx + pixy * dy;
- dx++;
- /*
- * Draw
- */
- switch (dst->format->BytesPerPixel) {
- case 1:
- for (; pixel <= pixellast; pixel += pixy) {
- memset(pixel, (Uint8) color, dx);
- }
- break;
- case 2:
- pixy -= (pixx * dx);
- for (; pixel <= pixellast; pixel += pixy) {
- for (x = 0; x < dx; x++) {
- *(Uint16 *) pixel = color;
- pixel += pixx;
- }
- }
- break;
- case 3:
- pixy -= (pixx * dx);
- for (; pixel <= pixellast; pixel += pixy) {
- for (x = 0; x < dx; x++) {
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
- pixel[0] = (color >> 16) & 0xff;
- pixel[1] = (color >> 8) & 0xff;
- pixel[2] = color & 0xff;
- } else {
- pixel[0] = color & 0xff;
- pixel[1] = (color >> 8) & 0xff;
- pixel[2] = (color >> 16) & 0xff;
- }
- pixel += pixx;
- }
- }
- break;
- default: /* case 4 */
- pixy -= (pixx * dx);
- for (; pixel <= pixellast; pixel += pixy) {
- for (x = 0; x < dx; x++) {
- *(Uint32 *) pixel = color;
- pixel += pixx;
- }
- }
- break;
- }
- /* Unlock surface */
- if (SDL_MUSTLOCK(dst)) {
- SDL_UnlockSurface(dst);
- }
- result = 0;
- } else {
- result = filledRectAlpha(dst, x1, y1, x1 + w, y1 + h, color);
- }
- return (result);
- }
- /*!
- \brief Draw box (filled rectangle) with blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point (i.e. top right) of the box.
- \param y1 Y coordinate of the first point (i.e. top right) of the box.
- \param x2 X coordinate of the second point (i.e. bottom left) of the box.
- \param y2 Y coordinate of the second point (i.e. bottom left) of the box.
- \param r The red value of the box to draw.
- \param g The green value of the box to draw.
- \param b The blue value of the box to draw.
- \param a The alpha value of the box to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int boxRGBA(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (boxColor(dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /* ----- Line */
- /* Non-alpha line drawing code adapted from routine */
- /* by Pete Shinners, pete@shinners.org */
- /* Originally from pygame, http://pygame.seul.org */
- #define ABS(a) (((a)<0) ? -(a) : (a))
- /*!
- \brief Draw line with alpha blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point of the line.
- \param y1 Y coordinate of the first point of the line.
- \param x2 X coordinate of the second point of the line.
- \param y2 Y coordinate of the second point of the line.
- \param color The color value of the line to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int lineColor(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color) {
- int pixx, pixy;
- int x, y;
- int dx, dy;
- int ax, ay;
- int sx, sy;
- int swaptmp;
- Uint8 *pixel;
- Uint8 *colorptr;
- /*
- * Clip line and test if we have to draw
- */
- if (!(_clipLine(dst, &x1, &y1, &x2, &y2))) {
- return (0);
- }
- /*
- * Test for special cases of straight lines or single point
- */
- if (x1 == x2) {
- if (y1 < y2) {
- return (vlineColor(dst, x1, y1, y2, color));
- } else if (y1 > y2) {
- return (vlineColor(dst, x1, y2, y1, color));
- } else {
- return (pixelColor(dst, x1, y1, color));
- }
- }
- if (y1 == y2) {
- if (x1 < x2) {
- return (hlineColor(dst, x1, x2, y1, color));
- } else if (x1 > x2) {
- return (hlineColor(dst, x2, x1, y1, color));
- }
- }
- /*
- * Variable setup
- */
- dx = x2 - x1;
- dy = y2 - y1;
- sx = (dx >= 0) ? 1 : -1;
- sy = (dy >= 0) ? 1 : -1;
- /* Lock surface */
- if (SDL_MUSTLOCK(dst)) {
- if (SDL_LockSurface(dst) < 0) {
- return (-1);
- }
- }
- /*
- * Check for alpha blending
- */
- if ((color & 255) == 255) {
- /*
- * No alpha blending - use fast pixel routines
- */
- /*
- * Setup color
- */
- colorptr = (Uint8 *) &color;
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
- color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
- } else {
- color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
- }
- /*
- * More variable setup
- */
- dx = sx * dx + 1;
- dy = sy * dy + 1;
- pixx = dst->format->BytesPerPixel;
- pixy = dst->pitch;
- pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1;
- pixx *= sx;
- pixy *= sy;
- if (dx < dy) {
- swaptmp = dx;
- dx = dy;
- dy = swaptmp;
- swaptmp = pixx;
- pixx = pixy;
- pixy = swaptmp;
- }
- /*
- * Draw
- */
- x = 0;
- y = 0;
- switch (dst->format->BytesPerPixel) {
- case 1:
- for (; x < dx; x++, pixel += pixx) {
- *pixel = color;
- y += dy;
- if (y >= dx) {
- y -= dx;
- pixel += pixy;
- }
- }
- break;
- case 2:
- for (; x < dx; x++, pixel += pixx) {
- *(Uint16 *) pixel = color;
- y += dy;
- if (y >= dx) {
- y -= dx;
- pixel += pixy;
- }
- }
- break;
- case 3:
- for (; x < dx; x++, pixel += pixx) {
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
- pixel[0] = (color >> 16) & 0xff;
- pixel[1] = (color >> 8) & 0xff;
- pixel[2] = color & 0xff;
- } else {
- pixel[0] = color & 0xff;
- pixel[1] = (color >> 8) & 0xff;
- pixel[2] = (color >> 16) & 0xff;
- }
- y += dy;
- if (y >= dx) {
- y -= dx;
- pixel += pixy;
- }
- }
- break;
- default: /* case 4 */
- for (; x < dx; x++, pixel += pixx) {
- *(Uint32 *) pixel = color;
- y += dy;
- if (y >= dx) {
- y -= dx;
- pixel += pixy;
- }
- }
- break;
- }
- } else {
- /*
- * Alpha blending required - use single-pixel blits
- */
- ax = ABS(dx) << 1;
- ay = ABS(dy) << 1;
- x = x1;
- y = y1;
- if (ax > ay) {
- int d = ay - (ax >> 1);
- while (x != x2) {
- pixelColorNolock(dst, x, y, color);
- if (d > 0 || (d == 0 && sx == 1)) {
- y += sy;
- d -= ax;
- }
- x += sx;
- d += ay;
- }
- } else {
- int d = ax - (ay >> 1);
- while (y != y2) {
- pixelColorNolock(dst, x, y, color);
- if (d > 0 || ((d == 0) && (sy == 1))) {
- x += sx;
- d -= ay;
- }
- y += sy;
- d += ax;
- }
- }
- pixelColorNolock(dst, x, y, color);
- }
- /* Unlock surface */
- if (SDL_MUSTLOCK(dst)) {
- SDL_UnlockSurface(dst);
- }
- return (0);
- }
- /*!
- \brief Draw line with alpha blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point of the line.
- \param y1 Y coordinate of the first point of the line.
- \param x2 X coordinate of the second point of the line.
- \param y2 Y coordinate of the second point of the line.
- \param r The red value of the line to draw.
- \param g The green value of the line to draw.
- \param b The blue value of the line to draw.
- \param a The alpha value of the line to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int lineRGBA(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (lineColor(dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /* AA Line */
- #define AAlevels 256
- #define AAbits 8
- /*!
- \brief Internal function to draw anti-aliased line with alpha blending and endpoint control.
- This implementation of the Wu antialiasing code is based on Mike Abrash's
- DDJ article which was reprinted as Chapter 42 of his Graphics Programming
- Black Book, but has been optimized to work with SDL and utilizes 32-bit
- fixed-point arithmetic by A. Schiffler. The endpoint control allows the
- supression to draw the last pixel useful for rendering continous aa-lines
- with alpha<255.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point of the aa-line.
- \param y1 Y coordinate of the first point of the aa-line.
- \param x2 X coordinate of the second point of the aa-line.
- \param y2 Y coordinate of the second point of the aa-line.
- \param color The color value of the aa-line to draw (0xRRGGBBAA).
- \param draw_endpoint Flag indicating if the endpoint should be drawn; draw if non-zero.
- \returns Returns 0 on success, -1 on failure.
- */
- int _aalineColor(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, int draw_endpoint) {
- Sint32 xx0, yy0, xx1, yy1;
- int result;
- Uint32 intshift, erracc, erradj;
- Uint32 erracctmp, wgt, wgtcompmask;
- int dx, dy, tmp, xdir, y0p1, x0pxdir;
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return (0);
- }
- /*
- * Clip line and test if we have to draw
- */
- if (!(_clipLine(dst, &x1, &y1, &x2, &y2))) {
- return (0);
- }
- /*
- * Keep on working with 32bit numbers
- */
- xx0 = x1;
- yy0 = y1;
- xx1 = x2;
- yy1 = y2;
- /*
- * Reorder points if required
- */
- if (yy0 > yy1) {
- tmp = yy0;
- yy0 = yy1;
- yy1 = tmp;
- tmp = xx0;
- xx0 = xx1;
- xx1 = tmp;
- }
- /*
- * Calculate distance
- */
- dx = xx1 - xx0;
- dy = yy1 - yy0;
- /*
- * Check for special cases
- */
- if (dx == 0) {
- /*
- * Vertical line
- */
- if (draw_endpoint) {
- return (vlineColor(dst, x1, y1, y2, color));
- } else {
- if (dy > 0) {
- return (vlineColor(dst, x1, yy0, yy0 + dy, color));
- } else {
- return (pixelColor(dst, x1, y1, color));
- }
- }
- } else if (dy == 0) {
- /*
- * Horizontal line
- */
- if (draw_endpoint) {
- return (hlineColor(dst, x1, x2, y1, color));
- } else {
- if (dx != 0) {
- return (hlineColor(dst, xx0, xx0 + dx, y1, color));
- } else {
- return (pixelColor(dst, x1, y1, color));
- }
- }
- } else if ((dx == dy) && (draw_endpoint)) {
- /*
- * Diagonal line (with endpoint)
- */
- return (lineColor(dst, x1, y1, x2, y2, color));
- }
- /*
- * Adjust for negative dx and set xdir
- */
- if (dx >= 0) {
- xdir = 1;
- } else {
- xdir = -1;
- dx = (-dx);
- }
- /*
- * Line is not horizontal, vertical or diagonal (with endpoint)
- */
- result = 0;
- /*
- * Zero accumulator
- */
- erracc = 0;
- /*
- * # of bits by which to shift erracc to get intensity level
- */
- intshift = 32 - AAbits;
- /*
- * Mask used to flip all bits in an intensity weighting
- */
- wgtcompmask = AAlevels - 1;
- /* Lock surface */
- if (SDL_MUSTLOCK(dst)) {
- if (SDL_LockSurface(dst) < 0) {
- return (-1);
- }
- }
- /*
- * Draw the initial pixel in the foreground color
- */
- result |= pixelColorNolock(dst, x1, y1, color);
- /*
- * x-major or y-major?
- */
- if (dy > dx) {
- /*
- * y-major. Calculate 16-bit fixed point fractional part of a pixel that
- * X advances every time Y advances 1 pixel, truncating the result so that
- * we won't overrun the endpoint along the X axis
- */
- /*
- * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy;
- */
- erradj = ((dx << 16) / dy) << 16;
- /*
- * draw all pixels other than the first and last
- */
- x0pxdir = xx0 + xdir;
- while (--dy) {
- erracctmp = erracc;
- erracc += erradj;
- if (erracc <= erracctmp) {
- /*
- * rollover in error accumulator, x coord advances
- */
- xx0 = x0pxdir;
- x0pxdir += xdir;
- }
- yy0++; /* y-major so always advance Y */
- /*
- * the AAbits most significant bits of erracc give us the intensity
- * weighting for this pixel, and the complement of the weighting for
- * the paired pixel.
- */
- wgt = (erracc >> intshift) & 255;
- result |= pixelColorWeightNolock(dst, xx0, yy0, color, 255 - wgt);
- result |= pixelColorWeightNolock(dst, x0pxdir, yy0, color, wgt);
- }
- } else {
- /*
- * x-major line. Calculate 16-bit fixed-point fractional part of a pixel
- * that Y advances each time X advances 1 pixel, truncating the result so
- * that we won't overrun the endpoint along the X axis.
- */
- /*
- * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx;
- */
- erradj = ((dy << 16) / dx) << 16;
- /*
- * draw all pixels other than the first and last
- */
- y0p1 = yy0 + 1;
- while (--dx) {
- erracctmp = erracc;
- erracc += erradj;
- if (erracc <= erracctmp) {
- /*
- * Accumulator turned over, advance y
- */
- yy0 = y0p1;
- y0p1++;
- }
- xx0 += xdir; /* x-major so always advance X */
- /*
- * the AAbits most significant bits of erracc give us the intensity
- * weighting for this pixel, and the complement of the weighting for
- * the paired pixel.
- */
- wgt = (erracc >> intshift) & 255;
- result |= pixelColorWeightNolock(dst, xx0, yy0, color, 255 - wgt);
- result |= pixelColorWeightNolock(dst, xx0, y0p1, color, wgt);
- }
- }
- /*
- * Do we have to draw the endpoint
- */
- if (draw_endpoint) {
- /*
- * Draw final pixel, always exactly intersected by the line and doesn't
- * need to be weighted.
- */
- result |= pixelColorNolock(dst, x2, y2, color);
- }
- /* Unlock surface */
- if (SDL_MUSTLOCK(dst)) {
- SDL_UnlockSurface(dst);
- }
- return (result);
- }
- /*!
- \brief Ddraw anti-aliased line with alpha blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point of the aa-line.
- \param y1 Y coordinate of the first point of the aa-line.
- \param x2 X coordinate of the second point of the aa-line.
- \param y2 Y coordinate of the second point of the aa-line.
- \param color The color value of the aa-line to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int aalineColor(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color) {
- return (_aalineColor(dst, x1, y1, x2, y2, color, 1));
- }
- /*!
- \brief Draw anti-aliased line with alpha blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point of the aa-line.
- \param y1 Y coordinate of the first point of the aa-line.
- \param x2 X coordinate of the second point of the aa-line.
- \param y2 Y coordinate of the second point of the aa-line.
- \param r The red value of the aa-line to draw.
- \param g The green value of the aa-line to draw.
- \param b The blue value of the aa-line to draw.
- \param a The alpha value of the aa-line to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int aalineRGBA(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- return (_aalineColor
- (dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1));
- }
- /* ----- Circle */
- /*!
- \brief Draw circle with blending.
- Note: Circle drawing routine is based on an algorithms from the sge library,
- but modified by A. Schiffler for multiple pixel-draw removal and other
- minor speedup changes.
- \param dst The surface to draw on.
- \param x X coordinate of the center of the circle.
- \param y Y coordinate of the center of the circle.
- \param rad Radius in pixels of the circle.
- \param color The color value of the circle to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int circleColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color) {
- Sint16 left, right, top, bottom;
- int result;
- Sint16 x1, y1, x2, y2;
- Sint16 cx = 0;
- Sint16 cy = rad;
- Sint16 df = 1 - rad;
- Sint16 d_e = 3;
- Sint16 d_se = -2 * rad + 5;
- Sint16 xpcx, xmcx, xpcy, xmcy;
- Sint16 ypcy, ymcy, ypcx, ymcx;
- Uint8 *colorptr;
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return (0);
- }
- /*
- * Sanity check radius
- */
- if (rad < 0) {
- return (-1);
- }
- /*
- * Special case for rad=0 - draw a point
- */
- if (rad == 0) {
- return (pixelColor(dst, x, y, color));
- }
- /*
- * Get circle and clipping boundary and
- * test if bounding box of circle is visible
- */
- x2 = x + rad;
- left = dst->clip_rect.x;
- if (x2 < left) {
- return (0);
- }
- x1 = x - rad;
- right = dst->clip_rect.x + dst->clip_rect.w - 1;
- if (x1 > right) {
- return (0);
- }
- y2 = y + rad;
- top = dst->clip_rect.y;
- if (y2 < top) {
- return (0);
- }
- y1 = y - rad;
- bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
- if (y1 > bottom) {
- return (0);
- }
- /*
- * Draw circle
- */
- result = 0;
- /* Lock surface */
- if (SDL_MUSTLOCK(dst)) {
- if (SDL_LockSurface(dst) < 0) {
- return (-1);
- }
- }
- /*
- * Alpha Check
- */
- if ((color & 255) == 255) {
- /*
- * No Alpha - direct memory writes
- */
- /*
- * Setup color
- */
- colorptr = (Uint8 *) &color;
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
- color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
- } else {
- color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
- }
- /*
- * Draw
- */
- do {
- ypcy = y + cy;
- ymcy = y - cy;
- if (cx > 0) {
- xpcx = x + cx;
- xmcx = x - cx;
- result |= fastPixelColorNolock(dst, xmcx, ypcy, color);
- result |= fastPixelColorNolock(dst, xpcx, ypcy, color);
- result |= fastPixelColorNolock(dst, xmcx, ymcy, color);
- result |= fastPixelColorNolock(dst, xpcx, ymcy, color);
- } else {
- result |= fastPixelColorNolock(dst, x, ymcy, color);
- result |= fastPixelColorNolock(dst, x, ypcy, color);
- }
- xpcy = x + cy;
- xmcy = x - cy;
- if ((cx > 0) && (cx != cy)) {
- ypcx = y + cx;
- ymcx = y - cx;
- result |= fastPixelColorNolock(dst, xmcy, ypcx, color);
- result |= fastPixelColorNolock(dst, xpcy, ypcx, color);
- result |= fastPixelColorNolock(dst, xmcy, ymcx, color);
- result |= fastPixelColorNolock(dst, xpcy, ymcx, color);
- } else if (cx == 0) {
- result |= fastPixelColorNolock(dst, xmcy, y, color);
- result |= fastPixelColorNolock(dst, xpcy, y, color);
- }
- /*
- * Update
- */
- if (df < 0) {
- df += d_e;
- d_e += 2;
- d_se += 2;
- } else {
- df += d_se;
- d_e += 2;
- d_se += 4;
- cy--;
- }
- cx++;
- } while (cx <= cy);
- /*
- * Unlock surface
- */
- SDL_UnlockSurface(dst);
- } else {
- /*
- * Using Alpha - blended pixel blits
- */
- do {
- /*
- * Draw
- */
- ypcy = y + cy;
- ymcy = y - cy;
- if (cx > 0) {
- xpcx = x + cx;
- xmcx = x - cx;
- result |= pixelColorNolock(dst, xmcx, ypcy, color);
- result |= pixelColorNolock(dst, xpcx, ypcy, color);
- result |= pixelColorNolock(dst, xmcx, ymcy, color);
- result |= pixelColorNolock(dst, xpcx, ymcy, color);
- } else {
- result |= pixelColorNolock(dst, x, ymcy, color);
- result |= pixelColorNolock(dst, x, ypcy, color);
- }
- xpcy = x + cy;
- xmcy = x - cy;
- if ((cx > 0) && (cx != cy)) {
- ypcx = y + cx;
- ymcx = y - cx;
- result |= pixelColorNolock(dst, xmcy, ypcx, color);
- result |= pixelColorNolock(dst, xpcy, ypcx, color);
- result |= pixelColorNolock(dst, xmcy, ymcx, color);
- result |= pixelColorNolock(dst, xpcy, ymcx, color);
- } else if (cx == 0) {
- result |= pixelColorNolock(dst, xmcy, y, color);
- result |= pixelColorNolock(dst, xpcy, y, color);
- }
- /*
- * Update
- */
- if (df < 0) {
- df += d_e;
- d_e += 2;
- d_se += 2;
- } else {
- df += d_se;
- d_e += 2;
- d_se += 4;
- cy--;
- }
- cx++;
- } while (cx <= cy);
- } /* Alpha check */
- /* Unlock surface */
- if (SDL_MUSTLOCK(dst)) {
- SDL_UnlockSurface(dst);
- }
- return (result);
- }
- /*!
- \brief Draw circle with blending.
- \param dst The surface to draw on.
- \param x X coordinate of the center of the circle.
- \param y Y coordinate of the center of the circle.
- \param rad Radius in pixels of the circle.
- \param r The red value of the circle to draw.
- \param g The green value of the circle to draw.
- \param b The blue value of the circle to draw.
- \param a The alpha value of the circle to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int circleRGBA(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (circleColor(dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /* ----- Arc */
- /*!
- \brief Arc with blending.
- Note Arc drawing is based on circle algorithm by A. Schiffler and
- written by D. Raber. Calculates which octants arc goes through and
- renders pixels accordingly.
- \param dst The surface to draw on.
- \param x X coordinate of the center of the arc.
- \param y Y coordinate of the center of the arc.
- \param rad Radius in pixels of the arc.
- \param start Starting radius in degrees of the arc. 0 degrees is down, increasing counterclockwise.
- \param end Ending radius in degrees of the arc. 0 degrees is down, increasing counterclockwise.
- \param color The color value of the arc to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int arcColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color) {
- Sint16 left, right, top, bottom;
- int result;
- Sint16 x1, y1, x2, y2;
- Sint16 cx = 0;
- Sint16 cy = rad;
- Sint16 df = 1 - rad;
- Sint16 d_e = 3;
- Sint16 d_se = -2 * rad + 5;
- Sint16 xpcx, xmcx, xpcy, xmcy;
- Sint16 ypcy, ymcy, ypcx, ymcx;
- Uint8 *colorptr;
- Uint8 drawoct;
- int startoct, endoct, oct, stopval_start = 0, stopval_end = 0;
- double dstart, dend, temp = 0.;
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return (0);
- }
- /*
- * Sanity check radius
- */
- if (rad < 0) {
- return (-1);
- }
- /*
- * Special case for rad=0 - draw a point
- */
- if (rad == 0) {
- return (pixelColor(dst, x, y, color));
- }
- /*
- * Get arc's circle and clipping boundary and
- * test if bounding box of circle is visible
- */
- x2 = x + rad;
- left = dst->clip_rect.x;
- if (x2 < left) {
- return (0);
- }
- x1 = x - rad;
- right = dst->clip_rect.x + dst->clip_rect.w - 1;
- if (x1 > right) {
- return (0);
- }
- y2 = y + rad;
- top = dst->clip_rect.y;
- if (y2 < top) {
- return (0);
- }
- y1 = y - rad;
- bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
- if (y1 > bottom) {
- return (0);
- }
- // Octant labelling
- //
- // \ 5 | 6 /
- // \ | /
- // 4 \ | / 7
- // \|/
- //------+------ +x
- // /|\
- // 3 / | \ 0
- // / | \
- // / 2 | 1 \
- // +y
- // Initially reset bitmask to 0x00000000
- // the set whether or not to keep drawing a given octant.
- // For example: 0x00111100 means we're drawing in octants 2-5
- drawoct = 0;
- /*
- * Fixup angles
- */
- start %= 360;
- end %= 360;
- // 0 <= start & end < 360; note that sometimes start > end - if so, arc goes back through 0.
- while (start < 0) start += 360;
- while (end < 0) end += 360;
- start %= 360;
- end %= 360;
- // now, we find which octants we're drawing in.
- startoct = start / 45;
- endoct = end / 45;
- oct = startoct - 1; // we increment as first step in loop
- // stopval_start, stopval_end;
- // what values of cx to stop at.
- do {
- oct = (oct + 1) % 8;
- if (oct == startoct) {
- // need to compute stopval_start for this octant. Look at picture above if this is unclear
- dstart = (double) start;
- switch (oct) {
- case 0:
- case 3:
- temp = sin(dstart * M_PI / 180.);
- break;
- case 1:
- case 6:
- temp = cos(dstart * M_PI / 180.);
- break;
- case 2:
- case 5:
- temp = -cos(dstart * M_PI / 180.);
- break;
- case 4:
- case 7:
- temp = -sin(dstart * M_PI / 180.);
- break;
- }
- temp *= rad;
- stopval_start = (int) temp; // always round down.
- // This isn't arbitrary, but requires graph paper to explain well.
- // The basic idea is that we're always changing drawoct after we draw, so we
- // stop immediately after we render the last sensible pixel at x = ((int)temp).
- // and whether to draw in this octant initially
- if (oct % 2)
- drawoct |= (1
- << oct); // this is basically like saying drawoct[oct] = true, if drawoct were a bool array
- else drawoct &= 255 - (1 << oct); // this is basically like saying drawoct[oct] = false
- }
- if (oct == endoct) {
- // need to compute stopval_end for this octant
- dend = (double) end;
- switch (oct) {
- case 0:
- case 3:
- temp = sin(dend * M_PI / 180);
- break;
- case 1:
- case 6:
- temp = cos(dend * M_PI / 180);
- break;
- case 2:
- case 5:
- temp = -cos(dend * M_PI / 180);
- break;
- case 4:
- case 7:
- temp = -sin(dend * M_PI / 180);
- break;
- }
- temp *= rad;
- stopval_end = (int) temp;
- // and whether to draw in this octant initially
- if (startoct == endoct) {
- // note: we start drawing, stop, then start again in this case
- // otherwise: we only draw in this octant, so initialize it to false, it will get set back to true
- if (start > end) {
- // unfortunately, if we're in the same octant and need to draw over the whole circle,
- // we need to set the rest to true, because the while loop will end at the bottom.
- drawoct = 255;
- } else {
- drawoct &= 255 - (1 << oct);
- }
- } else if (oct % 2) drawoct &= 255 - (1 << oct);
- else drawoct |= (1 << oct);
- } else if (oct != startoct) { // already verified that it's != endoct
- drawoct |= (1 << oct); // draw this entire segment
- }
- } while (oct != endoct);
- // so now we have what octants to draw and when to draw them. all that's left is the actual raster code.
- /* Lock surface */
- if (SDL_MUSTLOCK(dst)) {
- if (SDL_LockSurface(dst) < 0) {
- return (-1);
- }
- }
- /*
- * Draw arc
- */
- result = 0;
- /*
- * Alpha Check
- */
- if ((color & 255) == 255) {
- /*
- * No Alpha - direct memory writes
- */
- /*
- * Setup color
- */
- colorptr = (Uint8 *) &color;
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
- color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
- } else {
- color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
- }
- /*
- * Draw
- */
- do {
- ypcy = y + cy;
- ymcy = y - cy;
- if (cx > 0) {
- xpcx = x + cx;
- xmcx = x - cx;
- // always check if we're drawing a certain octant before adding a pixel to that octant.
- if (drawoct & 4) result |= fastPixelColorNolock(dst, xmcx, ypcy, color); // drawoct & 4 = 22; drawoct[2]
- if (drawoct & 2) result |= fastPixelColorNolock(dst, xpcx, ypcy, color);
- if (drawoct & 32) result |= fastPixelColorNolock(dst, xmcx, ymcy, color);
- if (drawoct & 64) result |= fastPixelColorNolock(dst, xpcx, ymcy, color);
- } else {
- if (drawoct & 6) result |= fastPixelColorNolock(dst, x, ypcy, color); // 4 + 2; drawoct[2] || drawoct[1]
- if (drawoct & 96) result |= fastPixelColorNolock(dst, x, ymcy, color); // 32 + 64
- }
- xpcy = x + cy;
- xmcy = x - cy;
- if (cx > 0 && cx != cy) {
- ypcx = y + cx;
- ymcx = y - cx;
- if (drawoct & 8) result |= fastPixelColorNolock(dst, xmcy, ypcx, color);
- if (drawoct & 1) result |= fastPixelColorNolock(dst, xpcy, ypcx, color);
- if (drawoct & 16) result |= fastPixelColorNolock(dst, xmcy, ymcx, color);
- if (drawoct & 128) result |= fastPixelColorNolock(dst, xpcy, ymcx, color);
- } else if (cx == 0) {
- if (drawoct & 24) result |= fastPixelColorNolock(dst, xmcy, y, color); // 8 + 16
- if (drawoct & 129) result |= fastPixelColorNolock(dst, xpcy, y, color); // 1 + 128
- }
- /*
- * Update whether we're drawing an octant
- */
- if (stopval_start == cx) {
- // works like an on-off switch because start & end may be in the same octant.
- if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);
- else drawoct |= (1 << startoct);
- }
- if (stopval_end == cx) {
- if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
- else drawoct |= (1 << endoct);
- }
- /*
- * Update pixels
- */
- if (df < 0) {
- df += d_e;
- d_e += 2;
- d_se += 2;
- } else {
- df += d_se;
- d_e += 2;
- d_se += 4;
- cy--;
- }
- cx++;
- } while (cx <= cy);
- /*
- * Unlock surface
- */
- SDL_UnlockSurface(dst);
- } else {
- /*
- * Using Alpha - blended pixel blits
- */
- do {
- ypcy = y + cy;
- ymcy = y - cy;
- if (cx > 0) {
- xpcx = x + cx;
- xmcx = x - cx;
- // always check if we're drawing a certain octant before adding a pixel to that octant.
- if (drawoct & 4) result |= pixelColorNolock(dst, xmcx, ypcy, color);
- if (drawoct & 2) result |= pixelColorNolock(dst, xpcx, ypcy, color);
- if (drawoct & 32) result |= pixelColorNolock(dst, xmcx, ymcy, color);
- if (drawoct & 64) result |= pixelColorNolock(dst, xpcx, ymcy, color);
- } else {
- if (drawoct & 96) result |= pixelColorNolock(dst, x, ymcy, color);
- if (drawoct & 6) result |= pixelColorNolock(dst, x, ypcy, color);
- }
- xpcy = x + cy;
- xmcy = x - cy;
- if (cx > 0 && cx != cy) {
- ypcx = y + cx;
- ymcx = y - cx;
- if (drawoct & 8) result |= pixelColorNolock(dst, xmcy, ypcx, color);
- if (drawoct & 1) result |= pixelColorNolock(dst, xpcy, ypcx, color);
- if (drawoct & 16) result |= pixelColorNolock(dst, xmcy, ymcx, color);
- if (drawoct & 128) result |= pixelColorNolock(dst, xpcy, ymcx, color);
- } else if (cx == 0) {
- if (drawoct & 24) result |= pixelColorNolock(dst, xmcy, y, color);
- if (drawoct & 129) result |= pixelColorNolock(dst, xpcy, y, color);
- }
- /*
- * Update whether we're drawing an octant
- */
- if (stopval_start == cx) {
- // works like an on-off switch.
- // This is just in case start & end are in the same octant.
- if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);
- else drawoct |= (1 << startoct);
- }
- if (stopval_end == cx) {
- if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
- else drawoct |= (1 << endoct);
- }
- /*
- * Update pixels
- */
- if (df < 0) {
- df += d_e;
- d_e += 2;
- d_se += 2;
- } else {
- df += d_se;
- d_e += 2;
- d_se += 4;
- cy--;
- }
- cx++;
- } while (cx <= cy);
- } /* Alpha check */
- /* Unlock surface */
- if (SDL_MUSTLOCK(dst)) {
- SDL_UnlockSurface(dst);
- }
- return (result);
- }
- /*!
- \brief Arc with blending.
- \param dst The surface to draw on.
- \param x X coordinate of the center of the arc.
- \param y Y coordinate of the center of the arc.
- \param rad Radius in pixels of the arc.
- \param start Starting radius in degrees of the arc. 0 degrees is down, increasing counterclockwise.
- \param end Ending radius in degrees of the arc. 0 degrees is down, increasing counterclockwise.
- \param r The red value of the arc to draw.
- \param g The green value of the arc to draw.
- \param b The blue value of the arc to draw.
- \param a The alpha value of the arc to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int arcRGBA(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b,
- Uint8 a) {
- /*
- * Draw
- */
- return (arcColor(dst, x, y, rad, start, end,
- ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /* ----- AA Circle */
- /*!
- \brief Draw anti-aliased circle with blending.
- Note: The AA-circle routine is based on AA-ellipse with identical radii.
- \param dst The surface to draw on.
- \param x X coordinate of the center of the aa-circle.
- \param y Y coordinate of the center of the aa-circle.
- \param rad Radius in pixels of the aa-circle.
- \param color The color value of the aa-circle to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int aacircleColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color) {
- return (aaellipseColor(dst, x, y, rad, rad, color));
- }
- /*!
- \brief Draw anti-aliased circle with blending.
- \param dst The surface to draw on.
- \param x X coordinate of the center of the aa-circle.
- \param y Y coordinate of the center of the aa-circle.
- \param rad Radius in pixels of the aa-circle.
- \param r The red value of the aa-circle to draw.
- \param g The green value of the aa-circle to draw.
- \param b The blue value of the aa-circle to draw.
- \param a The alpha value of the aa-circle to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int aacircleRGBA(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (aaellipseColor
- (dst, x, y, rad, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /* ----- Filled Circle */
- /*!
- \brief Draw filled circle with blending.
- Note: Based on algorithms from sge library with modifications by A. Schiffler for
- multiple-hline draw removal and other minor speedup changes.
- \param dst The surface to draw on.
- \param x X coordinate of the center of the filled circle.
- \param y Y coordinate of the center of the filled circle.
- \param rad Radius in pixels of the filled circle.
- \param color The color value of the filled circle to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int filledCircleColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color) {
- Sint16 left, right, top, bottom;
- int result;
- Sint16 x1, y1, x2, y2;
- Sint16 cx = 0;
- Sint16 cy = rad;
- Sint16 ocx = (Sint16) 0xffff;
- Sint16 ocy = (Sint16) 0xffff;
- Sint16 df = 1 - rad;
- Sint16 d_e = 3;
- Sint16 d_se = -2 * rad + 5;
- Sint16 xpcx, xmcx, xpcy, xmcy;
- Sint16 ypcy, ymcy, ypcx, ymcx;
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return (0);
- }
- /*
- * Sanity check radius
- */
- if (rad < 0) {
- return (-1);
- }
- /*
- * Special case for rad=0 - draw a point
- */
- if (rad == 0) {
- return (pixelColor(dst, x, y, color));
- }
- /*
- * Get circle and clipping boundary and
- * test if bounding box of circle is visible
- */
- x2 = x + rad;
- left = dst->clip_rect.x;
- if (x2 < left) {
- return (0);
- }
- x1 = x - rad;
- right = dst->clip_rect.x + dst->clip_rect.w - 1;
- if (x1 > right) {
- return (0);
- }
- y2 = y + rad;
- top = dst->clip_rect.y;
- if (y2 < top) {
- return (0);
- }
- y1 = y - rad;
- bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
- if (y1 > bottom) {
- return (0);
- }
- /*
- * Draw
- */
- result = 0;
- do {
- xpcx = x + cx;
- xmcx = x - cx;
- xpcy = x + cy;
- xmcy = x - cy;
- if (ocy != cy) {
- if (cy > 0) {
- ypcy = y + cy;
- ymcy = y - cy;
- result |= hlineColor(dst, xmcx, xpcx, ypcy, color);
- result |= hlineColor(dst, xmcx, xpcx, ymcy, color);
- } else {
- result |= hlineColor(dst, xmcx, xpcx, y, color);
- }
- ocy = cy;
- }
- if (ocx != cx) {
- if (cx != cy) {
- if (cx > 0) {
- ypcx = y + cx;
- ymcx = y - cx;
- result |= hlineColor(dst, xmcy, xpcy, ymcx, color);
- result |= hlineColor(dst, xmcy, xpcy, ypcx, color);
- } else {
- result |= hlineColor(dst, xmcy, xpcy, y, color);
- }
- }
- ocx = cx;
- }
- /*
- * Update
- */
- if (df < 0) {
- df += d_e;
- d_e += 2;
- d_se += 2;
- } else {
- df += d_se;
- d_e += 2;
- d_se += 4;
- cy--;
- }
- cx++;
- } while (cx <= cy);
- return (result);
- }
- /*!
- \brief Draw filled circle with blending.
- \param dst The surface to draw on.
- \param x X coordinate of the center of the filled circle.
- \param y Y coordinate of the center of the filled circle.
- \param rad Radius in pixels of the filled circle.
- \param r The red value of the filled circle to draw.
- \param g The green value of the filled circle to draw.
- \param b The blue value of the filled circle to draw.
- \param a The alpha value of the filled circle to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int filledCircleRGBA(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (filledCircleColor
- (dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /* ----- Ellipse */
- /*!
- \brief Draw ellipse with blending.
- Note: Based on algorithms from sge library with modifications by A. Schiffler for
- multiple-pixel draw removal and other minor speedup changes.
- \param dst The surface to draw on.
- \param x X coordinate of the center of the ellipse.
- \param y Y coordinate of the center of the ellipse.
- \param rx Horizontal radius in pixels of the ellipse.
- \param ry Vertical radius in pixels of the ellipse.
- \param color The color value of the ellipse to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int ellipseColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color) {
- Sint16 left, right, top, bottom;
- int result;
- Sint16 x1, y1, x2, y2;
- int ix, iy;
- int h, i, j, k;
- int oh, oi, oj, ok;
- int xmh, xph, ypk, ymk;
- int xmi, xpi, ymj, ypj;
- int xmj, xpj, ymi, ypi;
- int xmk, xpk, ymh, yph;
- Uint8 *colorptr;
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return (0);
- }
- /*
- * Sanity check radii
- */
- if ((rx < 0) || (ry < 0)) {
- return (-1);
- }
- /*
- * Special case for rx=0 - draw a vline
- */
- if (rx == 0) {
- return (vlineColor(dst, x, y - ry, y + ry, color));
- }
- /*
- * Special case for ry=0 - draw a hline
- */
- if (ry == 0) {
- return (hlineColor(dst, x - rx, x + rx, y, color));
- }
- /*
- * Get circle and clipping boundary and
- * test if bounding box of circle is visible
- */
- x2 = x + rx;
- left = dst->clip_rect.x;
- if (x2 < left) {
- return (0);
- }
- x1 = x - rx;
- right = dst->clip_rect.x + dst->clip_rect.w - 1;
- if (x1 > right) {
- return (0);
- }
- y2 = y + ry;
- top = dst->clip_rect.y;
- if (y2 < top) {
- return (0);
- }
- y1 = y - ry;
- bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
- if (y1 > bottom) {
- return (0);
- }
- /*
- * Init vars
- */
- oh = oi = oj = ok = 0xFFFF;
- /*
- * Draw
- */
- result = 0;
- /* Lock surface */
- if (SDL_MUSTLOCK(dst)) {
- if (SDL_LockSurface(dst) < 0) {
- return (-1);
- }
- }
- /*
- * Check alpha
- */
- if ((color & 255) == 255) {
- /*
- * No Alpha - direct memory writes
- */
- /*
- * Setup color
- */
- colorptr = (Uint8 *) &color;
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
- color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
- } else {
- color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
- }
- if (rx > ry) {
- ix = 0;
- iy = rx * 64;
- do {
- h = (ix + 32) >> 6;
- i = (iy + 32) >> 6;
- j = (h * ry) / rx;
- k = (i * ry) / rx;
- if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
- xph = x + h;
- xmh = x - h;
- if (k > 0) {
- ypk = y + k;
- ymk = y - k;
- result |= fastPixelColorNolock(dst, xmh, ypk, color);
- result |= fastPixelColorNolock(dst, xph, ypk, color);
- result |= fastPixelColorNolock(dst, xmh, ymk, color);
- result |= fastPixelColorNolock(dst, xph, ymk, color);
- } else {
- result |= fastPixelColorNolock(dst, xmh, y, color);
- result |= fastPixelColorNolock(dst, xph, y, color);
- }
- ok = k;
- xpi = x + i;
- xmi = x - i;
- if (j > 0) {
- ypj = y + j;
- ymj = y - j;
- result |= fastPixelColorNolock(dst, xmi, ypj, color);
- result |= fastPixelColorNolock(dst, xpi, ypj, color);
- result |= fastPixelColorNolock(dst, xmi, ymj, color);
- result |= fastPixelColorNolock(dst, xpi, ymj, color);
- } else {
- result |= fastPixelColorNolock(dst, xmi, y, color);
- result |= fastPixelColorNolock(dst, xpi, y, color);
- }
- oj = j;
- }
- ix = ix + iy / rx;
- iy = iy - ix / rx;
- } while (i > h);
- } else {
- ix = 0;
- iy = ry * 64;
- do {
- h = (ix + 32) >> 6;
- i = (iy + 32) >> 6;
- j = (h * rx) / ry;
- k = (i * rx) / ry;
- if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
- xmj = x - j;
- xpj = x + j;
- if (i > 0) {
- ypi = y + i;
- ymi = y - i;
- result |= fastPixelColorNolock(dst, xmj, ypi, color);
- result |= fastPixelColorNolock(dst, xpj, ypi, color);
- result |= fastPixelColorNolock(dst, xmj, ymi, color);
- result |= fastPixelColorNolock(dst, xpj, ymi, color);
- } else {
- result |= fastPixelColorNolock(dst, xmj, y, color);
- result |= fastPixelColorNolock(dst, xpj, y, color);
- }
- oi = i;
- xmk = x - k;
- xpk = x + k;
- if (h > 0) {
- yph = y + h;
- ymh = y - h;
- result |= fastPixelColorNolock(dst, xmk, yph, color);
- result |= fastPixelColorNolock(dst, xpk, yph, color);
- result |= fastPixelColorNolock(dst, xmk, ymh, color);
- result |= fastPixelColorNolock(dst, xpk, ymh, color);
- } else {
- result |= fastPixelColorNolock(dst, xmk, y, color);
- result |= fastPixelColorNolock(dst, xpk, y, color);
- }
- oh = h;
- }
- ix = ix + iy / ry;
- iy = iy - ix / ry;
- } while (i > h);
- }
- } else {
- if (rx > ry) {
- ix = 0;
- iy = rx * 64;
- do {
- h = (ix + 32) >> 6;
- i = (iy + 32) >> 6;
- j = (h * ry) / rx;
- k = (i * ry) / rx;
- if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
- xph = x + h;
- xmh = x - h;
- if (k > 0) {
- ypk = y + k;
- ymk = y - k;
- result |= pixelColorNolock(dst, xmh, ypk, color);
- result |= pixelColorNolock(dst, xph, ypk, color);
- result |= pixelColorNolock(dst, xmh, ymk, color);
- result |= pixelColorNolock(dst, xph, ymk, color);
- } else {
- result |= pixelColorNolock(dst, xmh, y, color);
- result |= pixelColorNolock(dst, xph, y, color);
- }
- ok = k;
- xpi = x + i;
- xmi = x - i;
- if (j > 0) {
- ypj = y + j;
- ymj = y - j;
- result |= pixelColorNolock(dst, xmi, ypj, color);
- result |= pixelColorNolock(dst, xpi, ypj, color);
- result |= pixelColorNolock(dst, xmi, ymj, color);
- result |= pixelColor(dst, xpi, ymj, color);
- } else {
- result |= pixelColorNolock(dst, xmi, y, color);
- result |= pixelColorNolock(dst, xpi, y, color);
- }
- oj = j;
- }
- ix = ix + iy / rx;
- iy = iy - ix / rx;
- } while (i > h);
- } else {
- ix = 0;
- iy = ry * 64;
- do {
- h = (ix + 32) >> 6;
- i = (iy + 32) >> 6;
- j = (h * rx) / ry;
- k = (i * rx) / ry;
- if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
- xmj = x - j;
- xpj = x + j;
- if (i > 0) {
- ypi = y + i;
- ymi = y - i;
- result |= pixelColorNolock(dst, xmj, ypi, color);
- result |= pixelColorNolock(dst, xpj, ypi, color);
- result |= pixelColorNolock(dst, xmj, ymi, color);
- result |= pixelColorNolock(dst, xpj, ymi, color);
- } else {
- result |= pixelColorNolock(dst, xmj, y, color);
- result |= pixelColorNolock(dst, xpj, y, color);
- }
- oi = i;
- xmk = x - k;
- xpk = x + k;
- if (h > 0) {
- yph = y + h;
- ymh = y - h;
- result |= pixelColorNolock(dst, xmk, yph, color);
- result |= pixelColorNolock(dst, xpk, yph, color);
- result |= pixelColorNolock(dst, xmk, ymh, color);
- result |= pixelColorNolock(dst, xpk, ymh, color);
- } else {
- result |= pixelColorNolock(dst, xmk, y, color);
- result |= pixelColorNolock(dst, xpk, y, color);
- }
- oh = h;
- }
- ix = ix + iy / ry;
- iy = iy - ix / ry;
- } while (i > h);
- }
- } /* Alpha check */
- /* Unlock surface */
- if (SDL_MUSTLOCK(dst)) {
- SDL_UnlockSurface(dst);
- }
- return (result);
- }
- /*!
- \brief Draw ellipse with blending.
- \param dst The surface to draw on.
- \param x X coordinate of the center of the ellipse.
- \param y Y coordinate of the center of the ellipse.
- \param rx Horizontal radius in pixels of the ellipse.
- \param ry Vertical radius in pixels of the ellipse.
- \param r The red value of the ellipse to draw.
- \param g The green value of the ellipse to draw.
- \param b The blue value of the ellipse to draw.
- \param a The alpha value of the ellipse to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int ellipseRGBA(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (ellipseColor(dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /* ----- AA Ellipse */
- /* Windows targets do not have lrint, so provide a local inline version */
- #if defined(_MSC_VER)
- /* Detect 64bit and use intrinsic version */
- #ifdef _M_X64
- #include <emmintrin.h>
- static __inline long
- lrint(float f)
- {
- return _mm_cvtss_si32(_mm_load_ss(&f));
- }
- #elif defined(_M_IX86)
- __inline long int
- lrint (double flt)
- {
- int intgr;
- _asm
- {
- fld flt
- fistp intgr
- };
- return intgr;
- }
- #elif defined(_M_ARM)
- #include <armintr.h>
- #pragma warning(push)
- #pragma warning(disable: 4716)
- __declspec(naked) long int
- lrint (double flt)
- {
- __emit(0xEC410B10); // fmdrr d0, r0, r1
- __emit(0xEEBD0B40); // ftosid s0, d0
- __emit(0xEE100A10); // fmrs r0, s0
- __emit(0xE12FFF1E); // bx lr
- }
- #pragma warning(pop)
- #else
- #error lrint needed for MSVC on non X86/AMD64/ARM targets.
- #endif
- #endif
- /*!
- \brief Draw anti-aliased ellipse with blending.
- Note: Based on code from Anders Lindstroem, which is based on code from sge library,
- which is based on code from TwinLib.
- \param dst The surface to draw on.
- \param x X coordinate of the center of the aa-ellipse.
- \param y Y coordinate of the center of the aa-ellipse.
- \param rx Horizontal radius in pixels of the aa-ellipse.
- \param ry Vertical radius in pixels of the aa-ellipse.
- \param color The color value of the aa-ellipse to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int aaellipseColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color) {
- Sint16 left, right, top, bottom;
- Sint16 x1, y1, x2, y2;
- int i;
- int a2, b2, ds, dt, dxt, t, s, d;
- Sint16 xp, yp, xs, ys, dyt, od, xx, yy, xc2, yc2;
- float cp;
- double sab;
- Uint8 weight, iweight;
- int result;
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return (0);
- }
- /*
- * Sanity check radii
- */
- if ((rx < 0) || (ry < 0)) {
- return (-1);
- }
- /*
- * Special case for rx=0 - draw a vline
- */
- if (rx == 0) {
- return (vlineColor(dst, x, y - ry, y + ry, color));
- }
- /*
- * Special case for ry=0 - draw an hline
- */
- if (ry == 0) {
- return (hlineColor(dst, x - rx, x + rx, y, color));
- }
- /*
- * Get circle and clipping boundary and
- * test if bounding box of circle is visible
- */
- x2 = x + rx;
- left = dst->clip_rect.x;
- if (x2 < left) {
- return (0);
- }
- x1 = x - rx;
- right = dst->clip_rect.x + dst->clip_rect.w - 1;
- if (x1 > right) {
- return (0);
- }
- y2 = y + ry;
- top = dst->clip_rect.y;
- if (y2 < top) {
- return (0);
- }
- y1 = y - ry;
- bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
- if (y1 > bottom) {
- return (0);
- }
- /* Variable setup */
- a2 = rx * rx;
- b2 = ry * ry;
- ds = 2 * a2;
- dt = 2 * b2;
- xc2 = 2 * x;
- yc2 = 2 * y;
- sab = sqrt((double) (a2 + b2));
- od = (Sint16) lrint(sab * 0.01) + 1; /* introduce some overdraw */
- dxt = (Sint16) lrint((double) a2 / sab) + od;
- t = 0;
- s = -2 * a2 * ry;
- d = 0;
- xp = x;
- yp = y - ry;
- /* Lock surface */
- if (SDL_MUSTLOCK(dst)) {
- if (SDL_LockSurface(dst) < 0) {
- return (-1);
- }
- }
- /* Draw */
- result = 0;
- /* "End points" */
- result |= pixelColorNolock(dst, xp, yp, color);
- result |= pixelColorNolock(dst, xc2 - xp, yp, color);
- result |= pixelColorNolock(dst, xp, yc2 - yp, color);
- result |= pixelColorNolock(dst, xc2 - xp, yc2 - yp, color);
- for (i = 1; i <= dxt; i++) {
- xp--;
- d += t - b2;
- if (d >= 0)
- ys = yp - 1;
- else if ((d - s - a2) > 0) {
- if ((2 * d - s - a2) >= 0)
- ys = yp + 1;
- else {
- ys = yp;
- yp++;
- d -= s + a2;
- s += ds;
- }
- } else {
- yp++;
- ys = yp + 1;
- d -= s + a2;
- s += ds;
- }
- t -= dt;
- /* Calculate alpha */
- if (s != 0) {
- cp = (float) abs(d) / (float) abs(s);
- if (cp > 1.0) {
- cp = 1.0;
- }
- } else {
- cp = 1.0;
- }
- /* Calculate weights */
- weight = (Uint8) (cp * 255);
- iweight = 255 - weight;
- /* Upper half */
- xx = xc2 - xp;
- result |= pixelColorWeightNolock(dst, xp, yp, color, iweight);
- result |= pixelColorWeightNolock(dst, xx, yp, color, iweight);
- result |= pixelColorWeightNolock(dst, xp, ys, color, weight);
- result |= pixelColorWeightNolock(dst, xx, ys, color, weight);
- /* Lower half */
- yy = yc2 - yp;
- result |= pixelColorWeightNolock(dst, xp, yy, color, iweight);
- result |= pixelColorWeightNolock(dst, xx, yy, color, iweight);
- yy = yc2 - ys;
- result |= pixelColorWeightNolock(dst, xp, yy, color, weight);
- result |= pixelColorWeightNolock(dst, xx, yy, color, weight);
- }
- /* Replaces original approximation code dyt = abs(yp - yc); */
- dyt = (Sint16) lrint((double) b2 / sab) + od;
- for (i = 1; i <= dyt; i++) {
- yp++;
- d -= s + a2;
- if (d <= 0)
- xs = xp + 1;
- else if ((d + t - b2) < 0) {
- if ((2 * d + t - b2) <= 0)
- xs = xp - 1;
- else {
- xs = xp;
- xp--;
- d += t - b2;
- t -= dt;
- }
- } else {
- xp--;
- xs = xp - 1;
- d += t - b2;
- t -= dt;
- }
- s += ds;
- /* Calculate alpha */
- if (t != 0) {
- cp = (float) abs(d) / (float) abs(t);
- if (cp > 1.0) {
- cp = 1.0;
- }
- } else {
- cp = 1.0;
- }
- /* Calculate weight */
- weight = (Uint8) (cp * 255);
- iweight = 255 - weight;
- /* Left half */
- xx = xc2 - xp;
- yy = yc2 - yp;
- result |= pixelColorWeightNolock(dst, xp, yp, color, iweight);
- result |= pixelColorWeightNolock(dst, xx, yp, color, iweight);
- result |= pixelColorWeightNolock(dst, xp, yy, color, iweight);
- result |= pixelColorWeightNolock(dst, xx, yy, color, iweight);
- /* Right half */
- xx = xc2 - xs;
- result |= pixelColorWeightNolock(dst, xs, yp, color, weight);
- result |= pixelColorWeightNolock(dst, xx, yp, color, weight);
- result |= pixelColorWeightNolock(dst, xs, yy, color, weight);
- result |= pixelColorWeightNolock(dst, xx, yy, color, weight);
- }
- /* Unlock surface */
- if (SDL_MUSTLOCK(dst)) {
- SDL_UnlockSurface(dst);
- }
- return (result);
- }
- /*!
- \brief Draw anti-aliased ellipse with blending.
- \param dst The surface to draw on.
- \param x X coordinate of the center of the aa-ellipse.
- \param y Y coordinate of the center of the aa-ellipse.
- \param rx Horizontal radius in pixels of the aa-ellipse.
- \param ry Vertical radius in pixels of the aa-ellipse.
- \param r The red value of the aa-ellipse to draw.
- \param g The green value of the aa-ellipse to draw.
- \param b The blue value of the aa-ellipse to draw.
- \param a The alpha value of the aa-ellipse to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int aaellipseRGBA(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (aaellipseColor
- (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /* ---- Filled Ellipse */
- /* Note: */
- /* Based on algorithm from sge library with multiple-hline draw removal */
- /* and other speedup changes. */
- /*!
- \brief Draw filled ellipse with blending.
- Note: Based on algorithm from sge library with multiple-hline draw removal
- and other speedup changes.
- \param dst The surface to draw on.
- \param x X coordinate of the center of the filled ellipse.
- \param y Y coordinate of the center of the filled ellipse.
- \param rx Horizontal radius in pixels of the filled ellipse.
- \param ry Vertical radius in pixels of the filled ellipse.
- \param color The color value of the filled ellipse to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int filledEllipseColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color) {
- Sint16 left, right, top, bottom;
- int result;
- Sint16 x1, y1, x2, y2;
- int ix, iy;
- int h, i, j, k;
- int oh, oi, oj, ok;
- int xmh, xph;
- int xmi, xpi;
- int xmj, xpj;
- int xmk, xpk;
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return (0);
- }
- /*
- * Sanity check radii
- */
- if ((rx < 0) || (ry < 0)) {
- return (-1);
- }
- /*
- * Special case for rx=0 - draw a vline
- */
- if (rx == 0) {
- return (vlineColor(dst, x, y - ry, y + ry, color));
- }
- /*
- * Special case for ry=0 - draw a hline
- */
- if (ry == 0) {
- return (hlineColor(dst, x - rx, x + rx, y, color));
- }
- /*
- * Get circle and clipping boundary and
- * test if bounding box of circle is visible
- */
- x2 = x + rx;
- left = dst->clip_rect.x;
- if (x2 < left) {
- return (0);
- }
- x1 = x - rx;
- right = dst->clip_rect.x + dst->clip_rect.w - 1;
- if (x1 > right) {
- return (0);
- }
- y2 = y + ry;
- top = dst->clip_rect.y;
- if (y2 < top) {
- return (0);
- }
- y1 = y - ry;
- bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
- if (y1 > bottom) {
- return (0);
- }
- /*
- * Init vars
- */
- oh = oi = oj = ok = 0xFFFF;
- /*
- * Draw
- */
- result = 0;
- if (rx > ry) {
- ix = 0;
- iy = rx * 64;
- do {
- h = (ix + 32) >> 6;
- i = (iy + 32) >> 6;
- j = (h * ry) / rx;
- k = (i * ry) / rx;
- if ((ok != k) && (oj != k)) {
- xph = x + h;
- xmh = x - h;
- if (k > 0) {
- result |= hlineColor(dst, xmh, xph, y + k, color);
- result |= hlineColor(dst, xmh, xph, y - k, color);
- } else {
- result |= hlineColor(dst, xmh, xph, y, color);
- }
- ok = k;
- }
- if ((oj != j) && (ok != j) && (k != j)) {
- xmi = x - i;
- xpi = x + i;
- if (j > 0) {
- result |= hlineColor(dst, xmi, xpi, y + j, color);
- result |= hlineColor(dst, xmi, xpi, y - j, color);
- } else {
- result |= hlineColor(dst, xmi, xpi, y, color);
- }
- oj = j;
- }
- ix = ix + iy / rx;
- iy = iy - ix / rx;
- } while (i > h);
- } else {
- ix = 0;
- iy = ry * 64;
- do {
- h = (ix + 32) >> 6;
- i = (iy + 32) >> 6;
- j = (h * rx) / ry;
- k = (i * rx) / ry;
- if ((oi != i) && (oh != i)) {
- xmj = x - j;
- xpj = x + j;
- if (i > 0) {
- result |= hlineColor(dst, xmj, xpj, y + i, color);
- result |= hlineColor(dst, xmj, xpj, y - i, color);
- } else {
- result |= hlineColor(dst, xmj, xpj, y, color);
- }
- oi = i;
- }
- if ((oh != h) && (oi != h) && (i != h)) {
- xmk = x - k;
- xpk = x + k;
- if (h > 0) {
- result |= hlineColor(dst, xmk, xpk, y + h, color);
- result |= hlineColor(dst, xmk, xpk, y - h, color);
- } else {
- result |= hlineColor(dst, xmk, xpk, y, color);
- }
- oh = h;
- }
- ix = ix + iy / ry;
- iy = iy - ix / ry;
- } while (i > h);
- }
- return (result);
- }
- /*!
- \brief Draw filled ellipse with blending.
- \param dst The surface to draw on.
- \param x X coordinate of the center of the filled ellipse.
- \param y Y coordinate of the center of the filled ellipse.
- \param rx Horizontal radius in pixels of the filled ellipse.
- \param ry Vertical radius in pixels of the filled ellipse.
- \param r The red value of the filled ellipse to draw.
- \param g The green value of the filled ellipse to draw.
- \param b The blue value of the filled ellipse to draw.
- \param a The alpha value of the filled ellipse to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int filledEllipseRGBA(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (filledEllipseColor
- (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /* ----- pie */
- /*!
- \brief Internal float (low-speed) pie-calc implementation by drawing polygons.
- Note: Determines vertex array and uses polygon or filledPolygon drawing routines to render.
- \param dst The surface to draw on.
- \param x X coordinate of the center of the pie.
- \param y Y coordinate of the center of the pie.
- \param rad Radius in pixels of the pie.
- \param start Starting radius in degrees of the pie.
- \param end Ending radius in degrees of the pie.
- \param color The color value of the pie to draw (0xRRGGBBAA).
- \param filled Flag indicating if the pie should be filled (=1) or not (=0).
- \returns Returns 0 on success, -1 on failure.
- */
- int _pieColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color, Uint8 filled) {
- Sint16 left, right, top, bottom;
- Sint16 x1, y1, x2, y2;
- int result;
- double angle, start_angle, end_angle;
- double deltaAngle;
- double dr;
- int numpoints, i;
- Sint16 *vx, *vy;
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return (0);
- }
- /*
- * Sanity check radii
- */
- if (rad < 0) {
- return (-1);
- }
- /*
- * Fixup angles
- */
- start = start % 360;
- end = end % 360;
- /*
- * Special case for rad=0 - draw a point
- */
- if (rad == 0) {
- return (pixelColor(dst, x, y, color));
- }
- /*
- * Clip against circle, not pie (not 100% optimal).
- * Get pie's circle and clipping boundary and
- * test if bounding box of circle is visible
- */
- x2 = x + rad;
- left = dst->clip_rect.x;
- if (x2 < left) {
- return (0);
- }
- x1 = x - rad;
- right = dst->clip_rect.x + dst->clip_rect.w - 1;
- if (x1 > right) {
- return (0);
- }
- y2 = y + rad;
- top = dst->clip_rect.y;
- if (y2 < top) {
- return (0);
- }
- y1 = y - rad;
- bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
- if (y1 > bottom) {
- return (0);
- }
- /*
- * Variable setup
- */
- dr = (double) rad;
- deltaAngle = 3.0 / dr;
- start_angle = (double) start * (2.0 * M_PI / 360.0);
- end_angle = (double) end * (2.0 * M_PI / 360.0);
- if (start > end) {
- end_angle += (2.0 * M_PI);
- }
- /* We will always have at least 2 points */
- numpoints = 2;
- /* Count points (rather than calculating it) */
- angle = start_angle;
- while (angle < end_angle) {
- angle += deltaAngle;
- numpoints++;
- }
- /* Allocate combined vertex array */
- vx = vy = (Sint16 *) malloc(2 * sizeof(Uint16) * numpoints);
- if (vx == NULL) {
- return (-1);
- }
- /* Update point to start of vy */
- vy += numpoints;
- /* Center */
- vx[0] = x;
- vy[0] = y;
- /* First vertex */
- angle = start_angle;
- vx[1] = x + (int) (dr * cos(angle));
- vy[1] = y + (int) (dr * sin(angle));
- if (numpoints < 3) {
- result = lineColor(dst, vx[0], vy[0], vx[1], vy[1], color);
- } else {
- /* Calculate other vertices */
- i = 2;
- angle = start_angle;
- while (angle < end_angle) {
- angle += deltaAngle;
- if (angle > end_angle) {
- angle = end_angle;
- }
- vx[i] = x + (int) (dr * cos(angle));
- vy[i] = y + (int) (dr * sin(angle));
- i++;
- }
- /* Draw */
- if (filled) {
- result = filledPolygonColor(dst, vx, vy, numpoints, color);
- } else {
- result = polygonColor(dst, vx, vy, numpoints, color);
- }
- }
- /* Free combined vertex array */
- free(vx);
- return (result);
- }
- /*!
- \brief Draw pie (outline) with alpha blending.
- \param dst The surface to draw on.
- \param x X coordinate of the center of the pie.
- \param y Y coordinate of the center of the pie.
- \param rad Radius in pixels of the pie.
- \param start Starting radius in degrees of the pie.
- \param end Ending radius in degrees of the pie.
- \param color The color value of the pie to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int pieColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad,
- Sint16 start, Sint16 end, Uint32 color) {
- return (_pieColor(dst, x, y, rad, start, end, color, 0));
- }
- /*!
- \brief Draw pie (outline) with alpha blending.
- \param dst The surface to draw on.
- \param x X coordinate of the center of the pie.
- \param y Y coordinate of the center of the pie.
- \param rad Radius in pixels of the pie.
- \param start Starting radius in degrees of the pie.
- \param end Ending radius in degrees of the pie.
- \param r The red value of the pie to draw.
- \param g The green value of the pie to draw.
- \param b The blue value of the pie to draw.
- \param a The alpha value of the pie to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int pieRGBA(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad,
- Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- return (_pieColor(dst, x, y, rad, start, end,
- ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 0));
- }
- /*!
- \brief Draw filled pie with alpha blending.
- \param dst The surface to draw on.
- \param x X coordinate of the center of the filled pie.
- \param y Y coordinate of the center of the filled pie.
- \param rad Radius in pixels of the filled pie.
- \param start Starting radius in degrees of the filled pie.
- \param end Ending radius in degrees of the filled pie.
- \param color The color value of the filled pie to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int filledPieColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color) {
- return (_pieColor(dst, x, y, rad, start, end, color, 1));
- }
- /*!
- \brief Draw filled pie with alpha blending.
- \param dst The surface to draw on.
- \param x X coordinate of the center of the filled pie.
- \param y Y coordinate of the center of the filled pie.
- \param rad Radius in pixels of the filled pie.
- \param start Starting radius in degrees of the filled pie.
- \param end Ending radius in degrees of the filled pie.
- \param r The red value of the filled pie to draw.
- \param g The green value of the filled pie to draw.
- \param b The blue value of the filled pie to draw.
- \param a The alpha value of the filled pie to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int filledPieRGBA(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad,
- Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- return (_pieColor(dst, x, y, rad, start, end,
- ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1));
- }
- /* ------ Trigon */
- /*!
- \brief Draw trigon (triangle outline) with alpha blending.
- Note: Creates vertex array and uses polygon routine to render.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point of the trigon.
- \param y1 Y coordinate of the first point of the trigon.
- \param x2 X coordinate of the second point of the trigon.
- \param y2 Y coordinate of the second point of the trigon.
- \param x3 X coordinate of the third point of the trigon.
- \param y3 Y coordinate of the third point of the trigon.
- \param color The color value of the trigon to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int trigonColor(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color) {
- Sint16 vx[3];
- Sint16 vy[3];
- vx[0] = x1;
- vx[1] = x2;
- vx[2] = x3;
- vy[0] = y1;
- vy[1] = y2;
- vy[2] = y3;
- return (polygonColor(dst, vx, vy, 3, color));
- }
- /*!
- \brief Draw trigon (triangle outline) with alpha blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point of the trigon.
- \param y1 Y coordinate of the first point of the trigon.
- \param x2 X coordinate of the second point of the trigon.
- \param y2 Y coordinate of the second point of the trigon.
- \param x3 X coordinate of the third point of the trigon.
- \param y3 Y coordinate of the third point of the trigon.
- \param r The red value of the trigon to draw.
- \param g The green value of the trigon to draw.
- \param b The blue value of the trigon to draw.
- \param a The alpha value of the trigon to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int trigonRGBA(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
- Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- Sint16 vx[3];
- Sint16 vy[3];
- vx[0] = x1;
- vx[1] = x2;
- vx[2] = x3;
- vy[0] = y1;
- vy[1] = y2;
- vy[2] = y3;
- return (polygonRGBA(dst, vx, vy, 3, r, g, b, a));
- }
- /* ------ AA-Trigon */
- /*!
- \brief Draw anti-aliased trigon (triangle outline) with alpha blending.
- Note: Creates vertex array and uses aapolygon routine to render.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point of the aa-trigon.
- \param y1 Y coordinate of the first point of the aa-trigon.
- \param x2 X coordinate of the second point of the aa-trigon.
- \param y2 Y coordinate of the second point of the aa-trigon.
- \param x3 X coordinate of the third point of the aa-trigon.
- \param y3 Y coordinate of the third point of the aa-trigon.
- \param color The color value of the aa-trigon to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int aatrigonColor(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color) {
- Sint16 vx[3];
- Sint16 vy[3];
- vx[0] = x1;
- vx[1] = x2;
- vx[2] = x3;
- vy[0] = y1;
- vy[1] = y2;
- vy[2] = y3;
- return (aapolygonColor(dst, vx, vy, 3, color));
- }
- /*!
- \brief Draw anti-aliased trigon (triangle outline) with alpha blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point of the aa-trigon.
- \param y1 Y coordinate of the first point of the aa-trigon.
- \param x2 X coordinate of the second point of the aa-trigon.
- \param y2 Y coordinate of the second point of the aa-trigon.
- \param x3 X coordinate of the third point of the aa-trigon.
- \param y3 Y coordinate of the third point of the aa-trigon.
- \param r The red value of the aa-trigon to draw.
- \param g The green value of the aa-trigon to draw.
- \param b The blue value of the aa-trigon to draw.
- \param a The alpha value of the aa-trigon to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int aatrigonRGBA(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
- Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- Sint16 vx[3];
- Sint16 vy[3];
- vx[0] = x1;
- vx[1] = x2;
- vx[2] = x3;
- vy[0] = y1;
- vy[1] = y2;
- vy[2] = y3;
- return (aapolygonRGBA(dst, vx, vy, 3, r, g, b, a));
- }
- /* ------ Filled Trigon */
- /*!
- \brief Draw filled trigon (triangle) with alpha blending.
- Note: Creates vertex array and uses aapolygon routine to render.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point of the filled trigon.
- \param y1 Y coordinate of the first point of the filled trigon.
- \param x2 X coordinate of the second point of the filled trigon.
- \param y2 Y coordinate of the second point of the filled trigon.
- \param x3 X coordinate of the third point of the filled trigon.
- \param y3 Y coordinate of the third point of the filled trigon.
- \param color The color value of the filled trigon to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int
- filledTrigonColor(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color) {
- Sint16 vx[3];
- Sint16 vy[3];
- vx[0] = x1;
- vx[1] = x2;
- vx[2] = x3;
- vy[0] = y1;
- vy[1] = y2;
- vy[2] = y3;
- return (filledPolygonColor(dst, vx, vy, 3, color));
- }
- /*!
- \brief Draw filled trigon (triangle) with alpha blending.
- Note: Creates vertex array and uses aapolygon routine to render.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point of the filled trigon.
- \param y1 Y coordinate of the first point of the filled trigon.
- \param x2 X coordinate of the second point of the filled trigon.
- \param y2 Y coordinate of the second point of the filled trigon.
- \param x3 X coordinate of the third point of the filled trigon.
- \param y3 Y coordinate of the third point of the filled trigon.
- \param r The red value of the filled trigon to draw.
- \param g The green value of the filled trigon to draw.
- \param b The blue value of the filled trigon to draw.
- \param a The alpha value of the filled trigon to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int filledTrigonRGBA(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
- Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- Sint16 vx[3];
- Sint16 vy[3];
- vx[0] = x1;
- vx[1] = x2;
- vx[2] = x3;
- vy[0] = y1;
- vy[1] = y2;
- vy[2] = y3;
- return (filledPolygonRGBA(dst, vx, vy, 3, r, g, b, a));
- }
- /* ---- Polygon */
- /*!
- \brief Draw polygon with alpha blending.
- \param dst The surface to draw on.
- \param vx Vertex array containing X coordinates of the points of the polygon.
- \param vy Vertex array containing Y coordinates of the points of the polygon.
- \param n Number of points in the vertex array. Minimum number is 3.
- \param color The color value of the polygon to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int polygonColor(SDL_Surface *dst, const Sint16 *vx, const Sint16 *vy, int n, Uint32 color) {
- int result;
- int i;
- const Sint16 *x1, *y1, *x2, *y2;
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return (0);
- }
- /*
- * Vertex array NULL check
- */
- if (vx == NULL) {
- return (-1);
- }
- if (vy == NULL) {
- return (-1);
- }
- /*
- * Sanity check
- */
- if (n < 3) {
- return (-1);
- }
- /*
- * Pointer setup
- */
- x1 = x2 = vx;
- y1 = y2 = vy;
- x2++;
- y2++;
- /*
- * Draw
- */
- result = 0;
- for (i = 1; i < n; i++) {
- result |= lineColor(dst, *x1, *y1, *x2, *y2, color);
- x1 = x2;
- y1 = y2;
- x2++;
- y2++;
- }
- result |= lineColor(dst, *x1, *y1, *vx, *vy, color);
- return (result);
- }
- /*!
- \brief Draw polygon with alpha blending.
- \param dst The surface to draw on.
- \param vx Vertex array containing X coordinates of the points of the polygon.
- \param vy Vertex array containing Y coordinates of the points of the polygon.
- \param n Number of points in the vertex array. Minimum number is 3.
- \param r The red value of the polygon to draw.
- \param g The green value of the polygon to draw.
- \param b The blue value of the polygon to draw.
- \param a The alpha value of the polygon to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int polygonRGBA(SDL_Surface *dst, const Sint16 *vx, const Sint16 *vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (polygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /* ---- AA-Polygon */
- /*!
- \brief Draw anti-aliased polygon with alpha blending.
- \param dst The surface to draw on.
- \param vx Vertex array containing X coordinates of the points of the aa-polygon.
- \param vy Vertex array containing Y coordinates of the points of the aa-polygon.
- \param n Number of points in the vertex array. Minimum number is 3.
- \param color The color value of the aa-polygon to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int aapolygonColor(SDL_Surface *dst, const Sint16 *vx, const Sint16 *vy, int n, Uint32 color) {
- int result;
- int i;
- const Sint16 *x1, *y1, *x2, *y2;
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return (0);
- }
- /*
- * Vertex array NULL check
- */
- if (vx == NULL) {
- return (-1);
- }
- if (vy == NULL) {
- return (-1);
- }
- /*
- * Sanity check
- */
- if (n < 3) {
- return (-1);
- }
- /*
- * Pointer setup
- */
- x1 = x2 = vx;
- y1 = y2 = vy;
- x2++;
- y2++;
- /*
- * Draw
- */
- result = 0;
- for (i = 1; i < n; i++) {
- result |= _aalineColor(dst, *x1, *y1, *x2, *y2, color, 0);
- x1 = x2;
- y1 = y2;
- x2++;
- y2++;
- }
- result |= _aalineColor(dst, *x1, *y1, *vx, *vy, color, 0);
- return (result);
- }
- /*!
- \brief Draw anti-aliased polygon with alpha blending.
- \param dst The surface to draw on.
- \param vx Vertex array containing X coordinates of the points of the aa-polygon.
- \param vy Vertex array containing Y coordinates of the points of the aa-polygon.
- \param n Number of points in the vertex array. Minimum number is 3.
- \param r The red value of the aa-polygon to draw.
- \param g The green value of the aa-polygon to draw.
- \param b The blue value of the aa-polygon to draw.
- \param a The alpha value of the aa-polygon to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int aapolygonRGBA(SDL_Surface *dst, const Sint16 *vx, const Sint16 *vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (aapolygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /* ---- Filled Polygon */
- /*!
- \brief Internal helper qsort callback functions used in filled polygon drawing.
- \param a The surface to draw on.
- \param b Vertex array containing X coordinates of the points of the polygon.
- \returns Returns 0 if a==b, a negative number if a<b or a positive number if a>b.
- */
- int _gfxPrimitivesCompareInt(const void *a, const void *b) {
- return (*(const int *) a) - (*(const int *) b);
- }
- /*!
- \brief Global vertex array to use if optional parameters are not given in filledPolygonMT calls.
- Note: Used for non-multithreaded (default) operation of filledPolygonMT.
- */
- static int *gfxPrimitivesPolyIntsGlobal = NULL;
- /*!
- \brief Flag indicating if global vertex array was already allocated.
- Note: Used for non-multithreaded (default) operation of filledPolygonMT.
- */
- static int gfxPrimitivesPolyAllocatedGlobal = 0;
- /*!
- \brief Draw filled polygon with alpha blending (multi-threaded capable).
- Note: The last two parameters are optional; but are required for multithreaded operation.
- \param dst The surface to draw on.
- \param vx Vertex array containing X coordinates of the points of the filled polygon.
- \param vy Vertex array containing Y coordinates of the points of the filled polygon.
- \param n Number of points in the vertex array. Minimum number is 3.
- \param color The color value of the filled polygon to draw (0xRRGGBBAA).
- \param polyInts Preallocated, temporary vertex array used for sorting vertices. Required for multithreaded operation; set to NULL otherwise.
- \param polyAllocated Flag indicating if temporary vertex array was allocated. Required for multithreaded operation; set to NULL otherwise.
- \returns Returns 0 on success, -1 on failure.
- */
- int filledPolygonColorMT(SDL_Surface *dst, const Sint16 *vx, const Sint16 *vy, int n, Uint32 color, int **polyInts,
- int *polyAllocated) {
- int result;
- int i;
- int y, xa, xb;
- int miny, maxy;
- int x1, y1;
- int x2, y2;
- int ind1, ind2;
- int ints;
- int *gfxPrimitivesPolyInts = NULL;
- int *gfxPrimitivesPolyIntsNew = NULL;
- int gfxPrimitivesPolyAllocated = 0;
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return (0);
- }
- /*
- * Vertex array NULL check
- */
- if (vx == NULL) {
- return (-1);
- }
- if (vy == NULL) {
- return (-1);
- }
- /*
- * Sanity check number of edges
- */
- if (n < 3) {
- return -1;
- }
- /*
- * Map polygon cache
- */
- if ((polyInts == NULL) || (polyAllocated == NULL)) {
- /* Use global cache */
- gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
- gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
- } else {
- /* Use local cache */
- gfxPrimitivesPolyInts = *polyInts;
- gfxPrimitivesPolyAllocated = *polyAllocated;
- }
- /*
- * Allocate temp array, only grow array
- */
- if (!gfxPrimitivesPolyAllocated) {
- gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
- gfxPrimitivesPolyAllocated = n;
- } else {
- if (gfxPrimitivesPolyAllocated < n) {
- gfxPrimitivesPolyIntsNew = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
- if (!gfxPrimitivesPolyIntsNew) {
- if (!gfxPrimitivesPolyInts) {
- free(gfxPrimitivesPolyInts);
- gfxPrimitivesPolyInts = NULL;
- }
- gfxPrimitivesPolyAllocated = 0;
- } else {
- gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsNew;
- gfxPrimitivesPolyAllocated = n;
- }
- }
- }
- /*
- * Check temp array
- */
- if (gfxPrimitivesPolyInts == NULL) {
- gfxPrimitivesPolyAllocated = 0;
- }
- /*
- * Update cache variables
- */
- if ((polyInts == NULL) || (polyAllocated == NULL)) {
- gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts;
- gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
- } else {
- *polyInts = gfxPrimitivesPolyInts;
- *polyAllocated = gfxPrimitivesPolyAllocated;
- }
- /*
- * Check temp array again
- */
- if (gfxPrimitivesPolyInts == NULL) {
- return (-1);
- }
- /*
- * Determine Y maxima
- */
- miny = vy[0];
- maxy = vy[0];
- for (i = 1; (i < n); i++) {
- if (vy[i] < miny) {
- miny = vy[i];
- } else if (vy[i] > maxy) {
- maxy = vy[i];
- }
- }
- /*
- * Draw, scanning y
- */
- result = 0;
- for (y = miny; (y <= maxy); y++) {
- ints = 0;
- for (i = 0; (i < n); i++) {
- if (!i) {
- ind1 = n - 1;
- ind2 = 0;
- } else {
- ind1 = i - 1;
- ind2 = i;
- }
- y1 = vy[ind1];
- y2 = vy[ind2];
- if (y1 < y2) {
- x1 = vx[ind1];
- x2 = vx[ind2];
- } else if (y1 > y2) {
- y2 = vy[ind1];
- y1 = vy[ind2];
- x2 = vx[ind1];
- x1 = vx[ind2];
- } else {
- continue;
- }
- if (((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2))) {
- gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
- }
- }
- qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
- for (i = 0; (i < ints); i += 2) {
- xa = gfxPrimitivesPolyInts[i] + 1;
- xa = (xa >> 16) + ((xa & 32768) >> 15);
- xb = gfxPrimitivesPolyInts[i + 1] - 1;
- xb = (xb >> 16) + ((xb & 32768) >> 15);
- result |= hlineColor(dst, xa, xb, y, color);
- }
- }
- return (result);
- }
- /*!
- \brief Draw filled polygon with alpha blending (multi-threaded capable).
- Note: The last two parameters are optional; but are required for multithreaded operation.
- \param dst The surface to draw on.
- \param vx Vertex array containing X coordinates of the points of the filled polygon.
- \param vy Vertex array containing Y coordinates of the points of the filled polygon.
- \param n Number of points in the vertex array. Minimum number is 3.
- \param r The red value of the filled polygon to draw.
- \param g The green value of the filled polygon to draw.
- \param b The blue value of the filed polygon to draw.
- \param a The alpha value of the filled polygon to draw.
- \param polyInts Preallocated, temporary vertex array used for sorting vertices. Required for multithreaded operation; set to NULL otherwise.
- \param polyAllocated Flag indicating if temporary vertex array was allocated. Required for multithreaded operation; set to NULL otherwise.
- \returns Returns 0 on success, -1 on failure.
- */
- int filledPolygonRGBAMT(SDL_Surface *dst, const Sint16 *vx, const Sint16 *vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
- int **polyInts, int *polyAllocated) {
- /*
- * Draw
- */
- return (filledPolygonColorMT(dst, vx, vy, n,
- ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, polyInts,
- polyAllocated));
- }
- /*!
- \brief Draw filled polygon with alpha blending.
- Note: Standard filledPolygon function is calling multithreaded version with NULL parameters
- to use the global vertex cache.
- \param dst The surface to draw on.
- \param vx Vertex array containing X coordinates of the points of the filled polygon.
- \param vy Vertex array containing Y coordinates of the points of the filled polygon.
- \param n Number of points in the vertex array. Minimum number is 3.
- \param color The color value of the filled polygon to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int filledPolygonColor(SDL_Surface *dst, const Sint16 *vx, const Sint16 *vy, int n, Uint32 color) {
- /*
- * Draw
- */
- return (filledPolygonColorMT(dst, vx, vy, n, color, NULL, NULL));
- }
- /*!
- \brief Draw filled polygon with alpha blending.
- \param dst The surface to draw on.
- \param vx Vertex array containing X coordinates of the points of the filled polygon.
- \param vy Vertex array containing Y coordinates of the points of the filled polygon.
- \param n Number of points in the vertex array. Minimum number is 3.
- \param r The red value of the filled polygon to draw.
- \param g The green value of the filled polygon to draw.
- \param b The blue value of the filed polygon to draw.
- \param a The alpha value of the filled polygon to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int filledPolygonRGBA(SDL_Surface *dst, const Sint16 *vx, const Sint16 *vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (filledPolygonColorMT(dst, vx, vy, n,
- ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, NULL, NULL));
- }
- /*!
- \brief Internal function to draw a textured horizontal line.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point (i.e. left) of the line.
- \param x2 X coordinate of the second point (i.e. right) of the line.
- \param y Y coordinate of the points of the line.
- \param texture The texture surface to retrieve color information from.
- \param texture_dx The X offset for the texture lookup.
- \param texture_dy The Y offset for the textured lookup.
- \returns Returns 0 on success, -1 on failure.
- */
- int
- _HLineTextured(SDL_Surface *dst, Sint16 x1, Sint16 x2, Sint16 y, SDL_Surface *texture, int texture_dx, int texture_dy) {
- Sint16 left, right, top, bottom;
- Sint16 w;
- Sint16 xtmp;
- int result = 0;
- int texture_x_walker;
- int texture_y_start;
- SDL_Rect source_rect, dst_rect;
- int pixels_written, write_width;
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return (0);
- }
- /*
- * Swap x1, x2 if required to ensure x1<=x2
- */
- if (x1 > x2) {
- xtmp = x1;
- x1 = x2;
- x2 = xtmp;
- }
- /*
- * Get clipping boundary and
- * check visibility of hline
- */
- left = dst->clip_rect.x;
- if (x2 < left) {
- return (0);
- }
- right = dst->clip_rect.x + dst->clip_rect.w - 1;
- if (x1 > right) {
- return (0);
- }
- top = dst->clip_rect.y;
- bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
- if ((y < top) || (y > bottom)) {
- return (0);
- }
- /*
- * Clip x
- */
- if (x1 < left) {
- x1 = left;
- }
- if (x2 > right) {
- x2 = right;
- }
- /*
- * Calculate width to draw
- */
- w = x2 - x1 + 1;
- /*
- * Determine where in the texture we start drawing
- */
- texture_x_walker = (x1 - texture_dx) % texture->w;
- if (texture_x_walker < 0) {
- texture_x_walker = texture->w + texture_x_walker;
- }
- texture_y_start = (y + texture_dy) % texture->h;
- if (texture_y_start < 0) {
- texture_y_start = texture->h + texture_y_start;
- }
- // setup the source rectangle; we are only drawing one horizontal line
- source_rect.y = texture_y_start;
- source_rect.x = texture_x_walker;
- source_rect.h = 1;
- // we will draw to the current y
- dst_rect.y = y;
- // if there are enough pixels left in the current row of the texture
- // draw it all at once
- if (w <= texture->w - texture_x_walker) {
- source_rect.w = w;
- source_rect.x = texture_x_walker;
- dst_rect.x = x1;
- result = (SDL_BlitSurface(texture, &source_rect, dst, &dst_rect) == 0);
- } else { // we need to draw multiple times
- // draw the first segment
- pixels_written = texture->w - texture_x_walker;
- source_rect.w = pixels_written;
- source_rect.x = texture_x_walker;
- dst_rect.x = x1;
- result |= (SDL_BlitSurface(texture, &source_rect, dst, &dst_rect) == 0);
- write_width = texture->w;
- // now draw the rest
- // set the source x to 0
- source_rect.x = 0;
- while (pixels_written < w) {
- if (write_width >= w - pixels_written) {
- write_width = w - pixels_written;
- }
- source_rect.w = write_width;
- dst_rect.x = x1 + pixels_written;
- result |= (SDL_BlitSurface(texture, &source_rect, dst, &dst_rect) == 0);
- pixels_written += write_width;
- }
- }
- return result;
- }
- /*!
- \brief Draws a polygon filled with the given texture (Multi-Threading Capable).
- This operation use internally SDL_BlitSurface for lines of the source texture. It supports
- alpha drawing.
- To get the best performance of this operation you need to make sure the texture and the dst surface have the same format
- (see http://docs.mandragor.org/files/Common_libs_documentation/SDL/SDL_Documentation_project_en/sdlblitsurface.html).
- The last two parameters are optional, but required for multithreaded operation. When set to NULL, uses global static temp array.
- \param dst the destination surface,
- \param vx array of x vector components
- \param vy array of x vector components
- \param n the amount of vectors in the vx and vy array
- \param texture the sdl surface to use to fill the polygon
- \param texture_dx the offset of the texture relative to the screeen. if you move the polygon 10 pixels
- to the left and want the texture to apear the same you need to increase the texture_dx value
- \param texture_dy see texture_dx
- \param polyInts preallocated temp array storage for vertex sorting (used for multi-threaded operation)
- \param polyAllocated flag indicating oif the temp array was allocated (used for multi-threaded operation)
- \returns Returns 0 on success, -1 on failure.
- */
- int texturedPolygonMT(SDL_Surface *dst, const Sint16 *vx, const Sint16 *vy, int n,
- SDL_Surface *texture, int texture_dx, int texture_dy, int **polyInts, int *polyAllocated) {
- int result;
- int i;
- int y, xa, xb;
- int minx, maxx, miny, maxy;
- int x1, y1;
- int x2, y2;
- int ind1, ind2;
- int ints;
- int *gfxPrimitivesPolyInts = NULL;
- int gfxPrimitivesPolyAllocated = 0;
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return (0);
- }
- /*
- * Sanity check number of edges
- */
- if (n < 3) {
- return -1;
- }
- /*
- * Map polygon cache
- */
- if ((polyInts == NULL) || (polyAllocated == NULL)) {
- /* Use global cache */
- gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
- gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
- } else {
- /* Use local cache */
- gfxPrimitivesPolyInts = *polyInts;
- gfxPrimitivesPolyAllocated = *polyAllocated;
- }
- /*
- * Allocate temp array, only grow array
- */
- if (!gfxPrimitivesPolyAllocated) {
- gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
- gfxPrimitivesPolyAllocated = n;
- } else {
- if (gfxPrimitivesPolyAllocated < n) {
- gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
- gfxPrimitivesPolyAllocated = n;
- }
- }
- /*
- * Check temp array
- */
- if (gfxPrimitivesPolyInts == NULL) {
- gfxPrimitivesPolyAllocated = 0;
- }
- /*
- * Update cache variables
- */
- if ((polyInts == NULL) || (polyAllocated == NULL)) {
- gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts;
- gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
- } else {
- *polyInts = gfxPrimitivesPolyInts;
- *polyAllocated = gfxPrimitivesPolyAllocated;
- }
- /*
- * Check temp array again
- */
- if (gfxPrimitivesPolyInts == NULL) {
- return (-1);
- }
- /*
- * Determine X,Y minima,maxima
- */
- miny = vy[0];
- maxy = vy[0];
- minx = vx[0];
- maxx = vx[0];
- for (i = 1; (i < n); i++) {
- if (vy[i] < miny) {
- miny = vy[i];
- } else if (vy[i] > maxy) {
- maxy = vy[i];
- }
- if (vx[i] < minx) {
- minx = vx[i];
- } else if (vx[i] > maxx) {
- maxx = vx[i];
- }
- }
- if (maxx < 0 || minx > dst->w) {
- return -1;
- }
- if (maxy < 0 || miny > dst->h) {
- return -1;
- }
- /*
- * Draw, scanning y
- */
- result = 0;
- for (y = miny; (y <= maxy); y++) {
- ints = 0;
- for (i = 0; (i < n); i++) {
- if (!i) {
- ind1 = n - 1;
- ind2 = 0;
- } else {
- ind1 = i - 1;
- ind2 = i;
- }
- y1 = vy[ind1];
- y2 = vy[ind2];
- if (y1 < y2) {
- x1 = vx[ind1];
- x2 = vx[ind2];
- } else if (y1 > y2) {
- y2 = vy[ind1];
- y1 = vy[ind2];
- x2 = vx[ind1];
- x1 = vx[ind2];
- } else {
- continue;
- }
- if (((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2))) {
- gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
- }
- }
- qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
- for (i = 0; (i < ints); i += 2) {
- xa = gfxPrimitivesPolyInts[i] + 1;
- xa = (xa >> 16) + ((xa & 32768) >> 15);
- xb = gfxPrimitivesPolyInts[i + 1] - 1;
- xb = (xb >> 16) + ((xb & 32768) >> 15);
- result |= _HLineTextured(dst, xa, xb, y, texture, texture_dx, texture_dy);
- }
- }
- return (result);
- }
- /*!
- \brief Draws a polygon filled with the given texture.
- This standard version is calling multithreaded versions with NULL cache parameters.
- \param dst the destination surface,
- \param vx array of x vector components
- \param vy array of x vector components
- \param n the amount of vectors in the vx and vy array
- \param texture the sdl surface to use to fill the polygon
- \param texture_dx the offset of the texture relative to the screeen. if you move the polygon 10 pixels
- to the left and want the texture to apear the same you need to increase the texture_dx value
- \param texture_dy see texture_dx
- \returns Returns 0 on success, -1 on failure.
- */
- int texturedPolygon(SDL_Surface *dst, const Sint16 *vx, const Sint16 *vy, int n, SDL_Surface *texture, int texture_dx,
- int texture_dy) {
- /*
- * Draw
- */
- return (texturedPolygonMT(dst, vx, vy, n, texture, texture_dx, texture_dy, NULL, NULL));
- }
- /* ---- Character */
- /*!
- \brief Global cache for NxM pixel font surfaces created at runtime.
- */
- static SDL_Surface *gfxPrimitivesFont[256];
- /*!
- \brief Global cache of the color used for the font surfaces created at runtime.
- */
- static Uint32 gfxPrimitivesFontColor[256];
- /*!
- \brief Pointer to the current font data. Default is a 8x8 pixel internal font.
- */
- static const unsigned char *currentFontdata = gfxPrimitivesFontdata;
- /*!
- \brief Width of the current font. Default is 8.
- */
- static Uint32 charWidth = 8;
- /*!
- \brief Height of the current font. Default is 8.
- */
- static Uint32 charHeight = 8;
- /*!
- \brief Width for rendering. Autocalculated.
- */
- static Uint32 charWidthLocal = 8;
- /*!
- \brief Height for rendering. Autocalculated.
- */
- static Uint32 charHeightLocal = 8;
- /*!
- \brief Pitch of the current font in bytes. Default is 1.
- */
- static Uint32 charPitch = 1;
- /*!
- \brief Characters 90deg clockwise rotations. Default is 0. Max is 3.
- */
- static Uint32 charRotation = 0;
- /*!
- \brief Character data size in bytes of the current font. Default is 8.
- */
- static Uint32 charSize = 8;
- /*!
- \brief Sets or resets the current global font data.
- The font data array is organized in follows:
- [fontdata] = [character 0][character 1]...[character 255] where
- [character n] = [byte 1 row 1][byte 2 row 1]...[byte {pitch} row 1][byte 1 row 2] ...[byte {pitch} row height] where
- [byte n] = [bit 0]...[bit 7] where
- [bit n] = [0 for transparent pixel|1 for colored pixel]
- \param fontdata Pointer to array of font data. Set to NULL, to reset global font to the default 8x8 font.
- \param cw Width of character in bytes. Ignored if fontdata==NULL.
- \param ch Height of character in bytes. Ignored if fontdata==NULL.
- */
- void gfxPrimitivesSetFont(const void *fontdata, Uint32 cw, Uint32 ch) {
- int i;
- if ((fontdata) && (cw) && (ch)) {
- currentFontdata = fontdata;
- charWidth = cw;
- charHeight = ch;
- } else {
- currentFontdata = gfxPrimitivesFontdata;
- charWidth = 8;
- charHeight = 8;
- }
- charPitch = (charWidth + 7) / 8;
- charSize = charPitch * charHeight;
- /* Maybe flip width/height for rendering */
- if ((charRotation == 1) || (charRotation == 3)) {
- charWidthLocal = charHeight;
- charHeightLocal = charWidth;
- } else {
- charWidthLocal = charWidth;
- charHeightLocal = charHeight;
- }
- /* Clear character cache */
- for (i = 0; i < 256; i++) {
- if (gfxPrimitivesFont[i]) {
- SDL_FreeSurface(gfxPrimitivesFont[i]);
- gfxPrimitivesFont[i] = NULL;
- }
- }
- }
- /*!
- \brief Sets current global font character rotation steps.
- Default is 0 (no rotation). 1 = 90deg clockwise. 2 = 180deg clockwise. 3 = 270deg clockwise.
- Changing the rotation, will reset the character cache.
- \param rotation Number of 90deg clockwise steps to rotate
- */
- void gfxPrimitivesSetFontRotation(Uint32 rotation) {
- int i;
- rotation = rotation & 3;
- if (charRotation != rotation) {
- /* Store rotation */
- charRotation = rotation;
- /* Maybe flip width/height for rendering */
- if ((charRotation == 1) || (charRotation == 3)) {
- charWidthLocal = charHeight;
- charHeightLocal = charWidth;
- } else {
- charWidthLocal = charWidth;
- charHeightLocal = charHeight;
- }
- /* Clear character cache */
- for (i = 0; i < 256; i++) {
- if (gfxPrimitivesFont[i]) {
- SDL_FreeSurface(gfxPrimitivesFont[i]);
- gfxPrimitivesFont[i] = NULL;
- }
- }
- }
- }
- /*!
- \brief Draw a character of the currently set font.
- On first call for a particular character and color combination, the function needs to
- generate the character surface (slower. Subsequent calls blit a cached surface (fast).
- Uses alpha blending if A<255 in color.
- \param dst The surface to draw on.
- \param x X (horizontal) coordinate of the upper left corner of the character.
- \param y Y (vertical) coordinate of the upper left corner of the character.
- \param c The character to draw.
- \param color The color value of the character to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int characterColor(SDL_Surface *dst, Sint16 x, Sint16 y, char c, Uint32 color) {
- Sint16 left, right, top, bottom;
- Sint16 x1, y1, x2, y2;
- SDL_Rect srect;
- SDL_Rect drect;
- int result;
- Uint32 ix, iy;
- const unsigned char *charpos;
- Uint8 *curpos;
- int forced_redraw;
- Uint8 patt, mask;
- Uint8 *linepos;
- Uint32 pitch;
- SDL_Surface *rotatedCharacter;
- Uint32 ci;
- /*
- * Check visibility of clipping rectangle
- */
- if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
- return (0);
- }
- /*
- * Get text and clipping boundary and
- * test if bounding box of character is visible
- */
- left = dst->clip_rect.x;
- x2 = x + charWidthLocal;
- if (x2 < left) {
- return (0);
- }
- right = dst->clip_rect.x + dst->clip_rect.w - 1;
- x1 = x;
- if (x1 > right) {
- return (0);
- }
- top = dst->clip_rect.y;
- y2 = y + charHeightLocal;
- if (y2 < top) {
- return (0);
- }
- bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
- y1 = y;
- if (y1 > bottom) {
- return (0);
- }
- /*
- * Setup source rectangle
- */
- srect.x = 0;
- srect.y = 0;
- srect.w = charWidthLocal;
- srect.h = charHeightLocal;
- /*
- * Setup destination rectangle
- */
- drect.x = x;
- drect.y = y;
- drect.w = charWidthLocal;
- drect.h = charHeightLocal;
- /* Character index in cache */
- ci = (unsigned char) c;
- /*
- * Create new charWidth x charHeight bitmap surface if not already present.
- * Might get rotated later.
- */
- if (gfxPrimitivesFont[ci] == NULL) {
- gfxPrimitivesFont[ci] =
- SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_HWSURFACE | SDL_SRCALPHA,
- charWidth, charHeight, 32,
- 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
- /*
- * Check pointer
- */
- if (gfxPrimitivesFont[ci] == NULL) {
- return (-1);
- }
- /*
- * Definitely redraw
- */
- forced_redraw = 1;
- } else {
- forced_redraw = 0;
- }
- /*
- * Check if color has changed
- */
- if ((gfxPrimitivesFontColor[ci] != color) || (forced_redraw)) {
- /*
- * Redraw character
- */
- SDL_SetAlpha(gfxPrimitivesFont[ci], SDL_SRCALPHA, 255);
- gfxPrimitivesFontColor[ci] = color;
- /* Lock font-surface */
- if (SDL_LockSurface(gfxPrimitivesFont[ci]) != 0)
- return (-1);
- /*
- * Variable setup
- */
- charpos = currentFontdata + ci * charSize;
- linepos = (Uint8 *) gfxPrimitivesFont[ci]->pixels;
- pitch = gfxPrimitivesFont[ci]->pitch;
- /*
- * Drawing loop
- */
- patt = 0;
- for (iy = 0; iy < charHeight; iy++) {
- mask = 0x00;
- curpos = linepos;
- for (ix = 0; ix < charWidth; ix++) {
- if (!(mask >>= 1)) {
- patt = *charpos++;
- mask = 0x80;
- }
- if (patt & mask)
- *(Uint32 *) curpos = color;
- else
- *(Uint32 *) curpos = 0;
- curpos += 4;
- }
- linepos += pitch;
- }
- /* Unlock font-surface */
- SDL_UnlockSurface(gfxPrimitivesFont[ci]);
- /* Maybe rotate and replace cached image */
- if (charRotation > 0) {
- rotatedCharacter = rotateSurface90Degrees(gfxPrimitivesFont[ci], charRotation);
- SDL_FreeSurface(gfxPrimitivesFont[ci]);
- gfxPrimitivesFont[ci] = rotatedCharacter;
- }
- }
- /*
- * Draw bitmap onto destination surface
- */
- result = SDL_BlitSurface(gfxPrimitivesFont[ci], &srect, dst, &drect);
- return (result);
- }
- /*!
- \brief Draw a character of the currently set font.
- \param dst The surface to draw on.
- \param x X (horizontal) coordinate of the upper left corner of the character.
- \param y Y (vertical) coordinate of the upper left corner of the character.
- \param c The character to draw.
- \param r The red value of the character to draw.
- \param g The green value of the character to draw.
- \param b The blue value of the character to draw.
- \param a The alpha value of the character to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int characterRGBA(SDL_Surface *dst, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (characterColor(dst, x, y, c, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /*!
- \brief Draw a string in the currently set font.
- The spacing between consequtive characters in the string is the fixed number of pixels
- of the character width of the current global font.
- \param dst The surface to draw on.
- \param x X (horizontal) coordinate of the upper left corner of the string.
- \param y Y (vertical) coordinate of the upper left corner of the string.
- \param s The string to draw.
- \param color The color value of the string to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int stringColor(SDL_Surface *dst, Sint16 x, Sint16 y, const char *s, Uint32 color) {
- int result = 0;
- Sint16 curx = x;
- Sint16 cury = y;
- const char *curchar = s;
- while (*curchar && !result) {
- result |= characterColor(dst, curx, cury, *curchar, color);
- switch (charRotation) {
- case 0:
- curx += charWidthLocal;
- break;
- case 2:
- curx -= charWidthLocal;
- break;
- case 1:
- cury += charHeightLocal;
- break;
- case 3:
- cury -= charHeightLocal;
- break;
- }
- curchar++;
- }
- return (result);
- }
- /*!
- \brief Draw a string in the currently set font.
- \param dst The surface to draw on.
- \param x X (horizontal) coordinate of the upper left corner of the string.
- \param y Y (vertical) coordinate of the upper left corner of the string.
- \param s The string to draw.
- \param r The red value of the string to draw.
- \param g The green value of the string to draw.
- \param b The blue value of the string to draw.
- \param a The alpha value of the string to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int stringRGBA(SDL_Surface *dst, Sint16 x, Sint16 y, const char *s, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (stringColor(dst, x, y, s, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /* ---- Bezier curve */
- /*!
- \brief Internal function to calculate bezier interpolator of data array with ndata values at position 't'.
- \param data Array of values.
- \param ndata Size of array.
- \param t Position for which to calculate interpolated value. t should be between [0, ndata].
- \returns Interpolated value at position t, value[0] when t<0, value[n-1] when t>n.
- */
- double _evaluateBezier(double *data, int ndata, double t) {
- double mu, result;
- int n, k, kn, nn, nkn;
- double blend, muk, munk;
- /* Sanity check bounds */
- if (t < 0.0) {
- return (data[0]);
- }
- if (t >= (double) ndata) {
- return (data[ndata - 1]);
- }
- /* Adjust t to the range 0.0 to 1.0 */
- mu = t / (double) ndata;
- /* Calculate interpolate */
- n = ndata - 1;
- result = 0.0;
- muk = 1;
- munk = pow(1 - mu, (double) n);
- for (k = 0; k <= n; k++) {
- nn = n;
- kn = k;
- nkn = n - k;
- blend = muk * munk;
- muk *= mu;
- munk /= (1 - mu);
- while (nn >= 1) {
- blend *= nn;
- nn--;
- if (kn > 1) {
- blend /= (double) kn;
- kn--;
- }
- if (nkn > 1) {
- blend /= (double) nkn;
- nkn--;
- }
- }
- result += data[k] * blend;
- }
- return (result);
- }
- /*!
- \brief Draw a bezier curve with alpha blending.
- \param dst The surface to draw on.
- \param vx Vertex array containing X coordinates of the points of the bezier curve.
- \param vy Vertex array containing Y coordinates of the points of the bezier curve.
- \param n Number of points in the vertex array. Minimum number is 3.
- \param s Number of steps for the interpolation. Minimum number is 2.
- \param color The color value of the bezier curve to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int bezierColor(SDL_Surface *dst, const Sint16 *vx, const Sint16 *vy, int n, int s, Uint32 color) {
- int result;
- int i;
- double *x, *y, t, stepsize;
- Sint16 x1, y1, x2, y2;
- /*
- * Sanity check
- */
- if (n < 3) {
- return (-1);
- }
- if (s < 2) {
- return (-1);
- }
- /*
- * Variable setup
- */
- stepsize = (double) 1.0 / (double) s;
- /* Transfer vertices into float arrays */
- if ((x = (double *) malloc(sizeof(double) * (n + 1))) == NULL) {
- return (-1);
- }
- if ((y = (double *) malloc(sizeof(double) * (n + 1))) == NULL) {
- free(x);
- return (-1);
- }
- for (i = 0; i < n; i++) {
- x[i] = (double) vx[i];
- y[i] = (double) vy[i];
- }
- x[n] = (double) vx[0];
- y[n] = (double) vy[0];
- /*
- * Draw
- */
- result = 0;
- t = 0.0;
- x1 = (Sint16) lrint(_evaluateBezier(x, n + 1, t));
- y1 = (Sint16) lrint(_evaluateBezier(y, n + 1, t));
- for (i = 0; i <= (n * s); i++) {
- t += stepsize;
- x2 = (Sint16) _evaluateBezier(x, n, t);
- y2 = (Sint16) _evaluateBezier(y, n, t);
- result |= lineColor(dst, x1, y1, x2, y2, color);
- x1 = x2;
- y1 = y2;
- }
- /* Clean up temporary array */
- free(x);
- free(y);
- return (result);
- }
- /*!
- \brief Draw a bezier curve with alpha blending.
- \param dst The surface to draw on.
- \param vx Vertex array containing X coordinates of the points of the bezier curve.
- \param vy Vertex array containing Y coordinates of the points of the bezier curve.
- \param n Number of points in the vertex array. Minimum number is 3.
- \param s Number of steps for the interpolation. Minimum number is 2.
- \param r The red value of the bezier curve to draw.
- \param g The green value of the bezier curve to draw.
- \param b The blue value of the bezier curve to draw.
- \param a The alpha value of the bezier curve to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int bezierRGBA(SDL_Surface *dst, const Sint16 *vx, const Sint16 *vy, int n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
- /*
- * Draw
- */
- return (bezierColor(dst, vx, vy, n, s, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
- /*!
- \brief Internal function to initialize the Bresenham line iterator.
- Example of use:
- SDL_gfxBresenhamIterator b;
- _bresenhamInitialize (&b, x1, y1, x2, y2);
- do {
- plot(b.x, b.y);
- } while (_bresenhamIterate(&b)==0);
- \param b Pointer to struct for bresenham line drawing state.
- \param x1 X coordinate of the first point of the line.
- \param y1 Y coordinate of the first point of the line.
- \param x2 X coordinate of the second point of the line.
- \param y2 Y coordinate of the second point of the line.
- \returns Returns 0 on success, -1 on failure.
- */
- int _bresenhamInitialize(SDL_gfxBresenhamIterator *b, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2) {
- int temp;
- if (b == NULL) {
- return (-1);
- }
- b->x = x1;
- b->y = y1;
- /* dx = abs(x2-x1), s1 = sign(x2-x1) */
- if ((b->dx = x2 - x1) != 0) {
- if (b->dx < 0) {
- b->dx = -b->dx;
- b->s1 = -1;
- } else {
- b->s1 = 1;
- }
- } else {
- b->s1 = 0;
- }
- /* dy = abs(y2-y1), s2 = sign(y2-y1) */
- if ((b->dy = y2 - y1) != 0) {
- if (b->dy < 0) {
- b->dy = -b->dy;
- b->s2 = -1;
- } else {
- b->s2 = 1;
- }
- } else {
- b->s2 = 0;
- }
- if (b->dy > b->dx) {
- temp = b->dx;
- b->dx = b->dy;
- b->dy = temp;
- b->swapdir = 1;
- } else {
- b->swapdir = 0;
- }
- b->count = (b->dx < 0) ? 0 : (unsigned int) b->dx;
- b->dy <<= 1;
- b->error = b->dy - b->dx;
- b->dx <<= 1;
- return (0);
- }
- /*!
- \brief Internal function to move Bresenham line iterator to the next position.
- Maybe updates the x and y coordinates of the iterator struct.
- \param b Pointer to struct for bresenham line drawing state.
- \returns Returns 0 on success, 1 if last point was reached, 2 if moving past end-of-line, -1 on failure.
- */
- int _bresenhamIterate(SDL_gfxBresenhamIterator *b) {
- if (b == NULL) {
- return (-1);
- }
- /* last point check */
- if (b->count == 0) {
- return (2);
- }
- while (b->error >= 0) {
- if (b->swapdir) {
- b->x += b->s1;
- } else {
- b->y += b->s2;
- }
- b->error -= b->dx;
- }
- if (b->swapdir) {
- b->y += b->s2;
- } else {
- b->x += b->s1;
- }
- b->error += b->dy;
- b->count--;
- /* count==0 indicates "end-of-line" */
- return ((b->count) ? 0 : 1);
- }
- /*!
- \brief Internal function to to draw parallel lines with Murphy algorithm.
- \param m Pointer to struct for murphy iterator.
- \param x X coordinate of point.
- \param y Y coordinate of point.
- \param d1 Direction square/diagonal.
- */
- void _murphyParaline(SDL_gfxMurphyIterator *m, Sint16 x, Sint16 y, int d1) {
- int p;
- d1 = -d1;
- /*
- * Lock the surface
- */
- if (SDL_MUSTLOCK(m->dst)) {
- SDL_LockSurface(m->dst);
- }
- for (p = 0; p <= m->u; p++) {
- pixelColorNolock(m->dst, x, y, m->color);
- if (d1 <= m->kt) {
- if (m->oct2 == 0) {
- x++;
- } else {
- if (m->quad4 == 0) {
- y++;
- } else {
- y--;
- }
- }
- d1 += m->kv;
- } else {
- x++;
- if (m->quad4 == 0) {
- y++;
- } else {
- y--;
- }
- d1 += m->kd;
- }
- }
- /* Unlock surface */
- if (SDL_MUSTLOCK(m->dst)) {
- SDL_UnlockSurface(m->dst);
- }
- m->tempx = x;
- m->tempy = y;
- }
- /*!
- \brief Internal function to to draw one iteration of the Murphy algorithm.
- \param m Pointer to struct for murphy iterator.
- \param miter Iteration count.
- \param ml1bx X coordinate of a point.
- \param ml1by Y coordinate of a point.
- \param ml2bx X coordinate of a point.
- \param ml2by Y coordinate of a point.
- \param ml1x X coordinate of a point.
- \param ml1y Y coordinate of a point.
- \param ml2x X coordinate of a point.
- \param ml2y Y coordinate of a point.
- */
- void _murphyIteration(SDL_gfxMurphyIterator *m, Uint8 miter,
- Uint16 ml1bx, Uint16 ml1by, Uint16 ml2bx, Uint16 ml2by,
- Uint16 ml1x, Uint16 ml1y, Uint16 ml2x, Uint16 ml2y) {
- int atemp1, atemp2;
- int ftmp1, ftmp2;
- Uint16 m1x, m1y, m2x, m2y;
- Uint16 fix, fiy, lax, lay, curx, cury;
- Uint16 px[4], py[4];
- SDL_gfxBresenhamIterator b;
- if (miter > 1) {
- if (m->first1x != -32768) {
- fix = (m->first1x + m->first2x) / 2;
- fiy = (m->first1y + m->first2y) / 2;
- lax = (m->last1x + m->last2x) / 2;
- lay = (m->last1y + m->last2y) / 2;
- curx = (ml1x + ml2x) / 2;
- cury = (ml1y + ml2y) / 2;
- atemp1 = (fix - curx);
- atemp2 = (fiy - cury);
- ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
- atemp1 = (lax - curx);
- atemp2 = (lay - cury);
- ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
- if (ftmp1 <= ftmp2) {
- m1x = m->first1x;
- m1y = m->first1y;
- m2x = m->first2x;
- m2y = m->first2y;
- } else {
- m1x = m->last1x;
- m1y = m->last1y;
- m2x = m->last2x;
- m2y = m->last2y;
- }
- atemp1 = (m2x - ml2x);
- atemp2 = (m2y - ml2y);
- ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
- atemp1 = (m2x - ml2bx);
- atemp2 = (m2y - ml2by);
- ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
- if (ftmp2 >= ftmp1) {
- ftmp1 = ml2bx;
- ftmp2 = ml2by;
- ml2bx = ml2x;
- ml2by = ml2y;
- ml2x = ftmp1;
- ml2y = ftmp2;
- ftmp1 = ml1bx;
- ftmp2 = ml1by;
- ml1bx = ml1x;
- ml1by = ml1y;
- ml1x = ftmp1;
- ml1y = ftmp2;
- }
- /*
- * Lock the surface
- */
- if (SDL_MUSTLOCK(m->dst)) {
- SDL_LockSurface(m->dst);
- }
- _bresenhamInitialize(&b, m2x, m2y, m1x, m1y);
- do {
- pixelColorNolock(m->dst, b.x, b.y, m->color);
- } while (_bresenhamIterate(&b) == 0);
- _bresenhamInitialize(&b, m1x, m1y, ml1bx, ml1by);
- do {
- pixelColorNolock(m->dst, b.x, b.y, m->color);
- } while (_bresenhamIterate(&b) == 0);
- _bresenhamInitialize(&b, ml1bx, ml1by, ml2bx, ml2by);
- do {
- pixelColorNolock(m->dst, b.x, b.y, m->color);
- } while (_bresenhamIterate(&b) == 0);
- _bresenhamInitialize(&b, ml2bx, ml2by, m2x, m2y);
- do {
- pixelColorNolock(m->dst, b.x, b.y, m->color);
- } while (_bresenhamIterate(&b) == 0);
- /* Unlock surface */
- if (SDL_MUSTLOCK(m->dst)) {
- SDL_UnlockSurface(m->dst);
- }
- px[0] = m1x;
- px[1] = m2x;
- px[2] = ml1bx;
- px[3] = ml2bx;
- py[0] = m1y;
- py[1] = m2y;
- py[2] = ml1by;
- py[3] = ml2by;
- polygonColor(m->dst, px, py, 4, m->color);
- }
- }
- m->last1x = ml1x;
- m->last1y = ml1y;
- m->last2x = ml2x;
- m->last2y = ml2y;
- m->first1x = ml1bx;
- m->first1y = ml1by;
- m->first2x = ml2bx;
- m->first2y = ml2by;
- }
- #define HYPOT(x, y) sqrt((double)(x)*(double)(x)+(double)(y)*(double)(y))
- /*!
- \brief Internal function to to draw wide lines with Murphy algorithm.
- Draws lines parallel to ideal line.
- \param m Pointer to struct for murphy iterator.
- \param x1 X coordinate of first point.
- \param y1 Y coordinate of first point.
- \param x2 X coordinate of second point.
- \param y2 Y coordinate of second point.
- \param width Width of line.
- \param miter Iteration count.
- */
- void _murphyWideline(SDL_gfxMurphyIterator *m, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 miter) {
- float offset = (float) width / 2.f;
- Sint16 temp;
- Sint16 ptx, pty, ptxx, ptxy, ml1x, ml1y, ml2x, ml2y, ml1bx, ml1by, ml2bx, ml2by;
- int d0, d1; /* difference terms d0=perpendicular to line, d1=along line */
- int q; /* pel counter,q=perpendicular to line */
- int tmp;
- int dd; /* distance along line */
- int tk; /* thickness threshold */
- double ang; /* angle for initial point calculation */
- double sang, cang;
- /* Initialisation */
- m->u = x2 - x1; /* delta x */
- m->v = y2 - y1; /* delta y */
- if (m->u < 0) { /* swap to make sure we are in quadrants 1 or 4 */
- temp = x1;
- x1 = x2;
- x2 = temp;
- temp = y1;
- y1 = y2;
- y2 = temp;
- m->u *= -1;
- m->v *= -1;
- }
- if (m->v < 0) { /* swap to 1st quadrant and flag */
- m->v *= -1;
- m->quad4 = 1;
- } else {
- m->quad4 = 0;
- }
- if (m->v > m->u) { /* swap things if in 2 octant */
- tmp = m->u;
- m->u = m->v;
- m->v = tmp;
- m->oct2 = 1;
- } else {
- m->oct2 = 0;
- }
- m->ku = m->u + m->u; /* change in l for square shift */
- m->kv = m->v + m->v; /* change in d for square shift */
- m->kd = m->kv - m->ku; /* change in d for diagonal shift */
- m->kt = m->u - m->kv; /* diag/square decision threshold */
- d0 = 0;
- d1 = 0;
- dd = 0;
- ang = atan((double) m->v / (double) m->u); /* calc new initial point - offset both sides of ideal */
- sang = sin(ang);
- cang = cos(ang);
- if (m->oct2 == 0) {
- ptx = x1 + (Sint16) lrint(offset * sang);
- if (m->quad4 == 0) {
- pty = y1 - (Sint16) lrint(offset * cang);
- } else {
- pty = y1 + (Sint16) lrint(offset * cang);
- }
- } else {
- ptx = x1 - (Sint16) lrint(offset * cang);
- if (m->quad4 == 0) {
- pty = y1 + (Sint16) lrint(offset * sang);
- } else {
- pty = y1 - (Sint16) lrint(offset * sang);
- }
- }
- /* used here for constant thickness line */
- tk = (int) (4. * HYPOT(ptx - x1, pty - y1) * HYPOT(m->u, m->v));
- if (miter == 0) {
- m->first1x = -32768;
- m->first1y = -32768;
- m->first2x = -32768;
- m->first2y = -32768;
- m->last1x = -32768;
- m->last1y = -32768;
- m->last2x = -32768;
- m->last2y = -32768;
- }
- ptxx = ptx;
- ptxy = pty;
- for (q = 0; dd <= tk; q++) { /* outer loop, stepping perpendicular to line */
- _murphyParaline(m, ptx, pty, d1); /* call to inner loop - right edge */
- if (q == 0) {
- ml1x = ptx;
- ml1y = pty;
- ml1bx = m->tempx;
- ml1by = m->tempy;
- } else {
- ml2x = ptx;
- ml2y = pty;
- ml2bx = m->tempx;
- ml2by = m->tempy;
- }
- if (d0 < m->kt) { /* square move */
- if (m->oct2 == 0) {
- if (m->quad4 == 0) {
- pty++;
- } else {
- pty--;
- }
- } else {
- ptx++;
- }
- } else { /* diagonal move */
- dd += m->kv;
- d0 -= m->ku;
- if (d1 < m->kt) { /* normal diagonal */
- if (m->oct2 == 0) {
- ptx--;
- if (m->quad4 == 0) {
- pty++;
- } else {
- pty--;
- }
- } else {
- ptx++;
- if (m->quad4 == 0) {
- pty--;
- } else {
- pty++;
- }
- }
- d1 += m->kv;
- } else { /* double square move, extra parallel line */
- if (m->oct2 == 0) {
- ptx--;
- } else {
- if (m->quad4 == 0) {
- pty--;
- } else {
- pty++;
- }
- }
- d1 += m->kd;
- if (dd > tk) {
- _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
- return; /* breakout on the extra line */
- }
- _murphyParaline(m, ptx, pty, d1);
- if (m->oct2 == 0) {
- if (m->quad4 == 0) {
- pty++;
- } else {
- pty--;
- }
- } else {
- ptx++;
- }
- }
- }
- dd += m->ku;
- d0 += m->kv;
- }
- _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
- }
- /*!
- \brief Draw a thick line with alpha blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point of the line.
- \param y1 Y coordinate of the first point of the line.
- \param x2 X coordinate of the second point of the line.
- \param y2 Y coordinate of the second point of the line.
- \param width Width of the line in pixels. Must be >0.
- \param color The color value of the line to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- int thickLineColor(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint32 color) {
- int wh;
- SDL_gfxMurphyIterator m;
- if (dst == NULL) return -1;
- if (width < 1) return -1;
- /* Special case: thick "point" */
- if ((x1 == x2) && (y1 == y2)) {
- wh = width / 2;
- return boxColor(dst, x1 - wh, y1 - wh, x2 + width, y2 + width, color);
- }
- m.dst = dst;
- m.color = color;
- _murphyWideline(&m, x1, y1, x2, y2, width, 0);
- _murphyWideline(&m, x1, y1, x2, y2, width, 1);
- return (0);
- }
- /*!
- \brief Draw a thick line with alpha blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point of the line.
- \param y1 Y coordinate of the first point of the line.
- \param x2 X coordinate of the second point of the line.
- \param y2 Y coordinate of the second point of the line.
- \param width Width of the line in pixels. Must be >0.
- \param r The red value of the character to draw.
- \param g The green value of the character to draw.
- \param b The blue value of the character to draw.
- \param a The alpha value of the character to draw.
- \returns Returns 0 on success, -1 on failure.
- */
- int thickLineRGBA(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 r, Uint8 g, Uint8 b,
- Uint8 a) {
- return (thickLineColor(dst, x1, y1, x2, y2, width,
- ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
- }
|