| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636 |
- /****************************************************************************
- *
- * Copyright 2012 - 2023 Vivante Corporation, Santa Clara, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * 'Software'), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject
- * to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
- #include "vg_lite_context.h"
- #define PI 3.141592653589793238462643383279502f
- #define SINF(x) ((vg_lite_float_t) sin(x))
- #define COSF(x) ((vg_lite_float_t) cos(x))
- #define FABSF(x) ((vg_lite_float_t) fabs(x))
- #define SQRTF(x) ((vg_lite_float_t) sqrt(x))
- #define CLAMP(x, min, max) (((x) < (min)) ? (min) : \
- ((x) > (max)) ? (max) : (x))
- #define ACOSF(x) ((vg_lite_float_t) acos(x))
- #define FMODF(x, y) ((vg_lite_float_t) fmod((x), (y)))
- #define CEILF(x) ((vg_lite_float_t) ceil(x))
- #define SIZEOF(a) ((size_t)(sizeof(a)))
- #define PTR2SIZE(p) ((uintptr_t)(p))
- #define FLOAT_EPSILON 0.001f
- #define SWING_NO 0
- #define SWING_OUT 1
- #define SWING_IN 2
- /* Point curve type for generated stroke path. */
- #define CURVE_LINE 0
- #define CURVE_QUAD_CONTROL 1
- #define CURVE_QUAD_ANCHOR 2
- #define CURVE_ARC_SCCW 3
- #define CURVE_ARC_SCCW_HALF 4
- #define FLOAT_PI 3.141592654f
- #define FLOAT_PI_TWO 6.283185307f
- #define FLOAT_PI_THREE_QUARTER 2.356194490f
- #define FLOAT_PI_HALF 1.570796327f
- #define FLOAT_PI_QUARTER 0.7853981634f
- #define FLOAT_PI_EIGHTH 0.3926990817f
- /* cos(PI/8) */
- #define FLOAT_COS_PI_EIGHTH 0.9238795325f
- #define FLOAT_DIFF_EPSILON 0.125f
- #define FLOAT_SWING_CENTER_RANGE 0.125f
- #define FLOAT_ANGLE_EPSILON 0.0045f
- #define FLOAT_ANGLE_EPSILON_COS 0.99999f
- #define FLOAT_MIN_ARC_ANGLE 0.044f
- #define FLOAT_MIN_ARC_ANGLE_COS 0.999f
- /* Float constants. */
- #define gcvMAX_POS_FLOAT ((vg_lite_float_t) 3.4028235e+038)
- #define gcvMAX_NEG_FLOAT ((vg_lite_float_t) -3.4028235e+038)
- #define FLOAT_MIN gcvMAX_NEG_FLOAT
- #define FLOAT_MAX gcvMAX_POS_FLOAT
- #define FLOAT_FAT_LINE_WIDTH 2.5f
- /* Point flatten type for flattened line segments. */
- #define vgcFLATTEN_NO 0
- #define vgcFLATTEN_START 1
- #define vgcFLATTEN_MIDDLE 2
- #define vgcFLATTEN_END 3
- typedef struct vg_lite_control_coord
- {
- vg_lite_float_t startX;
- vg_lite_float_t startY;
- vg_lite_float_t lastX;
- vg_lite_float_t lastY;
- vg_lite_float_t controlX;
- vg_lite_float_t controlY;
- } vg_lite_control_coord_t;
- /* Command size calculation shortcuts. */
- #define COMMANDSIZE(CoordinateCount, CoordinateType) \
- ((1+CoordinateCount) * SIZEOF(CoordinateType))
- extern int32_t get_data_size(vg_lite_format_t format);
- static uint32_t _commandSize_float[] =
- {
- COMMANDSIZE(0, vg_lite_float_t), /* 0: END */
- COMMANDSIZE(0, vg_lite_float_t), /* 1: CLOSE */
- COMMANDSIZE(2, vg_lite_float_t), /* 2: MOVE */
- COMMANDSIZE(2, vg_lite_float_t), /* 3: MOVE_REL */
- COMMANDSIZE(2, vg_lite_float_t), /* 4: LINE */
- COMMANDSIZE(2, vg_lite_float_t), /* 5: LINE_REL */
- COMMANDSIZE(4, vg_lite_float_t), /* 6: QUAD */
- COMMANDSIZE(4, vg_lite_float_t), /* 7: QUAD_REL */
- COMMANDSIZE(6, vg_lite_float_t), /* 8: CUBIC */
- COMMANDSIZE(6, vg_lite_float_t), /* 9: CUBIC_REL */
- COMMANDSIZE(0, vg_lite_float_t), /* 10: BREAK */
- COMMANDSIZE(1, vg_lite_float_t), /* 11: HLINE */
- COMMANDSIZE(1, vg_lite_float_t), /* 12: HLINE_REL */
- COMMANDSIZE(1, vg_lite_float_t), /* 13: VLINE */
- COMMANDSIZE(1, vg_lite_float_t), /* 14: VLINE_REL */
- COMMANDSIZE(2, vg_lite_float_t), /* 15: SQUAD */
- COMMANDSIZE(2, vg_lite_float_t), /* 16: SQUAD_REL */
- COMMANDSIZE(4, vg_lite_float_t), /* 17: SCUBIC */
- COMMANDSIZE(4, vg_lite_float_t), /* 18: SCUBIC_REL */
- COMMANDSIZE(5, vg_lite_float_t), /* 19: SCCWARC */
- COMMANDSIZE(5, vg_lite_float_t), /* 20: SCCWARC_REL */
- COMMANDSIZE(5, vg_lite_float_t), /* 21: SCWARC */
- COMMANDSIZE(5, vg_lite_float_t), /* 22: SCWARC_REL */
- COMMANDSIZE(5, vg_lite_float_t), /* 23: LCCWARC */
- COMMANDSIZE(5, vg_lite_float_t), /* 24: LCCWARC_REL */
- COMMANDSIZE(5, vg_lite_float_t), /* 25: LCWARC */
- COMMANDSIZE(5, vg_lite_float_t), /* 26: LCWARC_REL */
- };
- #if gcFEATURE_VG_STROKE_PATH
- static vg_lite_float_t _GetS8_NS_NB(int8_t * Data)
- {
- int8_t x0 = *((int8_t *) Data);
- vg_lite_float_t x = (vg_lite_float_t) x0;
- return x;
- }
- static vg_lite_float_t _GetS16_NS_NB(int8_t * Data)
- {
- int16_t x0 = *((int16_t *) Data);
- vg_lite_float_t x = (vg_lite_float_t) x0;
- return x;
- }
- static vg_lite_float_t _GetS32_NS_NB(int8_t * Data)
- {
- int32_t x0 = *((int32_t *) Data);
- vg_lite_float_t x = (vg_lite_float_t) x0;
- return x;
- }
- static vg_lite_float_t _GetF_NS_NB(int8_t * Data)
- {
- vg_lite_float_t x = *((vg_lite_float_t *) Data);
- return x;
- }
- /* Special sqrt(1.0f + x) for quick calculation when 0 <= x <= 1. */
- static vg_lite_float_t _Sqrt(
- vg_lite_float_t X
- )
- {
- vg_lite_float_t x = X;
- vg_lite_float_t s = 1.0f;
- s += x * 0.5f;
- x *= X;
- s -= x * 0.12445995211601257f;
- x *= X;
- s += x * 0.058032196015119553f;
- x *= X;
- s -= x * 0.025314478203654289f;
- x *= X;
- s += x * 0.0059584137052297592f;
- return s;
- }
- static vg_lite_error_t _set_point_tangent(
- vg_lite_path_point_ptr Point,
- vg_lite_float_t Dx,
- vg_lite_float_t Dy
- )
- {
- if (!Point)
- return VG_LITE_INVALID_ARGUMENT;
- if (Dx == 0.0f)
- {
- if (Dy == 0.0f)
- {
- if (Point->prev)
- {
- Point->length = 0.0f;
- Point->tangentX = Point->prev->tangentX;
- Point->tangentY = Point->prev->tangentY;
- }
- else
- {
- Point->length = 0.0f;
- Point->tangentX = 0.0f;
- Point->tangentY = 0.0f;
- }
- }
- else
- {
- Point->tangentX = 0.0f;
- if (Dy > 0.0f)
- {
- Point->length = Dy;
- Point->tangentY = 1.0f;
- }
- else
- {
- Point->length = -Dy;
- Point->tangentY = -1.0f;
- }
- }
- }
- else if (Dy == 0.0f)
- {
- Point->tangentY = 0.0f;
- if (Dx > 0.0f)
- {
- Point->length = Dx;
- Point->tangentX = 1.0f;
- }
- else
- {
- Point->length = -Dx;
- Point->tangentX = -1.0f;
- }
- }
- else
- {
- vg_lite_float_t l, tx, ty;
- vg_lite_float_t dx, dy;
- vg_lite_float_t t, t2;
- dx = (Dx >= 0.0f ? Dx : -Dx);
- dy = (Dy >= 0.0f ? Dy : -Dy);
- if (dx >= dy)
- {
- t = dy / dx;
- t2 = t * t;
- l = _Sqrt(t2);
- Point->length = l * dx;
- tx = 1.0f / l;
- ty = tx * t;
- }
- else
- {
- t = dx / dy;
- t2 = t * t;
- l = _Sqrt(t2);
- Point->length = l * dy;
- ty = 1.0f / l;
- tx = ty * t;
- }
- if (Dx < 0.0f) tx = -tx;
- if (Dy < 0.0f) ty = -ty;
- tx = CLAMP(tx, -1.0f, 1.0f);
- ty = CLAMP(ty, -1.0f, 1.0f);
- Point->tangentX = tx;
- Point->tangentY = ty;
- }
- return VG_LITE_SUCCESS;
- }
- static vg_lite_error_t _add_point_to_point_list_wdelta(
- vg_lite_stroke_t * stroke_conversion,
- vg_lite_float_t X,
- vg_lite_float_t Y,
- vg_lite_float_t DX,
- vg_lite_float_t DY,
- uint8_t flatten_flag
- )
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- vg_lite_path_point_ptr last_point;
- vg_lite_path_point_ptr point;
- if (!stroke_conversion)
- return VG_LITE_INVALID_ARGUMENT;
- last_point = stroke_conversion->path_end;
- point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*point));
- if (!point)
- return VG_LITE_OUT_OF_RESOURCES;
- memset(point, 0, sizeof(*point));
- point->x = X;
- point->y = Y;
- point->flatten_flag = flatten_flag;
- /* Calculate tangent for last_point. */
- VG_LITE_ERROR_HANDLER(_set_point_tangent(last_point, DX, DY));
- last_point->next = point;
- stroke_conversion->path_end = point;
- point->prev = last_point;
- stroke_conversion->point_count++;
- stroke_conversion->cur_list->path_end = point;
- stroke_conversion->cur_list->point_count++;
- return error;
- ErrorHandler:
- vg_lite_os_free(point);
- point = NULL;
- return error;
- }
- static vg_lite_error_t _create_new_point_list(
- vg_lite_stroke_t* stroke_conversion,
- vg_lite_float_t X,
- vg_lite_float_t Y,
- uint8_t flatten_flag
- )
- {
- vg_lite_error_t status = VG_LITE_SUCCESS;
- vg_lite_path_point_ptr point;
- vg_lite_path_list_ptr path_list_divide;
- if (!stroke_conversion)
- return VG_LITE_INVALID_ARGUMENT;
- point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*point));
- if (!point)
- return VG_LITE_OUT_OF_RESOURCES;
- memset(point, 0, sizeof(*point));
- point->x = X;
- point->y = Y;
- point->flatten_flag = flatten_flag;
- point->prev = NULL;
- stroke_conversion->point_count = 0;
- stroke_conversion->path_end = stroke_conversion->path_points = point;
- stroke_conversion->point_count++;
- path_list_divide = (vg_lite_path_list_ptr)vg_lite_os_malloc(sizeof(*path_list_divide));
- if (!path_list_divide)
- return VG_LITE_OUT_OF_RESOURCES;
- memset(path_list_divide, 0, sizeof(*path_list_divide));
- path_list_divide->path_end = path_list_divide->path_points = point;
- path_list_divide->point_count++;
- if (stroke_conversion->cur_list == NULL)
- {
- stroke_conversion->cur_list = path_list_divide;
- stroke_conversion->path_list_divide = path_list_divide;
- }
- else
- {
- stroke_conversion->cur_list->next = path_list_divide;
- stroke_conversion->cur_list = stroke_conversion->cur_list->next;
- }
- return status;
- }
- static vg_lite_error_t _add_point_to_point_list(
- vg_lite_stroke_t * stroke_conversion,
- vg_lite_float_t X,
- vg_lite_float_t Y,
- uint8_t flatten_flag
- )
- {
- vg_lite_error_t status = VG_LITE_SUCCESS;
- vg_lite_path_point_ptr last_point;
- vg_lite_path_point_ptr point;
- if (!stroke_conversion)
- return VG_LITE_INVALID_ARGUMENT;
- last_point = stroke_conversion->path_end;
- if (last_point == NULL)
- {
- point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*point));
- if (!point)
- return VG_LITE_OUT_OF_RESOURCES;
- memset(point, 0, sizeof(*point));
- point->x = X;
- point->y = Y;
- point->flatten_flag = flatten_flag;
- point->prev = NULL;
- stroke_conversion->path_end = stroke_conversion->path_points = point;
- stroke_conversion->point_count++;
- status = VG_LITE_SUCCESS;
- }
- else
- {
- vg_lite_float_t dX = X - last_point->x;
- vg_lite_float_t dY = Y - last_point->y;
- vg_lite_float_t deltaX = (dX >= 0.0f ? dX : -dX);
- vg_lite_float_t deltaY = (dY >= 0.0f ? dY : -dY);
- /* Check for degenerated line. */
- if (deltaX == 0.0f && deltaY == 0.0f)
- {
- /* Skip degenerated line. */
- status = VG_LITE_SUCCESS;
- goto ErrorHandler;
- }
- if (deltaX < FLOAT_EPSILON && deltaY < FLOAT_EPSILON)
- {
- vg_lite_float_t ratioX, ratioY;
- if (deltaX == 0.0f)
- {
- ratioX = 0.0f;
- }
- else if (X == 0.0f)
- {
- ratioX = deltaX;
- }
- else
- {
- ratioX = deltaX / X;
- if (ratioX < 0.0f) ratioX = -ratioX;
- }
- if (deltaY == 0.0f)
- {
- ratioY = 0.0f;
- }
- else if (Y == 0.0f)
- {
- ratioY = deltaY;
- }
- else
- {
- ratioY = deltaY / Y;
- if (ratioY < 0.0f) ratioY = -ratioY;
- }
- if (ratioX < 1.0e-6f && ratioY < 1.0e-6f)
- {
- /* Skip degenerated line. */
- status = VG_LITE_SUCCESS;
- goto ErrorHandler;
- }
- }
- status = _add_point_to_point_list_wdelta(stroke_conversion, X, Y, dX, dY, flatten_flag);
- }
- ErrorHandler:
- return status;
- }
- #define gcFEATURE_VG_SIMPLYFIED_BEZIER 1
- #if gcFEATURE_VG_SIMPLYFIED_BEZIER
- void quad_bezier(float* x, float* y, const float curve[6], float t) {
- const float* v0, * v1, * v2;
- float mt, t2, mt2, res[2];
- v0 = &curve[0];
- v1 = &curve[2];
- v2 = &curve[4];
- mt = 1 - t;
- t2 = t * t;
- mt2 = mt * mt;
- for (uint8_t i = 0; i < 2; ++i) {
- res[i] = v0[i] * mt2 + 2 * v1[i] * mt * t + v2[i] * t2;
- }
- *x = res[0];
- *y = res[1];
- }
- void cubic_bezier(float* x, float* y, const float curve[8], float t) {
- const float* v0, * v1, * v2, * v3;
- float mt, t2, mt2, t3, mt3, res[2];
- v0 = &curve[0];
- v1 = &curve[2];
- v2 = &curve[4];
- v3 = &curve[6];
- mt = 1 - t;
- t2 = t * t;
- t3 = t2 * t;
- mt2 = mt * mt;
- mt3 = mt2 * mt;
- for (uint8_t i = 0; i < 2; ++i) {
- res[i] = v0[i] * mt3 + 3 * v1[i] * mt2 * t + 3 * v2[i] * mt * t2 + v3[i] * t3;
- }
- *x = res[0];
- *y = res[1];
- }
- void pointer_warp_affine(float out[2], float pt[2], vg_lite_matrix_t* matrix) {
- float x, y;
- x = pt[0];
- y = pt[1];
- out[0] = matrix->m[0][0] * x + matrix->m[1][0] * y + matrix->m[2][0];
- out[1] = matrix->m[0][1] * x + matrix->m[1][1] * y + matrix->m[2][1];
- }
- void get_aligned_quad(float out[6], float curve[6]) {
- float* v0, * v1, * v2;
- float angle, dx, dy;
- vg_lite_matrix_t matrix;
- v0 = &curve[0];
- v1 = &curve[2];
- v2 = &curve[4];
- dx = v2[0] - v0[0];
- dy = v2[1] - v0[1];
- angle = (dy >= 0) ? acosf(dx / sqrtf(dx * dx + dy * dy)) : (2 * 3.1415926535f - acosf(dx / sqrtf(dx * dx + dy * dy)));
- vg_lite_identity(&matrix);
- vg_lite_translate(-v0[0], -v0[1], &matrix);
- vg_lite_rotate(-angle, &matrix);
- pointer_warp_affine(&out[0], v0, &matrix);
- pointer_warp_affine(&out[2], v1, &matrix);
- pointer_warp_affine(&out[4], v2, &matrix);
- }
- void get_aligned_cubic(float out[8], float curve[8]) {
- float* v0, * v1, * v2, * v3;
- float angle, dx, dy;
- vg_lite_matrix_t matrix;
- v0 = &curve[0];
- v1 = &curve[2];
- v2 = &curve[4];
- v3 = &curve[6];
- dx = v3[0] - v0[0];
- dy = v3[1] - v0[1];
- angle = (dy >= 0) ? acosf(dx / sqrtf(dx * dx + dy * dy)) : (2 * 3.1415926535f - acosf(dx / sqrtf(dx * dx + dy * dy)));
- vg_lite_identity(&matrix);
- vg_lite_translate(-v0[0], -v0[1], &matrix);
- vg_lite_rotate(-angle, &matrix);
- pointer_warp_affine(&out[0], v0, &matrix);
- pointer_warp_affine(&out[2], v1, &matrix);
- pointer_warp_affine(&out[4], v2, &matrix);
- pointer_warp_affine(&out[6], v3, &matrix);
- }
- void split_quad(float out1[6], float out2[6], float curve[6], float split) {
- float* v0, * v1, * v2;
- float s, s2, ms, ms2;
- v0 = &curve[0];
- v1 = &curve[2];
- v2 = &curve[4];
- s = split;
- ms = 1 - split;
- s2 = s * s;
- ms2 = ms * ms;
- float B[2][3] = {
- {v0[0], v1[0], v2[0]},
- {v0[1], v1[1], v2[1]}
- };
- /* First curve */
- {
- float C[2][3] = { {0} };
- float A[9] = {
- 1, 0, 0,
- ms, s, 0,
- ms2, 2 * ms * s, s2
- };
- /* C = A ¡Á B */
- for (uint8_t i = 0; i < 2; ++i) {
- for (size_t y = 0; y < 3; ++y)
- for (size_t x = 0; x < 1; ++x)
- for (size_t z = 0; z < 3; ++z) {
- C[i][x + y * 1] += A[z + y * 3] * B[i][x + z * 1];
- }
- }
- out1[0] = C[0][0]; out1[1] = C[1][0];
- out1[2] = C[0][1]; out1[3] = C[1][1];
- out1[4] = C[0][2]; out1[5] = C[1][2];
- }
- /* Second curve */
- {
- float C[2][3] = { {0} };
- float A[9] = {
- ms2, 2 * s * ms, s2,
- 0, ms, s,
- 0, 0, 1
- };
- /* C = A ¡Á B */
- for (uint8_t i = 0; i < 2; ++i) {
- for (size_t y = 0; y < 3; ++y)
- for (size_t x = 0; x < 1; ++x)
- for (size_t z = 0; z < 3; ++z) {
- C[i][x + y * 1] += A[z + y * 3] * B[i][x + z * 1];
- }
- }
- out2[0] = C[0][0]; out2[1] = C[1][0];
- out2[2] = C[0][1]; out2[3] = C[1][1];
- out2[4] = C[0][2]; out2[5] = C[1][2];
- }
- }
- void split_cubic(float out1[8], float out2[8], float curve[8], float split) {
- float* v0, * v1, * v2, * v3;
- float s, s2, s3, ms, ms2, ms3;
- v0 = &curve[0];
- v1 = &curve[2];
- v2 = &curve[4];
- v3 = &curve[6];
- s = split;
- ms = 1 - split;
- s2 = s * s;
- ms2 = ms * ms;
- s3 = s2 * s;
- ms3 = ms2 * ms;
- float B[2][4] = {
- {v0[0], v1[0], v2[0], v3[0]},
- {v0[1], v1[1], v2[1], v3[1]}
- };
- /* First curve */
- {
- float C[2][4] = { {0} };
- float A[16] = {
- 1, 0, 0, 0,
- ms, s, 0, 0,
- ms2, 2 * ms * s, s2, 0,
- ms3, 3 * s * ms2, 3 * s2 * ms, s3
- };
- /* C = A ¡Á B */
- for (uint8_t i = 0; i < 2; ++i) {
- for (size_t y = 0; y < 4; ++y)
- for (size_t x = 0; x < 1; ++x)
- for (size_t z = 0; z < 4; ++z) {
- C[i][x + y * 1] += A[z + y * 4] * B[i][x + z * 1];
- }
- }
- out1[0] = C[0][0]; out1[1] = C[1][0];
- out1[2] = C[0][1]; out1[3] = C[1][1];
- out1[4] = C[0][2]; out1[5] = C[1][2];
- out1[6] = C[0][3]; out1[7] = C[1][3];
- }
- /* Second curve */
- {
- float C[2][4] = { {0} };
- float A[16] = {
- ms3, 3 * s * ms2, 3 * s2 * ms, s3,
- 0, ms2, 2 * ms * s, s2,
- 0, 0, ms, s,
- 0, 0, 0, 1
- };
- /* C = A ¡Á B */
- for (uint8_t i = 0; i < 2; ++i) {
- for (size_t y = 0; y < 4; ++y)
- for (size_t x = 0; x < 1; ++x)
- for (size_t z = 0; z < 4; ++z) {
- C[i][x + y * 1] += A[z + y * 4] * B[i][x + z * 1];
- }
- }
- out2[0] = C[0][0]; out2[1] = C[1][0];
- out2[2] = C[0][1]; out2[3] = C[1][1];
- out2[4] = C[0][2]; out2[5] = C[1][2];
- out2[6] = C[0][3]; out2[7] = C[1][3];
- }
- }
- static vg_lite_error_t _flatten_quad_bezier(
- vg_lite_stroke_t* stroke_conversion,
- vg_lite_float_t rootCurve[6],
- vg_lite_float_t subCurve[6],
- vg_lite_uint8_t level)
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- float* v0, * v1, * v2;
- float dx2, dy2, d1;
- float subCurve1[6], subCurve2[6];
- vg_lite_path_point_ptr point0, point1;
- vg_lite_float_t* curve;
- curve = (level == 0) ? rootCurve : subCurve;
- if (!stroke_conversion)
- return VG_LITE_INVALID_ARGUMENT;
- if (level > 10) return error;
- v0 = &curve[0];
- v1 = &curve[2];
- v2 = &curve[4];
- if (level == 0) {
- /* Add extra P0 for incoming tangent. */
- point0 = stroke_conversion->path_end;
- /* First add P1 to calculate incoming tangent, which is saved in P0. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v1[0], v1[1], vgcFLATTEN_START));
- point1 = stroke_conversion->path_end;
- /* Change the point1's coordinates back to P0. */
- point1->x = v0[0];
- point1->y = v0[1];
- point0->length = 0.0f;
- }
- dx2 = v2[0] - v0[0];
- dy2 = v2[1] - v0[1];
- d1 = fabsf((v1[0] - v2[0]) * dy2 - (v1[1] - v2[1]) * dx2);
- if (d1 * d1 < 0.25 * (dx2 * dx2 + dy2 * dy2)) {
- float bound[4];
- bound[0] = MIN(v0[0], v2[0]);
- bound[1] = MIN(v0[1], v2[1]);
- bound[2] = MAX(v0[0], v2[0]);
- bound[3] = MAX(v0[1], v2[1]);
- if (!(v1[0] >= bound[0] && v1[0] <= bound[2] && v1[1] >= bound[1] && v1[1] <= bound[3])) {
- /* Compute root. */
- float alignedCurve[6];
- float d, n, t, pt[2];
- get_aligned_quad(alignedCurve, curve);
- n = alignedCurve[0] - alignedCurve[2];
- d = alignedCurve[0] - 2.f * alignedCurve[2] + alignedCurve[4];
- if (fabsf(d) > 1e-12f) {
- t = n / d;
- if (t > 1e-12f && t < 1.f - 1e-12f) {
- quad_bezier(&pt[0], &pt[1], curve, t);
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, pt[0], pt[1], vgcFLATTEN_MIDDLE));
- }
- }
- }
- else if(level == 0) {
- float pt[2];
- uint8_t n = 16;
- for (uint8_t i = 1; i < n; i++) {
- vg_lite_float_t t = (vg_lite_float_t)i / (vg_lite_float_t)n;
- quad_bezier(&pt[0], &pt[1], curve, t);
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, pt[0], pt[1], vgcFLATTEN_MIDDLE));
- }
- }
- if (level == 0)
- {
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_END));
- }
- else if((v2[0] != rootCurve[4]) || (v2[1] != rootCurve[5]))
- {
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_MIDDLE));
- }
- if (level == 0) {
- /* Add extra P2 for outgoing tangent. */
- /* First change P2(point0)'s coordinates to P1. */
- point0 = stroke_conversion->path_end;
- point0->x = v1[0];
- point0->y = v1[1];
- /* Add P2 to calculate outgoing tangent. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_NO));
- point1 = stroke_conversion->path_end;
- /* Change point0's coordinates back to P2. */
- point0->x = v2[0];
- point0->y = v2[1];
- point0->length = 0.0f;
- }
- return error;
- }
- split_quad(subCurve1, subCurve2, curve, 0.5);
- VG_LITE_ERROR_HANDLER(_flatten_quad_bezier(stroke_conversion, rootCurve, subCurve1, level + 1));
- VG_LITE_ERROR_HANDLER(_flatten_quad_bezier(stroke_conversion, rootCurve, subCurve2, level + 1));
- if (level == 0) {
- /* Add point 2 separately to avoid cumulative errors. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_END));
- /* Add extra P2 for outgoing tangent. */
- /* First change P2(point0)'s coordinates to P1. */
- point0 = stroke_conversion->path_end;
- point0->x = v1[0];
- point0->y = v1[1];
- /* Add P2 to calculate outgoing tangent. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_NO));
- point1 = stroke_conversion->path_end;
- /* Change point0's coordinates back to P2. */
- point0->x = v2[0];
- point0->y = v2[1];
- point0->length = 0.0f;
- }
- ErrorHandler:
- return error;
- }
- static vg_lite_error_t _flatten_quad_bezier_original(
- vg_lite_stroke_t* stroke_conversion,
- vg_lite_float_t curve[6],
- vg_lite_uint8_t level)
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- float* v0, * v1, * v2;
- float dx2, dy2, d1;
- float subCurve1[6], subCurve2[6];
- vg_lite_path_point_ptr point0, point1;
- if (!stroke_conversion)
- return VG_LITE_INVALID_ARGUMENT;
- if (level > 10) return error;
- v0 = &curve[0];
- v1 = &curve[2];
- v2 = &curve[4];
- if (level == 0) {
- /* Add extra P0 for incoming tangent. */
- point0 = stroke_conversion->path_end;
- /* First add P1 to calculate incoming tangent, which is saved in P0. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v1[0], v1[1], vgcFLATTEN_NO));
- point1 = stroke_conversion->path_end;
- /* Change the point1's coordinates back to P0. */
- point1->x = v0[0];
- point1->y = v0[1];
- point0->length = 0.0f;
- }
- dx2 = v2[0] - v0[0];
- dy2 = v2[1] - v0[1];
- d1 = fabsf((v1[0] - v2[0]) * dy2 - (v1[1] - v2[1]) * dx2);
- if (d1 * d1 < 0.25 * (dx2 * dx2 + dy2 * dy2)) {
- float bound[4];
- bound[0] = MIN(v0[0], v2[0]);
- bound[1] = MIN(v0[1], v2[1]);
- bound[2] = MAX(v0[0], v2[0]);
- bound[3] = MAX(v0[1], v2[1]);
- if (!(v1[0] >= bound[0] && v1[0] <= bound[2] && v1[1] >= bound[1] && v1[1] <= bound[3])) {
- /* Compute root. */
- float alignedCurve[6];
- float d, n, t, pt[2];
- get_aligned_quad(alignedCurve, curve);
- n = alignedCurve[0] - alignedCurve[2];
- d = alignedCurve[0] - 2.f * alignedCurve[2] + alignedCurve[4];
- if (fabsf(d) > 1e-12f) {
- t = n / d;
- if (t > 1e-12f && t < 1.f - 1e-12f) {
- quad_bezier(&pt[0], &pt[1], curve, t);
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, pt[0], pt[1], vgcFLATTEN_NO));
- }
- }
- }
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_NO));
- return error;
- }
- split_quad(subCurve1, subCurve2, curve, 0.5);
- VG_LITE_ERROR_HANDLER(_flatten_quad_bezier_original(stroke_conversion, subCurve1, level + 1));
- VG_LITE_ERROR_HANDLER(_flatten_quad_bezier_original(stroke_conversion, subCurve2, level + 1));
- if (level == 0) {
- /* Add point 2 separately to avoid cumulative errors. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_NO));
- /* Add extra P2 for outgoing tangent. */
- /* First change P2(point0)'s coordinates to P1. */
- point0 = stroke_conversion->path_end;
- point0->x = v1[0];
- point0->y = v1[1];
- /* Add P2 to calculate outgoing tangent. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_NO));
- point1 = stroke_conversion->path_end;
- /* Change point0's coordinates back to P2. */
- point0->x = v2[0];
- point0->y = v2[1];
- point0->length = 0.0f;
- }
- ErrorHandler:
- return error;
- }
- static vg_lite_error_t _flatten_cubic_bezier(
- vg_lite_stroke_t* stroke_conversion,
- vg_lite_float_t rootCurve[8],
- vg_lite_float_t subCurve[8],
- vg_lite_uint8_t level)
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- float* v0, * v1, * v2, * v3;
- float dx3, dy3, d1, d2;
- float subCurve1[8], subCurve2[8];
- vg_lite_path_point_ptr point0, point1;
- vg_lite_float_t* curve;
- if (!stroke_conversion)
- return VG_LITE_INVALID_ARGUMENT;
- if (level > 10) return error;
- curve = (level == 0) ? rootCurve : subCurve;
- v0 = &curve[0];
- v1 = &curve[2];
- v2 = &curve[4];
- v3 = &curve[6];
- if (level == 0) {
- /* Add extra P0 for incoming tangent. */
- point0 = stroke_conversion->path_end;
- /* First add P1/P2/P3 to calculate incoming tangent, which is saved in P0. */
- if (v0[0] != v1[0] || v0[1] != v1[1])
- {
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v1[0], v1[1], vgcFLATTEN_START));
- }
- else if (v0[0] != v2[0] || v0[1] != v2[1])
- {
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_START));
- }
- else
- {
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_START));
- }
- point1 = stroke_conversion->path_end;
- /* Change the point1's coordinates back to P0. */
- point1->x = v0[0];
- point1->y = v0[1];
- point0->length = 0.0f;
- }
- dx3 = v3[0] - v0[0];
- dy3 = v3[1] - v0[1];
- d1 = fabsf((v1[0] - v3[0]) * dy3 - (v1[1] - v3[1]) * dx3);
- d2 = fabsf((v2[0] - v3[0]) * dy3 - (v2[1] - v3[1]) * dx3);
- if ((d1 + d2) * (d1 + d2) < 0.25f * (dx3 * dx3 + dy3 * dy3)) {
- float bound[4];
- bound[0] = MIN(v0[0], v3[0]);
- bound[1] = MIN(v0[1], v3[1]);
- bound[2] = MAX(v0[0], v3[0]);
- bound[3] = MAX(v0[1], v3[1]);
- if (!(v1[0] >= bound[0] && v1[0] <= bound[2] && v1[1] >= bound[1] && v1[1] <= bound[3]) ||
- !(v2[0] >= bound[0] && v2[0] <= bound[2] && v2[1] >= bound[1] && v2[1] <= bound[3])) {
- /* Compute root. */
- float alignedCurve[8];
- float a, b, c, b2ac, root[2], t, pt[2];
- uint8_t rootNum;
- get_aligned_cubic(alignedCurve, curve);
- a = -3.f * alignedCurve[0] + 9.f * alignedCurve[2] - 9.f * alignedCurve[4] + 3.f * alignedCurve[6];
- b = 6.f * alignedCurve[0] - 12.f * alignedCurve[2] + 6.f * alignedCurve[4];
- c = -3.f * alignedCurve[0] + 3.f * alignedCurve[2];
- rootNum = 0;
- if (fabs(a) < 1e-12f) { // linear solution
- t = -c / b;
- if (t > 1e-12f && t < 1.f - 1e-12f)
- root[rootNum++] = t;
- }
- else { // quadtratic solution
- b2ac = b * b - 4.f * a * c;
- if (b2ac > 1e-12f) {
- t = (-b + (float)sqrt(b2ac)) / (2.f * a);
- if (t > 1e-12f && t < 1.f - 1e-12f)
- root[rootNum++] = t;
- t = (-b - (float)sqrt(b2ac)) / (2.f * a);
- if (t > 1e-12f && t < 1.f - 1e-12f)
- root[rootNum++] = t;
- }
- }
- if (rootNum == 2 && root[0] > root[1]) {
- /* Exchange root. */
- float tmp;
- tmp = root[0];
- root[0] = root[1];
- root[1] = tmp;
- }
- if ((rootNum <= 2) && (level == 0)) {
- float pt[2];
- uint8_t n = 8;
- if (rootNum == 2)
- {
- float step = (root[1] - root[0]) / 8;
- float t = root[0];
- while (t < root[1])
- {
- cubic_bezier(&pt[0], &pt[1], curve, t);
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, pt[0], pt[1], vgcFLATTEN_MIDDLE));
- t += step;
- }
- }
- else
- {
- for (uint8_t i = 1; i < n; i++) {
- vg_lite_float_t t = (vg_lite_float_t)i / (vg_lite_float_t)n;
- cubic_bezier(&pt[0], &pt[1], curve, t);
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, pt[0], pt[1], vgcFLATTEN_MIDDLE));
- }
- }
- }
- else {
- for (uint8_t i = 0; i < rootNum; i++) {
- cubic_bezier(&pt[0], &pt[1], curve, root[i]);
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, pt[0], pt[1], vgcFLATTEN_MIDDLE));
- }
- }
- }
- else if (level == 0) {
- vg_lite_float_t a1x, a1y, a2x, a2y, a3x, a3y;
- vg_lite_float_t ddf0, ddf1, t1, t2, upper_bound;
- vg_lite_uint32_t n;
- vg_lite_float_t pt[2];
- a1x = 3 * (v1[0] - v0[0]);
- a1y = 3 * (v1[1] - v0[1]);
- a2x = 3 * (v0[0] - v1[0] - v1[0] + v2[0]);
- a2y = 3 * (v0[1] - v1[1] - v1[1] + v2[1]);
- a3x = 3 * (v1[0] - v2[0]) + v3[0] - v0[0];
- a3y = 3 * (v1[1] - v2[1]) + v3[1] - v0[1];
- ddf0 = a2x * a2x + a2y * a2y;
- t1 = a2x + a3x + a3x + a3x;
- t2 = a2y + a3y + a3y + a3y;
- ddf1 = t1 * t1 + t2 * t2;
- upper_bound = ddf0 > ddf1 ? ddf0 : ddf1;
- upper_bound = SQRTF(upper_bound);
- upper_bound += upper_bound;
- upper_bound = SQRTF(upper_bound);
- if (stroke_conversion->fattened)
- {
- upper_bound *= stroke_conversion->line_width;
- }
- n = (vg_lite_uint32_t)ceil(upper_bound);
- if (n == 0 || n > 64)
- {
- n = (vg_lite_uint8_t)(64 / (level + 1));
- }
- for (vg_lite_uint32_t i = 1; i < n; i++) {
- vg_lite_float_t t = (vg_lite_float_t)i / (vg_lite_float_t)n;
- cubic_bezier(&pt[0], &pt[1], curve, t);
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, pt[0], pt[1], vgcFLATTEN_MIDDLE));
- }
- }
- if (level == 0) {
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_END));
- }
- else
- {
- vg_lite_float_t pt[2], t;
- for (int i = 1; i < 4; i++)
- {
- t = (vg_lite_float_t)i / 4;
- cubic_bezier(&pt[0], &pt[1], curve, t);
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, pt[0], pt[1], vgcFLATTEN_MIDDLE));
- }
- if ((v3[0] != rootCurve[6]) || (v3[1] != rootCurve[7]))
- {
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_MIDDLE));
- }
- }
- /* Add extra P3 for outgoing tangent. */
- /* First change P3(point0)'s coordinates to P0/P1/P2. */
- if (level == 0) {
- point0 = stroke_conversion->path_end;
- if (v3[0] != v2[0] || v3[1] != v2[1])
- {
- point0->x = v2[0];
- point0->y = v2[1];
- }
- else if (v3[0] != v1[0] || v3[1] != v1[1])
- {
- point0->x = v1[0];
- point0->y = v1[1];
- }
- else
- {
- point0->x = v0[0];
- point0->y = v0[1];
- }
- /* Add P3 to calculate outgoing tangent. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_NO));
- point1 = stroke_conversion->path_end;
- /* Change point0's coordinates back to P3. */
- point0->x = v3[0];
- point0->y = v3[1];
- point0->length = 0.0f;
- }
- return error;
- }
- split_cubic(subCurve1, subCurve2, curve, 0.5);
- VG_LITE_ERROR_HANDLER(_flatten_cubic_bezier(stroke_conversion, rootCurve, subCurve1, level + 1));
- VG_LITE_ERROR_HANDLER(_flatten_cubic_bezier(stroke_conversion, rootCurve, subCurve2, level + 1));
- if (level == 0) {
- /* Add point 3 separately to avoid cumulative errors. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_END));
- /* Add extra P3 for outgoing tangent. */
- /* First change P3(point0)'s coordinates to P0/P1/P2. */
- point0 = stroke_conversion->path_end;
- if (v3[0] != v2[0] || v3[1] != v2[1])
- {
- point0->x = v2[0];
- point0->y = v2[1];
- }
- else if (v3[0] != v1[0] || v3[1] != v1[1])
- {
- point0->x = v1[0];
- point0->y = v1[1];
- }
- else
- {
- point0->x = v0[0];
- point0->y = v0[1];
- }
- /* Add P3 to calculate outgoing tangent. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_NO));
- point1 = stroke_conversion->path_end;
- /* Change point0's coordinates back to P3. */
- point0->x = v3[0];
- point0->y = v3[1];
- point0->length = 0.0f;
- }
- ErrorHandler:
- return error;
- }
- static vg_lite_error_t _flatten_cubic_bezier_original(
- vg_lite_stroke_t* stroke_conversion,
- vg_lite_float_t curve[8],
- vg_lite_uint8_t level)
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- float* v0, * v1, * v2, * v3;
- float dx3, dy3, d1, d2;
- float subCurve1[8], subCurve2[8];
- vg_lite_path_point_ptr point0, point1;
- if (!stroke_conversion)
- return VG_LITE_INVALID_ARGUMENT;
- if (level > 10) return error;
- v0 = &curve[0];
- v1 = &curve[2];
- v2 = &curve[4];
- v3 = &curve[6];
- if (level == 0) {
- /* Add extra P0 for incoming tangent. */
- point0 = stroke_conversion->path_end;
- /* First add P1/P2/P3 to calculate incoming tangent, which is saved in P0. */
- if (v0[0] != v1[0] || v0[1] != v1[1])
- {
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v1[0], v1[1], vgcFLATTEN_NO));
- }
- else if (v0[0] != v2[0] || v0[1] != v2[1])
- {
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_NO));
- }
- else
- {
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_NO));
- }
- point1 = stroke_conversion->path_end;
- /* Change the point1's coordinates back to P0. */
- point1->x = v0[0];
- point1->y = v0[1];
- point0->length = 0.0f;
- }
- dx3 = v3[0] - v0[0];
- dy3 = v3[1] - v0[1];
- d1 = fabsf((v1[0] - v3[0]) * dy3 - (v1[1] - v3[1]) * dx3);
- d2 = fabsf((v2[0] - v3[0]) * dy3 - (v2[1] - v3[1]) * dx3);
- if ((d1 + d2) * (d1 + d2) < 0.25f * (dx3 * dx3 + dy3 * dy3)) {
- float bound[4];
- bound[0] = MIN(v0[0], v3[0]);
- bound[1] = MIN(v0[1], v3[1]);
- bound[2] = MAX(v0[0], v3[0]);
- bound[3] = MAX(v0[1], v3[1]);
- if (!(v1[0] >= bound[0] && v1[0] <= bound[2] && v1[1] >= bound[1] && v1[1] <= bound[3]) ||
- !(v2[0] >= bound[0] && v2[0] <= bound[2] && v2[1] >= bound[1] && v2[1] <= bound[3])) {
- /* Compute root. */
- float alignedCurve[8];
- float a, b, c, b2ac, root[2], t, pt[2];
- uint8_t rootNum;
- get_aligned_cubic(alignedCurve, curve);
- a = -3.f * alignedCurve[0] + 9.f * alignedCurve[2] - 9.f * alignedCurve[4] + 3.f * alignedCurve[6];
- b = 6.f * alignedCurve[0] - 12.f * alignedCurve[2] + 6.f * alignedCurve[4];
- c = -3.f * alignedCurve[0] + 3.f * alignedCurve[2];
- rootNum = 0;
- if (fabs(a) < 1e-12f) { // linear solution
- t = -c / b;
- if (t > 1e-12f && t < 1.f - 1e-12f)
- root[rootNum++] = t;
- }
- else { // quadtratic solution
- b2ac = b * b - 4.f * a * c;
- if (b2ac > 1e-12f) {
- t = (-b + (float)sqrt(b2ac)) / (2.f * a);
- if (t > 1e-12f && t < 1.f - 1e-12f)
- root[rootNum++] = t;
- t = (-b - (float)sqrt(b2ac)) / (2.f * a);
- if (t > 1e-12f && t < 1.f - 1e-12f)
- root[rootNum++] = t;
- }
- }
- if (rootNum == 2 && root[0] > root[1]) {
- /* Exchange root. */
- float tmp;
- tmp = root[0];
- root[0] = root[1];
- root[1] = tmp;
- }
- for (uint8_t i = 0; i < rootNum; ++i) {
- cubic_bezier(&pt[0], &pt[1], curve, root[i]);
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, pt[0], pt[1], vgcFLATTEN_NO));
- }
- }
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_NO));
- return error;
- }
- split_cubic(subCurve1, subCurve2, curve, 0.5);
- VG_LITE_ERROR_HANDLER(_flatten_cubic_bezier_original(stroke_conversion, subCurve1, level + 1));
- VG_LITE_ERROR_HANDLER(_flatten_cubic_bezier_original(stroke_conversion, subCurve2, level + 1));
- if (level == 0) {
- /* Add point 3 separately to avoid cumulative errors. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_NO));
- /* Add extra P3 for outgoing tangent. */
- /* First change P3(point0)'s coordinates to P0/P1/P2. */
- point0 = stroke_conversion->path_end;
- if (v3[0] != v2[0] || v3[1] != v2[1])
- {
- point0->x = v2[0];
- point0->y = v2[1];
- }
- else if (v3[0] != v1[0] || v3[1] != v1[1])
- {
- point0->x = v1[0];
- point0->y = v1[1];
- }
- else
- {
- point0->x = v0[0];
- point0->y = v0[1];
- }
- /* Add P3 to calculate outgoing tangent. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_NO));
- point1 = stroke_conversion->path_end;
- /* Change point0's coordinates back to P3. */
- point0->x = v3[0];
- point0->y = v3[1];
- point0->length = 0.0f;
- }
- ErrorHandler:
- return error;
- }
- #else
- static vg_lite_error_t
- _flatten_quad_bezier(
- vg_lite_stroke_t * stroke_conversion,
- vg_lite_float_t X0,
- vg_lite_float_t Y0,
- vg_lite_float_t X1,
- vg_lite_float_t Y1,
- vg_lite_float_t X2,
- vg_lite_float_t Y2
- )
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- uint32_t n;
- vg_lite_path_point_ptr point0, point1;
- vg_lite_float_t x, y;
- vg_lite_float_t a1x, a1y, a2x, a2y;
- vg_lite_float_t f1, f2, t1, t2, upper_bound;
- if (!stroke_conversion)
- return VG_LITE_INVALID_ARGUMENT;
- /* Formula.
- * f(t) = (1 - t)^2 * p0 + 2 * t * (1 - t) * p1 + t^2 * p2
- * = a0 + a1 * t + a2 * t^2
- * a0 = p0
- * a1 = 2 * (-p0 + p1)
- * a2 = p0 - 2 * p1 + p2
- */
- x = X1 - X0;
- a1x = x + x;
- y = Y1 - Y0;
- a1y = y + y;
- a2x = X0 - X1 - X1 + X2;
- a2y = Y0 - Y1 - Y1 + Y2;
- /* Step 1: Calculate N. */
- /* Lefan's method. */
- /* dist(t) = ...
- * t2 = ...
- * if 0 <= t2 <= 1
- * upper_bound = dist(t2)
- * else
- * upper_bound = max(dist(0), dist(1))
- * N = ceil(sqrt(upper_bound / epsilon / 8))
- */
- /* Prepare dist(t). */
- f1 = a1x * a2y - a2x * a1y;
- if (f1 != 0.0f)
- {
- if (f1 < 0.0f) f1 = -f1;
- /* Calculate t2. */
- t1 = a2x * a2x + a2y * a2y;
- t2 = -(x * a2x + y * a2y) / t1;
- /* Calculate upper_bound. */
- if (t2 >= 0.0f && t2 <= 1.0f)
- {
- f2 = x + a2x * t2;
- f2 *= f2;
- t1 = y + a2y * t2;
- t1 *= t1;
- upper_bound = t1 + f2;
- }
- else
- {
- f2 = x + a2x;
- f2 *= f2;
- t1 = y + a2y;
- t1 *= t1;
- t2 = t1 + f2;
- t1 = x * x + y * y;
- upper_bound = t1 < t2 ? t1 : t2;
- }
- /* Calculate n. */
- upper_bound = f1 / SQRTF(upper_bound);
- upper_bound = SQRTF(upper_bound);
- if (stroke_conversion->fattened)
- {
- upper_bound *= stroke_conversion->line_width;
- }
- n = (uint32_t) ceil(upper_bound);
- }
- else
- {
- /* n = 0 => n = 256. */
- n = 256;
- }
- if (n == 0 || n > 256)
- {
- n = 256;
- }
- /* Add extra P0 for incoming tangent. */
- point0 = stroke_conversion->path_end;
- /* First add P1 to calculate incoming tangent, which is saved in P0. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X1, Y1, vgcFLATTEN_START));
- point1 = stroke_conversion->path_end;
- /* Change the point1's coordinates back to P0. */
- point1->x = X0;
- point1->y = Y0;
- point0->length = 0.0f;
- if (n > 1)
- {
- vg_lite_float_t d, dsquare, dx, dy, ddx, ddy;
- vg_lite_float_t ratioX, ratioY;
- uint32_t i;
- /* Step 2: Calculate deltas. */
- /* Df(t) = f(t + d) - f(t)
- * = a1 * d + a2 * d^2 + 2 * a2 * d * t
- * DDf(t) = Df(t + d) - Df(t)
- * = 2 * a2 * d^2
- * f(0) = a0
- * Df(0) = a1 * d + a2 * d^2
- * DDf(0) = 2 * a2 * d^2
- */
- d = 1.0f / (vg_lite_float_t) n;
- dsquare = d * d;
- ddx = a2x * dsquare;
- ddy = a2y * dsquare;
- dx = a1x * d + ddx;
- dy = a1y * d + ddy;
- ddx += ddx;
- ddy += ddy;
- /* Step 3: Add points. */
- ratioX = dx / X0;
- if (ratioX < 0.0f) ratioX = -ratioX;
- ratioY = dy / Y0;
- if (ratioY < 0.0f) ratioY = -ratioY;
- if (ratioX > 1.0e-6f && ratioY > 1.0e-6f)
- {
- x = X0;
- y = Y0;
- for (i = 1; i < n; i++)
- {
- x += dx;
- y += dy;
- /* Add a point to subpath. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list_wdelta(stroke_conversion, x, y, dx, dy, vgcFLATTEN_MIDDLE));
- dx += ddx;
- dy += ddy;
- }
- }
- else
- {
- for (i = 1; i < n; i++)
- {
- vg_lite_float_t t = (vg_lite_float_t) i / (vg_lite_float_t) n;
- vg_lite_float_t u = 1.0f - t;
- vg_lite_float_t a0 = u * u;
- vg_lite_float_t a1 = 2.0f * t * u;
- vg_lite_float_t a2 = t * t;
- x = a0 * X0 + a1 * X1 + a2 * X2;
- y = a0 * Y0 + a1 * Y1 + a2 * Y2;
- /* Add a point to subpath. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, x, y, vgcFLATTEN_MIDDLE));
- }
- }
- }
- /* Add point 2 separately to avoid cumulative errors. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X2, Y2, vgcFLATTEN_END));
- /* Add extra P2 for outgoing tangent. */
- /* First change P2(point0)'s coordinates to P1. */
- point0 = stroke_conversion->path_end;
- point0->x = X1;
- point0->y = Y1;
- /* Add P2 to calculate outgoing tangent. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X2, Y2, vgcFLATTEN_NO));
- point1 = stroke_conversion->path_end;
- /* Change point0's coordinates back to P2. */
- point0->x = X2;
- point0->y = Y2;
- point0->length = 0.0f;
- ErrorHandler:
- return error;
- }
- static vg_lite_error_t
- _flatten_cubic_bezier(
- vg_lite_stroke_t * stroke_conversion,
- vg_lite_float_t X0,
- vg_lite_float_t Y0,
- vg_lite_float_t X1,
- vg_lite_float_t Y1,
- vg_lite_float_t X2,
- vg_lite_float_t Y2,
- vg_lite_float_t X3,
- vg_lite_float_t Y3
- )
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- uint32_t n;
- vg_lite_path_point_ptr point0, point1;
- vg_lite_float_t x, y;
- vg_lite_float_t a1x, a1y, a2x, a2y, a3x, a3y;
- vg_lite_float_t ddf0, ddf1, t1, t2, upper_bound;
- if (!stroke_conversion)
- return VG_LITE_INVALID_ARGUMENT;
- /* Formula.
- * f(t) = (1 - t)^3 * p0 + 3 * t * (1 - t)^2 * p1 + 3 * t^2 * (1 - t) * p2 + t^3 * p3
- * = a0 + a1 * t + a2 * t^2 + a3 * t^3
- */
- x = X1 - X0;
- a1x = x + x + x;
- y = Y1 - Y0;
- a1y = y + y + y;
- x = X0 - X1 - X1 + X2;
- a2x = x + x + x;
- y = Y0 - Y1 - Y1 + Y2;
- a2y = y + y + y;
- x = X1 - X2;
- a3x = x + x + x + X3 - X0;
- y = Y1 - Y2;
- a3y = y + y + y + Y3 - Y0;
- /* Step 1: Calculate N. */
- /* Lefan's method. */
- /* df(t)/dt = a1 + 2 * a2 * t + 3 * a3 * t^2
- * d2f(t)/dt2 = 2 * a2 + 6 * a3 * t
- * N = ceil(sqrt(max(ddfx(0)^2 + ddfy(0)^2, ddfx(1)^2 + ddyf(1)^2) / epsilon / 8))
- */
- ddf0 = a2x * a2x + a2y * a2y;
- t1 = a2x + a3x + a3x + a3x;
- t2 = a2y + a3y + a3y + a3y;
- ddf1 = t1 * t1 + t2 * t2;
- upper_bound = ddf0 > ddf1 ? ddf0: ddf1;
- upper_bound = SQRTF(upper_bound);
- upper_bound += upper_bound;
- upper_bound = SQRTF(upper_bound);
- if (stroke_conversion->fattened)
- {
- upper_bound *= stroke_conversion->line_width;
- }
- n = (uint32_t) ceil(upper_bound);
- if (n == 0 || n > 256)
- {
- n = 256;
- }
- /* Add extra P0 for incoming tangent. */
- point0 = stroke_conversion->path_end;
- /* First add P1/P2/P3 to calculate incoming tangent, which is saved in P0. */
- if (X0 != X1 || Y0 != Y1)
- {
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X1, Y1, vgcFLATTEN_START));
- }
- else if (X0 != X2 || Y0 != Y2)
- {
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X2, Y2, vgcFLATTEN_START));
- }
- else
- {
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X3, Y3, vgcFLATTEN_START));
- }
- point1 = stroke_conversion->path_end;
- /* Change the point1's coordinates back to P0. */
- point1->x = X0;
- point1->y = Y0;
- point0->length = 0.0f;
- if (n > 1)
- {
- vg_lite_float_t d, dsquare, dcube, dx, dy, ddx, ddy, dddx, dddy;
- vg_lite_float_t ratioX, ratioY;
- uint32_t i;
- /* Step 2: Calculate deltas */
- /* Df(t) = f(t + d) - f(t)
- * DDf(t) = Df(t + d) - Df(t)
- * DDDf(t) = DDf(t + d) - DDf(t)
- * f(0) = a0
- * Df(0) = a1 * d + a2 * d^2 + a3 * d^3
- * DDf(0) = 2 * a2 * d^2 + 6 * a3 * d^3
- * DDDf(0) = 6 * a3 * d^3
- */
- d = 1.0f / (vg_lite_float_t) n;
- dsquare = d * d;
- dcube = dsquare * d;
- ddx = a2x * dsquare;
- ddy = a2y * dsquare;
- dddx = a3x * dcube;
- dddy = a3y * dcube;
- dx = a1x * d + ddx + dddx;
- dy = a1y * d + ddy + dddy;
- ddx += ddx;
- ddy += ddy;
- dddx *= 6.0f;
- dddy *= 6.0f;
- ddx += dddx;
- ddy += dddy;
- /* Step 3: Add points. */
- ratioX = dx / X0;
- if (ratioX < 0.0f) ratioX = -ratioX;
- ratioY = dy / Y0;
- if (ratioY < 0.0f) ratioY = -ratioY;
- if (ratioX > 1.0e-6f && ratioY > 1.0e-6f)
- {
- x = X0;
- y = Y0;
- for (i = 1; i < n; i++)
- {
- x += dx;
- y += dy;
- /* Add a point to subpath. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list_wdelta(stroke_conversion, x, y, dx, dy, vgcFLATTEN_MIDDLE));
- dx += ddx; ddx += dddx;
- dy += ddy; ddy += dddy;
- }
- }
- else
- {
- for (i = 1; i < n; i++)
- {
- vg_lite_float_t t = (vg_lite_float_t) i / (vg_lite_float_t) n;
- vg_lite_float_t tSquare = t * t;
- vg_lite_float_t tCube = tSquare * t;
- vg_lite_float_t a0 = 1.0f - 3.0f * t + 3.0f * tSquare - tCube;
- vg_lite_float_t a1 = 3.0f * t - 6.0f * tSquare + 3.0f * tCube;
- vg_lite_float_t a2 = 3.0f * tSquare - 3.0f * tCube;
- vg_lite_float_t a3 = tCube;
- x = a0 * X0 + a1 * X1 + a2 * X2 + a3 * X3;
- y = a0 * Y0 + a1 * Y1 + a2 * Y2 + a3 * Y3;
- /* Add a point to subpath. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, x, y, vgcFLATTEN_MIDDLE));
- }
- }
- }
- /* Add point 3 separately to avoid cumulative errors. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X3, Y3, vgcFLATTEN_END));
- /* Add extra P3 for outgoing tangent. */
- /* First change P3(point0)'s coordinates to P0/P1/P2. */
- point0 = stroke_conversion->path_end;
- if (X3 != X2 || Y3 != Y2)
- {
- point0->x = X2;
- point0->y = Y2;
- }
- else if (X3 != X1 || Y3 != Y1)
- {
- point0->x = X1;
- point0->y = Y1;
- }
- else
- {
- point0->x = X0;
- point0->y = Y0;
- }
- /* Add P3 to calculate outgoing tangent. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X3, Y3, vgcFLATTEN_NO));
- point1 = stroke_conversion->path_end;
- /* Change point0's coordinates back to P3. */
- point0->x = X3;
- point0->y = Y3;
- point0->length = 0.0f;
- ErrorHandler:
- return error;
- }
- #endif /* gcFEATURE_VG_SIMPLYFIED_BEZIER */
- #define GETINCREMENT(pointer, datatype_size) \
- (datatype_size - (PTR2SIZE(pointer) & (datatype_size - 1)))
- #define SKIPTODATA(pointer, datatype_size, SIZE) \
- /* Determine the increment value. */ \
- increment = GETINCREMENT(pointer, datatype_size); \
- /* Skip to the data. */ \
- pointer += increment; \
- SIZE -= increment
- #define VGSL_GETVALUE(X) \
- X = get_value(data_pointer); \
- data_pointer += data_type_size; \
- size -= data_type_size
- #define VGSL_GETCOORDXY(X, Y) \
- VGSL_GETVALUE(X); \
- VGSL_GETVALUE(Y); \
- if (is_relative) { X += ox; Y += oy; }
- typedef vg_lite_float_t(*vg_value_getter)(int8_t* Data);
- static vg_lite_error_t _flatten_path(
- vg_lite_stroke_t * stroke_conversion,
- vg_lite_path_t *path
- )
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- uint32_t increment;
- uint8_t is_relative;
- uint32_t size;
- uint32_t path_command;
- uint32_t prev_command;
- uint8_t data_type_size;
- int8_t* data_pointer = NULL;
- int8_t* data_pointer_use = NULL;
- vg_lite_float_t sx, sy;
- vg_lite_float_t ox, oy;
- vg_lite_float_t px, py;
- vg_lite_float_t x0, y0, x1, y1, x2, y2;
- vg_value_getter get_value = NULL;
- if (!stroke_conversion || !path)
- return VG_LITE_INVALID_ARGUMENT;
- sx = sy = ox = oy = px = py = 0.0f;
- prev_command = 0xFF;
- /* Select the data picker. */
- switch (path->format)
- {
- case VG_LITE_S8:
- data_type_size = 1;
- get_value = _GetS8_NS_NB;
- break;
- case VG_LITE_S16:
- data_type_size = 2;
- get_value = _GetS16_NS_NB;
- break;
- case VG_LITE_S32:
- data_type_size = 4;
- get_value = _GetS32_NS_NB;
- break;
- case VG_LITE_FP32:
- data_type_size = 4;
- get_value = _GetF_NS_NB;
- break;
- default:
- error = VG_LITE_INVALID_ARGUMENT;
- goto ErrorHandler;
- }
- if ((path->path_type == VG_LITE_DRAW_FILL_PATH) || (path->path_type == VG_LITE_DRAW_FILL_STROKE_PATH))
- {
- if (path->path_length % (3 * data_type_size) == 0)
- {
- /* add END_PATH if path_data have no END_PATH */
- stroke_conversion->add_end = 1;
- path->path_length = path->path_length + data_type_size;
- data_pointer_use = (int8_t*)vg_lite_os_malloc(path->path_length);
- if (!data_pointer_use)
- return VG_LITE_OUT_OF_RESOURCES;
- memset(data_pointer_use, 0, path->path_length);
- memcpy((int8_t*)data_pointer_use, (int8_t*)path->path, path->path_length - data_type_size);
- vg_lite_os_free(path->path);
- path->path = data_pointer_use;
- path->pdata_internal = 1;
- }
- if (path->add_end == 1)
- {
- stroke_conversion->add_end = 1;
- }
- else
- {
- stroke_conversion->add_end = 0;
- }
- }
- /* Determine the data size. */
- size = path->path_length;
- /* Determine the beginning of the path data. */
- data_pointer = (int8_t*)path->path;
- /* Add an extra gcvVGCMD_MOVE 0.0 0.0 to handle the case the first command is not gcvVGCMD_MOVE. */
- if ((*data_pointer & 0xfe) != VLC_OP_MOVE)
- {
- /* Add first point to subpath. */
- VG_LITE_ERROR_HANDLER(_create_new_point_list(stroke_conversion, 0.f, 0.f, vgcFLATTEN_NO));
- }
- while (size > 0)
- {
- /* Get the command. */
- path_command = *data_pointer & 0x1F;
- /* Assume absolute. */
- is_relative = VGL_FALSE;
- switch (path_command)
- {
- case VLC_OP_END:
- /* Skip the command. */
- size -= 1;
- if (prev_command == VLC_OP_END)
- {
- /* Continuous gcvVGCMD_CLOSE - do nothing. */
- break;
- }
- if ((prev_command & 0xfe) == VLC_OP_MOVE) {
- /* Delete the invalid path list. */
- vg_lite_path_list_ptr path_list_divide = stroke_conversion->cur_list;
- vg_lite_os_free(path_list_divide->path_points);
- vg_lite_os_free(path_list_divide);
- if (stroke_conversion->cur_list == stroke_conversion->path_list_divide) {
- stroke_conversion->cur_list = stroke_conversion->path_list_divide = NULL;
- stroke_conversion->path_end = NULL;
- stroke_conversion->path_points = NULL;
- stroke_conversion->point_count = 0;
- }
- else {
- stroke_conversion->cur_list = stroke_conversion->path_list_divide;
- while (stroke_conversion->cur_list->next != path_list_divide)
- stroke_conversion->cur_list = stroke_conversion->cur_list->next;
- stroke_conversion->path_end = stroke_conversion->cur_list->path_end;
- stroke_conversion->point_count = stroke_conversion->cur_list->point_count;
- stroke_conversion->cur_list->next = NULL;
- }
- break;
- }
- if (!stroke_conversion->add_end)
- {
- /* Check if subPath is already closed. */
- if (ox != sx || oy != sy)
- {
- /* Add a line from current point to the first point of current subpath. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, sx, sy, vgcFLATTEN_NO));
- }
- if (stroke_conversion->path_points != stroke_conversion->path_end)
- {
- /* Copy tangent data from first point to last_point. */
- vg_lite_path_point_ptr first_point = stroke_conversion->path_points;
- vg_lite_path_point_ptr last_point = stroke_conversion->path_end;
- last_point->length = first_point->length;
- last_point->tangentX = first_point->tangentX;
- last_point->tangentY = first_point->tangentY;
- }
- else
- {
- /* Single point path. */
- vg_lite_path_point_ptr point = stroke_conversion->path_points;
- point->tangentX = 0.0f;
- point->tangentY = 0.0f;
- point->length = 0.0f;
- }
- stroke_conversion->cur_list->closed = 1;
- stroke_conversion->closed = 1;
- stroke_conversion->path_end->next = NULL;
- }
- break;
- case VLC_OP_CLOSE:
- /* Skip the command. */
- SKIPTODATA(data_pointer, data_type_size, size);
- if (prev_command == VLC_OP_CLOSE)
- {
- /* Continuous gcvVGCMD_CLOSE - do nothing. */
- break;
- }
- /* Check if subPath is already closed. */
- if (ox != sx || oy != sy)
- {
- /* Add a line from current point to the first point of current subpath. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, sx, sy, vgcFLATTEN_NO));
- }
- if (stroke_conversion->path_points != stroke_conversion->path_end)
- {
- /* Copy tangent data from first point to last_point. */
- vg_lite_path_point_ptr first_point = stroke_conversion->path_points;
- vg_lite_path_point_ptr last_point = stroke_conversion->path_end;
- last_point->length = first_point->length;
- last_point->tangentX = first_point->tangentX;
- last_point->tangentY = first_point->tangentY;
- }
- else
- {
- /* Single point path. */
- vg_lite_path_point_ptr point = stroke_conversion->path_points;
- point->tangentX = 0.0f;
- point->tangentY = 0.0f;
- point->length = 0.0f;
- }
- px = ox = sx;
- py = oy = sy;
- stroke_conversion->cur_list->closed = 1;
- stroke_conversion->closed = 1;
- break;
- case VLC_OP_MOVE_REL:
- is_relative = 1;
- case VLC_OP_MOVE: /* Indicate the beginning of a new sub-path. */
- /* Skip to the data. */
- SKIPTODATA(data_pointer, data_type_size, size);
- VGSL_GETCOORDXY(x0, y0);
- if ((prev_command & 0xfe) == VLC_OP_MOVE) {
- /* Continuous gcvVGCMD_MOVE draw nothing */
- stroke_conversion->path_points->x = x0;
- stroke_conversion->path_points->y = y0;
- }
- else {
- /* First command is gcvVGCMD_MOVE. */
- /* Add first point to subpath. */
- VG_LITE_ERROR_HANDLER(_create_new_point_list(stroke_conversion, x0, y0, vgcFLATTEN_NO));
- }
- sx = px = ox = x0;
- sy = py = oy = y0;
- break;
- case VLC_OP_LINE_REL:
- is_relative = 1;
- case VLC_OP_LINE:
- /* Skip to the data. */
- SKIPTODATA(data_pointer, data_type_size, size);
- VGSL_GETCOORDXY(x0, y0);
- /* Add a point to subpath. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, x0, y0, vgcFLATTEN_NO));
- px = ox = x0;
- py = oy = y0;
- break;
- case VLC_OP_QUAD_REL:
- is_relative = 1;
- case VLC_OP_QUAD:
- /* Skip to the data. */
- SKIPTODATA(data_pointer, data_type_size, size);
- VGSL_GETCOORDXY(x0, y0);
- VGSL_GETCOORDXY(x1, y1);
- if ((ox == x0 && oy == y0) && (ox == x1 && oy == y1))
- {
- /* Degenerated Bezier curve. Becomes a point. */
- /* Discard zero-length segments. */
- }
- else if ((ox == x0 && oy == y0) || (x0 == x1 && y0 == y1))
- {
- /* Degenerated Bezier curve. Becomes a line. */
- /* Add a point to subpath. */
- VG_LITE_ERROR_HANDLER(_add_point_to_point_list( stroke_conversion, x1, y1, vgcFLATTEN_NO));
- }
- else
- {
- #if gcFEATURE_VG_SIMPLYFIED_BEZIER
- vg_lite_float_t curve[6] = { ox, oy, x0, y0, x1, y1 };
- #if (CHIPID != 0x265)
- vg_lite_float_t subCurve[6] = { 0, 0, 0, 0, 0, 0};
- VG_LITE_ERROR_HANDLER(_flatten_quad_bezier(stroke_conversion, curve, subCurve, 0));
- #else
- VG_LITE_ERROR_HANDLER(_flatten_quad_bezier_original(stroke_conversion, curve, 0));
- #endif
- #else
- VG_LITE_ERROR_HANDLER(_flatten_quad_bezier(stroke_conversion, ox, oy, x0, y0, x1, y1));
- #endif
- }
- px = x0;
- py = y0;
- ox = x1;
- oy = y1;
- break;
- case VLC_OP_CUBIC_REL:
- is_relative = 1;
- case VLC_OP_CUBIC:
- /* Skip to the data. */
- SKIPTODATA(data_pointer, data_type_size, size);
- VGSL_GETCOORDXY(x0, y0);
- VGSL_GETCOORDXY(x1, y1);
- VGSL_GETCOORDXY(x2, y2);
- if ((ox == x0 && oy == y0) && (ox == x1 && oy == y1) && (ox == x2 && oy == y2))
- {
- /* Degenerated Bezier curve. Becomes a point. */
- /* Discard zero-length segments. */
- }
- else
- {
- #if gcFEATURE_VG_SIMPLYFIED_BEZIER
- vg_lite_float_t curve[8] = { ox, oy, x0, y0, x1, y1, x2, y2 };
- #if (CHIPID != 0x265)
- vg_lite_float_t subCurve[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
- VG_LITE_ERROR_HANDLER(_flatten_cubic_bezier(stroke_conversion, curve, subCurve, 0));
- #else
- VG_LITE_ERROR_HANDLER(_flatten_cubic_bezier_original(stroke_conversion, curve, 0));
- #endif
- #else
- VG_LITE_ERROR_HANDLER(_flatten_cubic_bezier(stroke_conversion, ox, oy, x0, y0, x1, y1, x2, y2));
- #endif
- }
- px = x1;
- py = y1;
- ox = x2;
- oy = y2;
- break;
- default:
- error = VG_LITE_INVALID_ARGUMENT;
- goto ErrorHandler;
- }
- prev_command = path_command;
- }
- if ((prev_command != VLC_OP_END))
- {
- stroke_conversion->cur_list->path_end->next = NULL;
- stroke_conversion->path_end->next = NULL;
- if (stroke_conversion->point_count == 1)
- {
- /* Single point path. */
- vg_lite_path_point_ptr point = stroke_conversion->path_points;
- point->tangentX = 0.0f;
- point->tangentY = 0.0f;
- point->length = 0.0f;
- }
- }
- ErrorHandler:
- return error;
- }
- static vg_lite_error_t
- _add_point_to_right_stroke_point_list_tail(
- vg_lite_stroke_t * stroke_conversion,
- vg_lite_float_t X,
- vg_lite_float_t Y
- )
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- vg_lite_path_point_ptr point;
- if (!stroke_conversion)
- return VG_LITE_INVALID_ARGUMENT;
- point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*point));
- if (!point)
- return VG_LITE_OUT_OF_RESOURCES;
- memset(point, 0, sizeof(*point));
- point->x = X;
- point->y = Y;
- point->curve_type = CURVE_LINE;
- point->prev = stroke_conversion->right_point;
- point->next = NULL;
- stroke_conversion->right_point->next = point;
- stroke_conversion->right_point = point;
- stroke_conversion->stroke_count++;
- stroke_conversion->last_stroke->point_count++;
- return error;
- }
- static vg_lite_error_t
- _add_point_to_left_point_list_head(
- vg_lite_stroke_t * stroke_conversion,
- vg_lite_float_t X,
- vg_lite_float_t Y
- )
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- vg_lite_path_point_ptr point;
- if (!stroke_conversion)
- return VG_LITE_INVALID_ARGUMENT;
- point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*point));
- if (!point)
- return VG_LITE_OUT_OF_RESOURCES;
- memset(point, 0, sizeof(*point));
- point->x = X;
- point->y = Y;
- point->curve_type = CURVE_LINE;
- point->next = stroke_conversion->left_point;
- point->prev = NULL;
- stroke_conversion->left_point->prev = point;
- stroke_conversion->left_point = point;
- stroke_conversion->stroke_count++;
- stroke_conversion->last_stroke->point_count++;
- return error;
- }
- static vg_lite_error_t _add_stroke_sub_path(
- vg_lite_stroke_t * stroke_conversion,
- vg_lite_sub_path_ptr *sub_path
- )
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- if (!stroke_conversion || !sub_path)
- return VG_LITE_INVALID_ARGUMENT;
- *sub_path = (vg_lite_sub_path_ptr)vg_lite_os_malloc(sizeof(**sub_path));
- if (!*sub_path)
- return VG_LITE_OUT_OF_RESOURCES;
- memset(*sub_path, 0, sizeof(**sub_path));
- if (stroke_conversion->last_stroke != NULL)
- {
- stroke_conversion->last_stroke->next = *sub_path;
- stroke_conversion->last_stroke = *sub_path;
- }
- else
- {
- stroke_conversion->last_stroke = stroke_conversion->stroke_paths = *sub_path;
- }
- return error;
- }
- static vg_lite_error_t
- _add_zero_length_stroke_sub_path(
- vg_lite_stroke_t * stroke_conversion,
- vg_lite_sub_path_ptr *stroke_subpath
- )
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- vg_lite_path_point_ptr new_point,Point;
- vg_lite_sub_path_ptr stroke_sub_path;
- vg_lite_float_t half_width;
- if (!stroke_conversion)
- return VG_LITE_INVALID_ARGUMENT;
- half_width = stroke_conversion->half_width;
- Point = stroke_conversion->path_points;
- if (stroke_conversion->cap_style == VG_LITE_CAP_BUTT)
- {
- /* No need to draw zero-length subPath for gcvCAP_BUTT. */
- error = VG_LITE_SUCCESS;
- goto ErrorHandler;
- }
- VG_LITE_ERROR_HANDLER(_add_stroke_sub_path(stroke_conversion, &stroke_sub_path));
- if (stroke_conversion->cap_style == VG_LITE_CAP_SQUARE)
- {
- /* Draw a square along the point's direction. */
- vg_lite_float_t dx, dy;
- if (Point->tangentX == 0.0f || Point->tangentY == 0.0f)
- {
- dx = half_width;
- dy = 0.0f;
- }
- else
- {
- dx = Point->tangentY * half_width;
- dy = -Point->tangentX * half_width;
- }
- new_point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*new_point));
- if (!new_point)
- return VG_LITE_OUT_OF_RESOURCES;
- memset(new_point, 0, sizeof(*new_point));
- new_point->x = Point->x + dx + dy;
- new_point->y = Point->y - dx + dy;
- new_point->curve_type = CURVE_LINE;
- stroke_sub_path->point_list = stroke_conversion->right_point = new_point;
- stroke_sub_path->point_count = 1;
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
- Point->x + dx - dy, Point->y + dx + dy));
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
- Point->x - dx - dy, Point->y + dx - dy));
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
- Point->x - dx + dy, Point->y - dx - dy));
- }
- else
- {
- /* Draw a circle. */
- new_point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*new_point));
- if (!new_point)
- return VG_LITE_OUT_OF_RESOURCES;
- memset(new_point, 0, sizeof(*new_point));
- new_point->x = Point->x + half_width;
- new_point->y = Point->y;
- new_point->curve_type = CURVE_LINE;
- stroke_sub_path->point_list = stroke_conversion->right_point = new_point;
- stroke_sub_path->point_count = 1;
- /* Add upper half circle. */
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
- Point->x - half_width, Point->y));
- stroke_conversion->right_point->curve_type = CURVE_ARC_SCCW_HALF;
- stroke_conversion->right_point->tangentX = Point->x;
- stroke_conversion->right_point->tangentY = Point->y;
- /* Add lower half circle. */
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
- Point->x + half_width, Point->y));
- stroke_conversion->right_point->curve_type = CURVE_ARC_SCCW_HALF;
- stroke_conversion->right_point->tangentX = Point->x;
- stroke_conversion->right_point->tangentY = Point->y;
- }
- stroke_sub_path->end_point = stroke_conversion->right_point;
- stroke_sub_path->end_point->next = NULL;
- ErrorHandler:
- return error;
- }
- /* Special asin(x) for quick calculation when -sqrt(0.5) <= x <= sqrt(0.5). */
- static vg_lite_float_t _Asin(
- vg_lite_float_t X
- )
- {
- vg_lite_float_t x = X;
- vg_lite_float_t x2 = X * X;
- vg_lite_float_t s = X;
- x *= x2;
- s += x * 0.1660510562575219f;
- x *= x2;
- s += x * 0.084044676143618186f;
- x *= x2;
- s += x * 0.0023776176698039313f;
- x *= x2;
- s += x * 0.10211922020091345f;
- return s;
- }
- /* Special cos(x) for quick calculation when -PI <= x <= PI. */
- static vg_lite_float_t _Cos(
- vg_lite_float_t X
- )
- {
- vg_lite_float_t x2 = X * X;
- vg_lite_float_t x = x2;
- vg_lite_float_t s = 1.0f;
- s -= x * 0.49985163079668843f;
- x *= x2;
- s += x * 0.041518066216932693f;
- x *= x2;
- s -= x * 0.0013422997970712939f;
- x *= x2;
- s += x * 0.000018930111278021357f;
- return s;
- }
- /* Special sin(x) for quick calculation when -PI <= x <= PI. */
- static vg_lite_float_t _Sine(
- vg_lite_float_t X
- )
- {
- vg_lite_float_t x = X;
- vg_lite_float_t x2 = X * X;
- vg_lite_float_t s = X;
- x *= x2;
- s -= x * 0.16664527099620879f;
- x *= x2;
- s += x * 0.0083154803736487041f;
- x *= x2;
- s -= x * 0.00019344151251408578f;
- x *= x2;
- s += x * 0.0000021810214160988925f;
- return s;
- }
- static vg_lite_float_t
- _Angle(
- vg_lite_float_t X,
- vg_lite_float_t Y,
- vg_lite_float_t Length
- )
- {
- vg_lite_float_t angle;
- vg_lite_float_t ux = (X >= 0.0f ? X : -X);
- vg_lite_float_t uy = (Y >= 0.0f ? Y : -Y);
- if (ux > uy)
- {
- angle = ((uy > 0.0f && ux < Length) ? _Asin(uy / Length) : 0.0f);
- }
- else
- {
- angle = ((ux > 0.0f && uy < Length) ? (FLOAT_PI_HALF - _Asin(ux / Length)) : FLOAT_PI_HALF);
- }
- if (X < 0.0f) angle = FLOAT_PI - angle;
- if (Y < 0.0f) angle = -angle;
- return angle;
- }
- /* The arc is always counter clockwise and less than half circle (small). */
- static vg_lite_error_t
- _convert_circle_arc(
- vg_lite_stroke_t *stroke_conversion,
- vg_lite_float_t Radius,
- vg_lite_float_t CenterX,
- vg_lite_float_t CenterY,
- vg_lite_float_t StartX,
- vg_lite_float_t StartY,
- vg_lite_float_t EndX,
- vg_lite_float_t EndY,
- uint8_t Half_circle,
- vg_lite_path_point_ptr *point_list
- )
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- /*gceVGCMD segmentCommand;*/
- vg_lite_float_t theta1, theta_span;
- uint32_t segs;
- vg_lite_float_t theta, theta_half, theta2;
- vg_lite_float_t cos_theta_half;
- vg_lite_float_t control_ratio;
- vg_lite_float_t controlX, controlY, anchorX, anchorY;
- /*gctFLOAT lastX, lastY;*/
- vg_lite_path_point_ptr point, start_point, last_point;
- if (!stroke_conversion || !point_list)
- return VG_LITE_INVALID_ARGUMENT;
- /* Converting. */
- theta1 = _Angle(StartX - CenterX, StartY - CenterY, Radius);
- if (Half_circle)
- {
- theta_span = FLOAT_PI;
- segs = 4;
- theta = FLOAT_PI_QUARTER;
- theta_half = FLOAT_PI_EIGHTH;
- cos_theta_half = FLOAT_COS_PI_EIGHTH;
- }
- else
- {
- theta_span = _Angle(EndX - CenterX, EndY - CenterY, Radius) - theta1;
- if (theta_span == 0.0f)
- {
- /* Handle specail case for huge scaling. */
- *point_list = NULL;
- error = VG_LITE_SUCCESS;
- return error;
- }
- if ((theta_span < 0))
- {
- theta_span += FLOAT_PI_TWO;
- }
- /* Calculate the number of quadratic Bezier curves. */
- /* Assumption: most of angles are small angles. */
- if (theta_span <= FLOAT_PI_QUARTER) segs = 1;
- else if (theta_span <= FLOAT_PI_HALF) segs = 2;
- else if (theta_span <= FLOAT_PI_THREE_QUARTER) segs = 3;
- else segs = 4;
- theta = theta_span / segs;
- theta_half = theta / 2.0f;
- cos_theta_half = _Cos(theta_half);
- }
- /* Determine the segment command. */
- /*egmentCommand = gcvVGCMD_ARC_QUAD;*/
- /* Generate quadratic Bezier curves. */
- start_point = last_point = NULL;
- control_ratio = Radius / cos_theta_half;
- while (segs-- > 0)
- {
- theta1 += theta;
- theta2 = theta1 - theta_half;
- if (theta2 > FLOAT_PI) theta2 -= FLOAT_PI_TWO;
- controlX = CenterX + _Cos(theta2) * control_ratio;
- controlY = CenterY + _Sine(theta2) * control_ratio;
- theta2 = theta1;
- if (theta2 > FLOAT_PI) theta2 -= FLOAT_PI_TWO;
- anchorX = CenterX + _Cos(theta2) * Radius;
- anchorY = CenterY + _Sine(theta2) * Radius;
- if (segs == 0)
- {
- /* Use end point directly to avoid accumulated errors. */
- anchorX = EndX;
- anchorY = EndY;
- }
- /* Add control point. */
- point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*point));
- if (!point)
- return VG_LITE_OUT_OF_RESOURCES;
- memset(point, 0, sizeof(*point));
- point->x = controlX;
- point->y = controlY;
- point->curve_type = CURVE_QUAD_CONTROL;
- if (last_point)
- {
- last_point->next = point;
- last_point = point;
- }
- else
- {
- start_point = last_point = point;
- }
- /* Add anchor point. */
- point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*point));
- if (!point) {
- error = VG_LITE_OUT_OF_RESOURCES;
- goto ErrorHandler;
- }
- memset(point, 0, sizeof(*point));
- point->x = anchorX;
- point->y = anchorY;
- point->curve_type = CURVE_QUAD_ANCHOR;
- last_point->next = point;
- last_point = point;
- }
- if (last_point)
- {
- last_point->next = NULL;
- }
- *point_list = start_point;
- return error;
- ErrorHandler:
- /* Return status. */
- if (start_point) {
- vg_lite_os_free(start_point);
- start_point = last_point = NULL;
- }
- return error;
- }
- static vg_lite_error_t
- _start_new_stroke_sub_path(
- vg_lite_stroke_t * stroke_conversion,
- vg_lite_float_t X,
- vg_lite_float_t Y,
- vg_lite_float_t Dx,
- vg_lite_float_t Dy,
- uint8_t add_end_cap,
- vg_lite_sub_path_ptr *stroke_subpath
- )
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- vg_lite_sub_path_ptr stroke_sub_path;
- vg_lite_path_point_ptr new_point;
- if (!stroke_conversion || !stroke_subpath)
- return VG_LITE_INVALID_ARGUMENT;
- VG_LITE_ERROR_HANDLER(_add_stroke_sub_path(stroke_conversion, &stroke_sub_path));
- new_point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*new_point));
- if (!new_point)
- return VG_LITE_OUT_OF_RESOURCES;
- memset(new_point, 0, sizeof(*new_point));
- new_point->x = X + Dx;
- new_point->y = Y + Dy;
- new_point->prev = NULL;
- new_point->curve_type = CURVE_LINE;
- stroke_conversion->stroke_points = stroke_conversion->right_point = new_point;
- stroke_sub_path->point_list = stroke_conversion->right_point = new_point;
- new_point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*new_point));
- if (!new_point)
- return VG_LITE_OUT_OF_RESOURCES;
- memset(new_point, 0, sizeof(*new_point));
- new_point->x = X - Dx;
- new_point->y = Y - Dy;
- new_point->curve_type = CURVE_LINE;
- new_point->next = NULL;
- stroke_conversion->stroke_end = stroke_conversion->left_point = new_point;
- stroke_conversion->stroke_count = 2;
- stroke_sub_path->end_point = stroke_conversion->left_point = new_point;
- stroke_sub_path->point_count = 2;
- if (add_end_cap)
- {
- /* Add end cap if the subPath is not closed. */
- switch (stroke_conversion->cap_style)
- {
- case VG_LITE_CAP_BUTT:
- /* No adjustment needed. */
- break;
- case VG_LITE_CAP_ROUND:
- /* Add curve. */
- /* Add the starting point again as arc. */
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
- stroke_sub_path->point_list->x, stroke_sub_path->point_list->y));
- stroke_conversion->right_point->curve_type = CURVE_ARC_SCCW_HALF;
- stroke_conversion->right_point->tangentX = X;
- stroke_conversion->right_point->tangentY = Y;
- /* Change the starting point to end point. */
- stroke_sub_path->point_list->x = stroke_sub_path->end_point->x;
- stroke_sub_path->point_list->y = stroke_sub_path->end_point->y;
- break;
- case VG_LITE_CAP_SQUARE:
- stroke_conversion->right_point->x += Dy;
- stroke_conversion->right_point->y -= Dx;
- stroke_conversion->left_point->x += Dy;
- stroke_conversion->left_point->y -= Dx;
- break;
- }
- }
- *stroke_subpath = stroke_sub_path;
- ErrorHandler:
- return error;
- }
- static void
- _adjust_joint_point(
- vg_lite_path_point_ptr Point,
- vg_lite_path_point_ptr join_point,
- vg_lite_float_t X,
- vg_lite_float_t Y,
- vg_lite_float_t Ratio
- )
- {
- vg_lite_float_t mx = (join_point->x + X) / 2.0f;
- vg_lite_float_t my = (join_point->y + Y) / 2.0f;
- vg_lite_float_t dx = mx - Point->x;
- vg_lite_float_t dy = my - Point->y;
- dx = dx * Ratio;
- dy = dy * Ratio;
- join_point->x = Point->x + dx;
- join_point->y = Point->y + dy;
- }
- static uint8_t
- _is_angle_span_acute(
- vg_lite_float_t Ux,
- vg_lite_float_t Uy,
- vg_lite_float_t Vx,
- vg_lite_float_t Vy
- )
- {
- return ((Ux * Vx + Uy * Vy) > 0.0f ? 1 : 0);
- }
- static vg_lite_error_t
- _draw_swing_pie_area(
- vg_lite_stroke_t *stroke_conversion,
- vg_lite_path_point_ptr center_point,
- uint8_t end_at_prev_point
- )
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- if (!stroke_conversion)
- return VG_LITE_INVALID_ARGUMENT;
- if (stroke_conversion->swing_ccw)
- {
- vg_lite_path_point_ptr start_point = stroke_conversion->swing_stroke;
- vg_lite_path_point_ptr end_point = NULL, real_end_point = NULL;
- vg_lite_path_point_ptr point, prev_point;
- uint32_t count = 0;
- {
- if (end_at_prev_point)
- {
- /* Detach the end point from leftStrokePoint. */
- /* The end point will be added back later. */
- real_end_point = stroke_conversion->left_point;
- stroke_conversion->left_point = real_end_point->next;
- stroke_conversion->left_point->prev = NULL;
- }
- VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion,
- center_point->x, center_point->y));
- end_point = stroke_conversion->left_point;
- /* Reverse the point list from startPoint to endPoint. */
- for (point = start_point; point; point = prev_point)
- {
- prev_point = point->prev;
- point->prev = point->next;
- point->next = prev_point;
- count++;
- }
- if (end_point)
- {
- end_point->next = start_point->prev;
- }
- start_point->prev->prev = end_point;
- start_point->prev = NULL;
- stroke_conversion->left_point = start_point;
- VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion,
- center_point->x, center_point->y));
- VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion,
- stroke_conversion->swing_start->x,
- stroke_conversion->swing_start->y));
- VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion,
- end_point->prev->x, end_point->prev->y));
- if (end_at_prev_point)
- {
- if (real_end_point)
- {
- real_end_point->next = stroke_conversion->left_point;
- }
- stroke_conversion->left_point->prev = real_end_point;
- stroke_conversion->left_point = real_end_point;
- }
- }
- }
- else
- {
- vg_lite_path_point_ptr start_point = stroke_conversion->swing_stroke;
- vg_lite_path_point_ptr end_point = NULL, real_end_point = NULL;
- vg_lite_path_point_ptr point, next_point;
- uint32_t count = 0;
- {
- if (end_at_prev_point)
- {
- /* Detach the end point from leftStrokePoint. */
- /* The end point will be added back later. */
- real_end_point = stroke_conversion->right_point;
- stroke_conversion->right_point = real_end_point->prev;
- stroke_conversion->right_point->next = NULL;
- }
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
- center_point->x, center_point->y));
- end_point = stroke_conversion->right_point;
- /* Reverse the point list from startPoint to endPoint. */
- for (point = start_point; point; point = next_point)
- {
- next_point = point->next;
- point->next = point->prev;
- point->prev = next_point;
- count++;
- }
- end_point->prev = start_point->next;
- start_point->next->next = end_point;
- start_point->next = NULL;
- stroke_conversion->right_point = start_point;
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
- center_point->x, center_point->y));
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
- stroke_conversion->swing_start->x,
- stroke_conversion->swing_start->y));
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
- end_point->next->x, end_point->next->y));
- if (end_at_prev_point)
- {
- real_end_point->prev = stroke_conversion->right_point;
- stroke_conversion->right_point->next = real_end_point;
- stroke_conversion->right_point = real_end_point;
- }
- }
- }
- stroke_conversion->swing_handling = SWING_NO;
- ErrorHandler:
- return error;
- }
- static vg_lite_error_t
- _process_line_joint(
- vg_lite_stroke_t * stroke_conversion,
- vg_lite_path_point_ptr Point,
- vg_lite_float_t Length,
- vg_lite_float_t prev_length,
- uint32_t Swing_handling,
- vg_lite_float_t X1,
- vg_lite_float_t Y1,
- vg_lite_float_t X2,
- vg_lite_float_t Y2
- )
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- vg_lite_join_style_t join_style;
- vg_lite_float_t half_width;
- vg_lite_float_t ratio;
- vg_lite_float_t min_length_square;
- vg_lite_float_t cos_theta;
- uint8_t counter_clockwise;
- uint8_t fat_line;
- uint32_t swing_handling = SWING_NO;
- uint8_t handle_short_line = 0;
- if (!stroke_conversion)
- return VG_LITE_INVALID_ARGUMENT;
- join_style = stroke_conversion->join_style;
- half_width = stroke_conversion->half_width;
- fat_line = stroke_conversion->fattened;
- if (stroke_conversion->swing_length < half_width)
- {
- if (stroke_conversion->need_swing)
- {
- swing_handling = SWING_OUT;
- }
- else
- {
- handle_short_line = 1;
- }
- }
- else if (stroke_conversion->stroke_length - stroke_conversion->swing_length < half_width)
- {
- if (stroke_conversion->need_swing)
- {
- swing_handling = SWING_IN;
- }
- else
- {
- handle_short_line = 1;
- }
- }
- if (swing_handling != Swing_handling)
- {
- error = VG_LITE_INVALID_ARGUMENT;
- goto ErrorHandler;
- }
- /* For flattened curves/arcs, the join style is always round. */
- if ((Point->flatten_flag != vgcFLATTEN_NO) && fat_line)
- {
- join_style = VG_LITE_JOIN_ROUND;
- }
- /* First, determine the turn is clockwise or counter-clockwise. */
- cos_theta = Point->prev->tangentX * Point->tangentX + Point->prev->tangentY * Point->tangentY;
- if (cos_theta > FLOAT_ANGLE_EPSILON_COS)
- {
- /* Straight line or semi-straight line--no need to handle join. */
- if (stroke_conversion->swing_handling !=SWING_NO)
- {
- /* Begin to swing to the opposite direction. */
- /* Draw the swing area (pie area). */
- VG_LITE_ERROR_HANDLER(_draw_swing_pie_area(stroke_conversion, Point->prev, 1));
- }
- /* Add the new stroke points. */
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, X1, Y1));
- VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, X2, Y2));
- if (stroke_conversion->swing_handling != SWING_NO)
- {
- stroke_conversion->swing_count++;
- }
- goto endCheck;
- }
- else if (cos_theta < -FLOAT_ANGLE_EPSILON_COS)
- {
- /* Almost 180 degree turn. */
- counter_clockwise = 1;
- ratio = FLOAT_MAX;
- min_length_square = FLOAT_MAX;
- }
- else
- {
- vg_lite_float_t angleSign = Point->prev->tangentX * Point->tangentY - Point->prev->tangentY * Point->tangentX;
- counter_clockwise = (angleSign >= 0.0f ? 1 : 0);
- ratio = 2.0f / (1.0f + cos_theta);
- min_length_square = half_width * half_width * (1.0f - cos_theta) / (1.0f + cos_theta) + 0.02f;
- }
- if (stroke_conversion->swing_handling != SWING_NO)
- {
- if (counter_clockwise != stroke_conversion->swing_ccw)
- {
- /* Swing to the opposite direction. */
- /* Draw the swing area (pie area). */
- VG_LITE_ERROR_HANDLER(_draw_swing_pie_area(stroke_conversion, Point->prev, 1));
- }
- }
- if (counter_clockwise)
- {
- if (stroke_conversion->swing_handling != SWING_NO)
- {
- vg_lite_path_point_ptr prev_point = stroke_conversion->left_point->next; /* Skip the line segment movement. */
- vg_lite_float_t deltaX = X2 - prev_point->x;
- vg_lite_float_t deltaY = Y2 - prev_point->y;
- if (_is_angle_span_acute(stroke_conversion->swing_deltax,
- stroke_conversion->swing_deltay,
- deltaX, deltaY))
- {
- /* Continue swinging. */
- stroke_conversion->swing_deltax = deltaX;
- stroke_conversion->swing_deltay = deltaY;
- }
- else
- {
- /* Swing to the max. */
- /* Draw the swing area (pie area). */
- VG_LITE_ERROR_HANDLER(_draw_swing_pie_area(stroke_conversion, Point->prev, 1));
- }
- }
- /* Check if the miter length is too long for inner intersection. */
- if (stroke_conversion->swing_handling == SWING_NO
- && ! handle_short_line
- && min_length_square <= Length * Length
- && min_length_square <= prev_length * prev_length)
- {
- /* Adjust leftStrokePoint to the intersection point. */
- _adjust_joint_point(Point, stroke_conversion->left_point, X2, Y2, ratio);
- }
- else if (stroke_conversion->swing_handling == SWING_NO && Point->flatten_flag == vgcFLATTEN_NO)
- {
- /* Add the point to avoid incorrect sharp angle. */
- VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, Point->x, Point->y));
- /* Add the point to form a loop to avoid out-of-bound problem. */
- VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, X2, Y2));
- }
- else if (stroke_conversion->swing_handling == SWING_NO && (! fat_line || Swing_handling == SWING_NO))
- {
- /* Flattened line segments should not have sharp angle. */
- /* Add the point to form a loop to avoid out-of-bound problem. */
- VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, X2, Y2));
- }
- else
- {
- if (stroke_conversion->swing_handling == SWING_NO)
- {
- vg_lite_path_point_ptr prev_point = stroke_conversion->left_point;
- /* Start swing handling. */
- stroke_conversion->swing_handling = Swing_handling;
- stroke_conversion->swing_ccw = 1;
- stroke_conversion->swing_start = Point;
- stroke_conversion->swing_centlen = 0.0f;
- stroke_conversion->swing_count= 0;
- /* Save stroking path delta. */
- stroke_conversion->swing_deltax = X2 - prev_point->x;
- stroke_conversion->swing_deltay = Y2 - prev_point->y;
- /* Add extra center point for swing out pie area. */
- /* VIV: [todo] Should adjust prev_point, instead of adding new point? */
- VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, Point->x, Point->y));
- /* Add extra start stroke point for swing out pie area. */
- VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, prev_point->x, prev_point->y));
- stroke_conversion->swing_stroke = stroke_conversion->left_point;
- }
- /* Add curve. */
- /* Note that the curve will be reversed, so the direction is CW. */
- /* Then, left side is in reversed order, so the direction is CCW. */
- VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, X2, Y2));
- stroke_conversion->left_point->curve_type = CURVE_ARC_SCCW;
- stroke_conversion->left_point->tangentX = Point->x;
- stroke_conversion->left_point->tangentY = Point->y;
- stroke_conversion->swing_count++;
- }
- switch (join_style)
- {
- case VG_LITE_JOIN_ROUND:
- if (cos_theta > FLOAT_MIN_ARC_ANGLE_COS)
- {
- /* Add a point. */
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, X1, Y1));
- }
- else
- {
- /* Add curve. */
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, X1, Y1));
- stroke_conversion->right_point->curve_type = CURVE_ARC_SCCW;
- stroke_conversion->right_point->tangentX = Point->x;
- stroke_conversion->right_point->tangentY = Point->y;
- }
- break;
- case VG_LITE_JOIN_MITER:
- if (ratio <= stroke_conversion->miter_square)
- {
- /* Adjust lastRightStrokePoint to the outer intersection point. */
- _adjust_joint_point(Point, stroke_conversion->right_point, X1, Y1, ratio);
- break;
- }
- /* Else use Bevel join style. */
- case VG_LITE_JOIN_BEVEL:
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, X1, Y1));
- break;
- }
- }
- else
- {
- if (stroke_conversion->swing_handling != SWING_NO)
- {
- vg_lite_path_point_ptr prev_point = stroke_conversion->right_point->prev; /* Skip the line segment movement. */
- vg_lite_float_t deltaX = X1 - prev_point->x;
- vg_lite_float_t deltaY = Y1 - prev_point->y;
- if (_is_angle_span_acute(stroke_conversion->swing_deltax,
- stroke_conversion->swing_deltay,
- deltaX, deltaY))
- {
- /* Continue swinging. */
- stroke_conversion->swing_deltax = deltaX;
- stroke_conversion->swing_deltay = deltaY;
- }
- else
- {
- /* Swing to the max. */
- /* Draw the swing area (pie area). */
- VG_LITE_ERROR_HANDLER(_draw_swing_pie_area(stroke_conversion, Point->prev, 1));
- }
- }
- /* Check if the miter length is too long for inner intersection. */
- if (stroke_conversion->swing_handling == SWING_NO
- && ! handle_short_line
- && min_length_square <= Length * Length
- && min_length_square <= prev_length * prev_length)
- {
- /* Adjust lastRightStrokePoint to the intersection point. */
- _adjust_joint_point(Point, stroke_conversion->right_point, X1, Y1, ratio);
- }
- else if (stroke_conversion->swing_handling == SWING_NO && Point->flatten_flag == vgcFLATTEN_NO)
- {
- /* Add the point to avoid incorrect sharp angle. */
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, Point->x, Point->y));
- /* Add the point to form a loop to avoid out-of-bound problem. */
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, X1, Y1));
- }
- else if (stroke_conversion->swing_handling == SWING_NO && (! fat_line || Swing_handling == SWING_NO))
- {
- /* Flattened line segments should not have sharp angle. */
- /* Add the point to form a loop to avoid out-of-bound problem. */
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, X1, Y1));
- }
- else
- {
- if (stroke_conversion->swing_handling == SWING_NO)
- {
- vg_lite_path_point_ptr prev_point = stroke_conversion->right_point;
- /* Start swing handling. */
- stroke_conversion->swing_handling = Swing_handling;
- stroke_conversion->swing_ccw = 0;
- stroke_conversion->swing_start = Point;
- stroke_conversion->swing_centlen = 0.0f;
- stroke_conversion->swing_count= 0;
- /* Save stroking path delta. */
- stroke_conversion->swing_deltax = X1 - prev_point->x;
- stroke_conversion->swing_deltay = Y1 - prev_point->y;
- /* Add extra center point for swing out pie area. */
- /* VIV: [todo] Should adjust prev_point, instead of adding new point? */
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, Point->x, Point->y));
- /* Add extra start stroke point for swing out pie area. */
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, prev_point->x, prev_point->y));
- stroke_conversion->swing_stroke = stroke_conversion->right_point;
- }
- if (cos_theta > FLOAT_MIN_ARC_ANGLE_COS)
- {
- /* Add a point. */
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, X1, Y1));
- }
- else
- {
- /* Add curve. */
- /* Note that the curve will be reversed, so the direction is CCW. */
- stroke_conversion->right_point->curve_type = CURVE_ARC_SCCW;
- stroke_conversion->right_point->tangentX = Point->x;
- stroke_conversion->right_point->tangentY = Point->y;
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, X1, Y1));
- }
- stroke_conversion->swing_count++;
- }
- switch (join_style)
- {
- case VG_LITE_JOIN_ROUND:
- if (cos_theta > FLOAT_MIN_ARC_ANGLE_COS)
- {
- /* Add a point. */
- VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, X2, Y2));
- }
- else
- {
- /* Add curve. */
- stroke_conversion->left_point->curve_type = CURVE_ARC_SCCW;
- stroke_conversion->left_point->tangentX = Point->x;
- stroke_conversion->left_point->tangentY = Point->y;
- VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, X2, Y2));
- }
- break;
- case VG_LITE_JOIN_MITER:
- if (ratio <= stroke_conversion->miter_square)
- {
- /* Adjust leftStrokePoint to the outer intersection point. */
- _adjust_joint_point(Point, stroke_conversion->left_point, X2, Y2, ratio);
- break;
- }
- /* Else use Bevel join style. */
- case VG_LITE_JOIN_BEVEL:
- VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, X2, Y2));
- break;
- }
- }
- endCheck:
- if (stroke_conversion->need_swing)
- {
- stroke_conversion->swing_length += Point->length;
- }
- if (stroke_conversion->swing_handling != SWING_NO)
- {
- if (Point->flatten_flag == vgcFLATTEN_END ||
- (stroke_conversion->swing_handling == SWING_OUT &&
- stroke_conversion->swing_length > half_width))
- {
- /* Draw the swing area (pie area). */
- VG_LITE_ERROR_HANDLER(_draw_swing_pie_area(stroke_conversion, Point, 0));
- }
- else
- {
- /* Check if center line will move too far. */
- stroke_conversion->swing_centlen += Point->length;
- if (stroke_conversion->swing_centlen > FLOAT_SWING_CENTER_RANGE)
- {
- /* Draw the swing area (pie area). */
- VG_LITE_ERROR_HANDLER(_draw_swing_pie_area(stroke_conversion, Point, 0));
- }
- }
- }
- ErrorHandler:
- return error;
- }
- static vg_lite_error_t
- _close_stroke_sub_path(
- vg_lite_stroke_t * stroke_conversion,
- vg_lite_path_point_ptr Point,
- vg_lite_float_t Length,
- vg_lite_float_t prev_length,
- uint8_t Swing_handling,
- vg_lite_path_point_ptr first_stroke_point,
- vg_lite_path_point_ptr last_stroke_point
- )
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- if (!stroke_conversion)
- return VG_LITE_INVALID_ARGUMENT;
- /* Handle line joint style for the first/last point in closed path. */
- VG_LITE_ERROR_HANDLER(_process_line_joint(
- stroke_conversion, Point,
- Length, prev_length, Swing_handling,
- first_stroke_point->x, first_stroke_point->y,
- last_stroke_point->x, last_stroke_point->y
- ));
- if (stroke_conversion->cap_style == VG_LITE_CAP_SQUARE
- && stroke_conversion->join_style == VG_LITE_JOIN_MITER
- && stroke_conversion->pattern_count > 0) {
- stroke_conversion->left_point->x = last_stroke_point->x;
- stroke_conversion->left_point->y = last_stroke_point->y;
- }
- /* Adjust the two end ponts of the first point. */
- first_stroke_point->x = stroke_conversion->right_point->x;
- first_stroke_point->y = stroke_conversion->right_point->y;
- last_stroke_point->x = stroke_conversion->left_point->x;
- last_stroke_point->y = stroke_conversion->left_point->y;
- /* Concatnate right and left point lists. */
- stroke_conversion->right_point->next = stroke_conversion->left_point;
- stroke_conversion->left_point->prev = stroke_conversion->right_point;
- /*gcmERROR_RETURN(_CheckStrokeSubPath(stroke_conversion->lastStrokeSubPath));*/
- ErrorHandler:
- return error;
- }
- static vg_lite_error_t _end_stroke_sub_path(
- vg_lite_stroke_t *stroke_conversion,
- vg_lite_float_t X,
- vg_lite_float_t Y,
- vg_lite_float_t Dx,
- vg_lite_float_t Dy
- )
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- if (!stroke_conversion)
- return VG_LITE_INVALID_ARGUMENT;
- /* Add points for end of line. */
- VG_LITE_RETURN_ERROR(_add_point_to_right_stroke_point_list_tail(stroke_conversion, X + Dx, Y + Dy));
- VG_LITE_RETURN_ERROR(_add_point_to_left_point_list_head(stroke_conversion, X - Dx, Y - Dy));
- /* Add end cap if the subPath is not closed. */
- switch (stroke_conversion->cap_style)
- {
- case VG_LITE_CAP_BUTT:
- /* No adjustment needed. */
- break;
- case VG_LITE_CAP_ROUND:
- /* Add curve. */
- stroke_conversion->left_point->curve_type = CURVE_ARC_SCCW_HALF;
- stroke_conversion->left_point->tangentX = X;
- stroke_conversion->left_point->tangentY = Y;
- break;
- case VG_LITE_CAP_SQUARE:
- stroke_conversion->right_point->x -= Dy;
- stroke_conversion->right_point->y += Dx;
- stroke_conversion->left_point->x -= Dy;
- stroke_conversion->left_point->y += Dx;
- break;
- }
- /* Concatnate right and left point lists. */
- stroke_conversion->right_point->next = stroke_conversion->left_point;
- stroke_conversion->left_point->prev = stroke_conversion->right_point;
- /*gcmERROR_RETURN(_CheckStrokeSubPath(stroke_conversion->lastStrokeSubPath));*/
- return error;
- }
- static vg_lite_error_t _get_next_dash_length(
- vg_lite_stroke_t * stroke_conversion,
- uint32_t * dash_index,
- vg_lite_float_t * dash_length
- )
- {
- if (!stroke_conversion || !dash_index || !dash_length)
- return VG_LITE_INVALID_ARGUMENT;
- (*dash_index)++;
- if (*dash_index == stroke_conversion->pattern_count)
- {
- *dash_index = 0;
- }
- *dash_length = stroke_conversion->dash_pattern[*dash_index];
- return VG_LITE_SUCCESS;
- }
- static vg_lite_error_t
- _create_stroke_path(
- vg_lite_stroke_t * stroke_conversion
- )
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- vg_lite_sub_path_ptr stroke_sub_path = NULL,first_stroke_sub_path = NULL;
- vg_lite_path_point_ptr point, next_point;
- vg_lite_float_t half_width;
- vg_lite_float_t x, y;
- vg_lite_float_t dx, dy, ux, uy;
- vg_lite_float_t length, prev_length, first_length;
- vg_lite_float_t dash_length;
- uint32_t dash_index;
- uint8_t dashing;
- uint8_t add_end_cap;
- uint8_t need_to_handle_swing = 1 /* (stroke_conversion->strokeCapStyle == gcvCAP_BUTT) */;
- vg_lite_uint8_t dash_phase_reset;
- vg_lite_path_point_ptr first_right_point = NULL;
- vg_lite_path_point_ptr last_left_point = NULL;
- vg_lite_float_t first_dx = 0.0f, first_dy = 0.0f;
- uint8_t drawing = 0;
- vg_lite_float_t total_length = 0.0f;
- vg_lite_float_t accu_length = 0.0f;
- uint32_t swing_handling = SWING_NO;
- if (!stroke_conversion)
- return VG_LITE_INVALID_ARGUMENT;
- half_width = stroke_conversion->half_width;
- dashing = stroke_conversion->pattern_count > 0 ? 1 : 0;
- dash_index = stroke_conversion->dash_index;
- dash_length = stroke_conversion->dash_length;
- dash_phase_reset = stroke_conversion->dash_reset;
- /* VIV: [todo] Need to check/debug closed stroke path. */
- need_to_handle_swing = (stroke_conversion->cap_style == VG_LITE_CAP_BUTT || stroke_conversion->closed);
- if (need_to_handle_swing)
- {
- uint8_t reallyneed_to_handle_swing = 0;
- /* Calculate the total length. */
- for (point = stroke_conversion->path_points; point; point = point->next)
- {
- total_length += point->length;
- if (point->flatten_flag != vgcFLATTEN_NO)
- {
- reallyneed_to_handle_swing = 1;
- }
- }
- stroke_conversion->stroke_length = total_length;
- if (reallyneed_to_handle_swing)
- {
- swing_handling = SWING_OUT;
- }
- else
- {
- need_to_handle_swing = 0;
- swing_handling = SWING_NO;
- }
- }
- stroke_conversion->need_swing = need_to_handle_swing;
- point = stroke_conversion->path_points;
- next_point = point->next;
- if (next_point == NULL)
- {
- if (!dashing || ((dash_index & 0x1) == 0))
- {
- /* Single point (zero-length) subpath. */
- /* Note that one-MOVE_TO subpaths are removed during parsing. */
- VG_LITE_ERROR_HANDLER(_add_zero_length_stroke_sub_path(stroke_conversion, &stroke_sub_path));
- }
- goto ErrorHandler;
- }
- /* Adjust closed status for dashing. */
- if (dashing && stroke_conversion->closed && ((dash_index & 0x1) == 1))
- {
- stroke_conversion->closed = VGL_FALSE;
- }
- /* Set add_end_cap. */
- add_end_cap = dashing ? 1: (stroke_conversion->closed ? 0 : 1);
- /* Process first line. */
- first_length = point->length;
- ux = point->tangentX;
- uy = point->tangentY;
- dx = uy * half_width;
- dy = -ux * half_width;
- if (need_to_handle_swing)
- {
- stroke_conversion->swing_length = first_length;
- }
- if (dashing)
- {
- vg_lite_float_t delta_length;
- /* Draw dashes. */
- x = point->x;
- y = point->y;
- do
- {
- if ((dash_index & 0x1) == 0)
- {
- VG_LITE_ERROR_HANDLER(_start_new_stroke_sub_path(
- stroke_conversion,
- x, y,
- dx, dy, add_end_cap,
- &stroke_sub_path
- ));
- drawing = 1;
- add_end_cap = 1;
- if (stroke_conversion->closed && (first_stroke_sub_path == NULL))
- {
- first_stroke_sub_path = stroke_conversion->last_stroke;
- first_right_point = stroke_conversion->right_point;
- last_left_point = stroke_conversion->left_point;
- first_dx = dx;
- first_dy = dy;
- }
- }
- delta_length = first_length - dash_length;
- if (delta_length >= FLOAT_EPSILON)
- {
- /* Move (x, y) forward along the line by dash_length. */
- x += ux * dash_length;
- y += uy * dash_length;
- if ((dash_index & 0x1) == 0)
- {
- VG_LITE_ERROR_HANDLER(_end_stroke_sub_path(
- stroke_conversion,
- x, y,
- dx, dy
- ));
- drawing = 0;
- }
- VG_LITE_ERROR_HANDLER(_get_next_dash_length(stroke_conversion, &dash_index, &dash_length));
- first_length = delta_length;
- }
- else if (delta_length <= -FLOAT_EPSILON)
- {
- dash_length = -delta_length;
- break;
- }
- else
- {
- if ((dash_index & 0x1) == 0)
- {
- VG_LITE_ERROR_HANDLER(_end_stroke_sub_path(
- stroke_conversion,
- next_point->x, next_point->y,
- dx, dy
- ));
- drawing = 0;
- }
- VG_LITE_ERROR_HANDLER(_get_next_dash_length(stroke_conversion, &dash_index, &dash_length));
- first_length = 0;
- break;
- }
- }
- while (1);
- }
- else
- {
- VG_LITE_ERROR_HANDLER(_start_new_stroke_sub_path(
- stroke_conversion,
- point->x, point->y,
- dx, dy, add_end_cap,
- &stroke_sub_path
- ));
- drawing = 1;
- add_end_cap = 1;
- }
- /* Process the rest of lines. */
- prev_length = first_length;
- for (point = next_point, next_point = point->next; next_point;
- point = next_point, next_point = point->next)
- {
- if (!dashing || ((dash_index & 0x1) == 0 && drawing))
- {
- /* Add points for end of line for line join process with next line. */
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
- point->x + dx, point->y + dy));
- VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion,
- point->x - dx, point->y - dy));
- }
- length = point->length;
- ux = point->tangentX;
- uy = point->tangentY;
- dx = uy * half_width;
- dy = -ux * half_width;
- if (need_to_handle_swing)
- {
- accu_length += point->prev->length;
- stroke_conversion->swing_length = accu_length;
- if (accu_length < half_width)
- {
- swing_handling = SWING_OUT;
- }
- else if (total_length - accu_length < half_width)
- {
- swing_handling = SWING_IN;
- }
- else
- {
- swing_handling = SWING_NO;
- }
- }
- if (!dashing)
- {
- /* Handle line joint style. */
- VG_LITE_ERROR_HANDLER(_process_line_joint(
- stroke_conversion, point,
- length, prev_length, swing_handling,
- point->x + dx, point->y + dy,
- point->x - dx, point->y - dy
- ));
- }
- else
- {
- vg_lite_float_t delta_length;
- /* Draw dashes. */
- x = point->x;
- y = point->y;
- if ((dash_index & 0x1) == 0)
- {
- if (drawing)
- {
- /* Handle line joint style. */
- VG_LITE_ERROR_HANDLER(_process_line_joint(
- stroke_conversion, point,
- dash_length, prev_length, swing_handling,
- x + dx, y + dy,
- x - dx, y - dy
- ));
- }
- else
- {
- /* Start a new sub path. */
- VG_LITE_ERROR_HANDLER(_start_new_stroke_sub_path(
- stroke_conversion,
- x, y,
- dx, dy, add_end_cap,
- &stroke_sub_path
- ));
- drawing = 1;
- add_end_cap = 1;
- }
- }
- do
- {
- delta_length = length - dash_length;
- if (delta_length >= FLOAT_EPSILON)
- {
- /* Move (x, y) forward along the line by dash_length. */
- x += ux * dash_length;
- y += uy * dash_length;
- if ((dash_index & 0x1) == 0)
- {
- VG_LITE_ERROR_HANDLER(_end_stroke_sub_path(
- stroke_conversion,
- x, y, dx, dy
- ));
- drawing = 0;
- }
- VG_LITE_ERROR_HANDLER(_get_next_dash_length(stroke_conversion, &dash_index, &dash_length));
- length = delta_length;
- }
- else if (delta_length <= -FLOAT_EPSILON)
- {
- dash_length = -delta_length;
- break;
- }
- else
- {
- if ((dash_index & 0x1) == 0)
- {
- VG_LITE_ERROR_HANDLER(_end_stroke_sub_path(
- stroke_conversion,
- next_point->x, next_point->y,
- dx, dy
- ));
- drawing = 0;
- }
- VG_LITE_ERROR_HANDLER(_get_next_dash_length(stroke_conversion, &dash_index, &dash_length));
- length = 0;
- break;
- }
- if ((dash_index & 0x1) == 0)
- {
- VG_LITE_ERROR_HANDLER(_start_new_stroke_sub_path(
- stroke_conversion,
- x, y,
- dx, dy, add_end_cap,
- &stroke_sub_path
- ));
- drawing = 1;
- add_end_cap = 1;
- }
- }
- while (1);
- }
- prev_length = length;
- }
- if (need_to_handle_swing)
- {
- accu_length += point->prev->length;
- stroke_conversion->swing_length = accu_length;
- if (accu_length < half_width)
- {
- swing_handling = SWING_OUT;
- }
- else if (total_length - accu_length < half_width)
- {
- swing_handling = SWING_IN;
- }
- else
- {
- swing_handling = SWING_NO;
- }
- }
- if (stroke_conversion->swing_handling != SWING_NO)
- {
- /* Draw the swing area (pie area). */
- VG_LITE_ERROR_HANDLER(_draw_swing_pie_area(stroke_conversion, stroke_conversion->path_end, VGL_FALSE));
- }
- if (stroke_conversion->closed)
- {
- if (! dashing || drawing)
- {
- /* Add points for end of line. */
- VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
- point->x + dx, point->y + dy));
- VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion,
- point->x - dx, point->y - dy));
- if (! dashing)
- {
- if (stroke_sub_path)
- {
- /* Handle line joint style for the first/last point in closed path. */
- VG_LITE_ERROR_HANDLER(_close_stroke_sub_path(
- stroke_conversion, point,
- first_length, prev_length, swing_handling,
- stroke_sub_path->point_list, stroke_sub_path->end_point
- ));
- }
- }
- else
- {
- /* Handle line joint style for the first/last point in closed path. */
- if (first_right_point && last_left_point) {
- VG_LITE_ERROR_HANDLER(_close_stroke_sub_path(
- stroke_conversion, point,
- first_length, prev_length, swing_handling,
- first_right_point, last_left_point
- ));
- }else {
- error = VG_LITE_INVALID_ARGUMENT;
- goto ErrorHandler;
- }
- }
- }
- else if (stroke_conversion->cap_style != VG_LITE_CAP_BUTT)
- {
- /* No closing join need. Add end cap for the starting point. */
- if (stroke_conversion->cap_style == VG_LITE_CAP_SQUARE)
- {
- if (first_right_point && last_left_point) {
- first_right_point->x += first_dy;
- first_right_point->y -= first_dx;
- last_left_point->x += first_dy;
- last_left_point->y -= first_dx;
- }else {
- error = VG_LITE_INVALID_ARGUMENT;
- goto ErrorHandler;
- }
- }
- else
- {
- vg_lite_sub_path_ptr last_stroke = stroke_conversion->last_stroke;
- vg_lite_path_point_ptr start_point = last_stroke->point_list;
- vg_lite_path_point_ptr extra_point;
- /* Add curve. */
- /* Add extra point to the beginning with end point's coordinates. */
- extra_point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*extra_point));
- if (!extra_point)
- return VG_LITE_OUT_OF_RESOURCES;
- memset(extra_point, 0, sizeof(*extra_point));
- extra_point->x = last_stroke->end_point->x;
- extra_point->y = last_stroke->end_point->y;
- extra_point->next = start_point;
- start_point->prev = extra_point;
- start_point->curve_type = CURVE_ARC_SCCW;
- start_point->tangentX = stroke_conversion->path_points->x;
- start_point->tangentY = stroke_conversion->path_points->y;
- last_stroke->point_list = extra_point;
- }
- }
- }
- else if (! dashing ||
- (((dash_index & 0x1) == 0) && (dash_length < stroke_conversion->dash_pattern[dash_index])))
- {
- /* Add end cap if the subPath is not closed. */
- VG_LITE_ERROR_HANDLER(_end_stroke_sub_path(
- stroke_conversion,
- point->x, point->y,
- dx, dy
- ));
- drawing = 0;
- }
- if (!dash_phase_reset) {
- /* Update dash index and length for next subpath. */
- if (dashing) {
- if (((dash_index & 0x1) == 1) &&
- (stroke_conversion->dash_pattern[dash_index] - dash_length < FLOAT_EPSILON)) {
- stroke_conversion->dash_index = dash_index - 1;
- stroke_conversion->dash_length = 0;
- }
- else {
- stroke_conversion->dash_index = dash_index;
- stroke_conversion->dash_length = dash_length;
- }
- }
- }
- ErrorHandler:
- return error;
- }
- static vg_lite_error_t _copy_stroke_path(
- vg_lite_stroke_t * stroke_conversion,
- vg_lite_path_t *path
- )
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- vg_lite_path_point_ptr point,prev_point,tmp_point;
- vg_lite_float_t totalsize = 0,real_size = 0;
- float *pfloat;
- char *cpath;
- #if (CHIPID==0x355 || CHIPID==0x255)
- char last_opcode = 0;
- #endif
- void *temp_stroke_data = NULL;
- uint32_t temp_stroke_size;
- vg_lite_sub_path_ptr sub_path;
- vg_lite_float_t half_width;
- #if (CHIPID==0x355)
- vg_lite_buffer_t buffer = { 0 };
- uint32_t bytes;
- #endif
- if (!stroke_conversion || !path)
- return VG_LITE_INVALID_ARGUMENT;
- half_width = stroke_conversion->half_width;
- sub_path = stroke_conversion->stroke_paths;
- if (!stroke_conversion || !path || !sub_path)
- return VG_LITE_SUCCESS;
- while (sub_path)
- {
- tmp_point = prev_point = point = sub_path->point_list;
- totalsize += _commandSize_float[VLC_OP_LINE] * sub_path->point_count + _commandSize_float[VLC_OP_CLOSE];
- for(;tmp_point;tmp_point = tmp_point->next)
- {
- if (tmp_point->curve_type == CURVE_ARC_SCCW || tmp_point->curve_type == CURVE_ARC_SCCW_HALF) {
- totalsize += 4 * _commandSize_float[VLC_OP_QUAD];
- }
- }
- temp_stroke_data = path->stroke_path;
- temp_stroke_size = path->stroke_size;
- path->stroke_size += (int32_t)totalsize;
- #if (CHIPID==0x355)
- if (sub_path->next == NULL) {
- bytes = (8 + path->stroke_size + 7 + 8) & ~7;
- buffer.width = bytes;
- buffer.height = 1;
- buffer.stride = 0;
- buffer.format = VG_LITE_A8;
- VG_LITE_RETURN_ERROR(vg_lite_allocate(&buffer));
- memset(buffer.memory, 0, buffer.stride);
- ((uint32_t*)buffer.memory)[0] = VG_LITE_DATA((path->stroke_size + 7) / 8);
- ((uint32_t*)buffer.memory)[1] = 0;
- if (temp_stroke_data) {
- memcpy((char *)buffer.memory + 8, temp_stroke_data, temp_stroke_size);
- vg_lite_os_free(temp_stroke_data);
- temp_stroke_data = NULL;
- }
- path->stroke_path = 0;
- pfloat = (vg_lite_float_t*)((char*)buffer.memory + 8 + temp_stroke_size);
- }
- else
- #endif
- {
- path->stroke_path = (void*)vg_lite_os_malloc(path->stroke_size);
- if (!path->stroke_path) {
- error = VG_LITE_OUT_OF_RESOURCES;
- goto ErrorHandler;
- }
- memset(path->stroke_path, 0, path->stroke_size);
- if (temp_stroke_data) {
- memcpy(path->stroke_path, temp_stroke_data, temp_stroke_size);
- vg_lite_os_free(temp_stroke_data);
- temp_stroke_data = NULL;
- }
- pfloat = (vg_lite_float_t*)((char*)path->stroke_path + temp_stroke_size);
- }
- #if (CHIPID==0x355 || CHIPID==0x255)
- if (last_opcode == VLC_OP_CLOSE) {
- cpath = (char*)(pfloat - 1) + 1;
- *cpath++ = VLC_OP_MOVE;
- cpath = (char*)pfloat;
- }
- else
- #endif
- {
- cpath = (char*)pfloat;
- *cpath = VLC_OP_MOVE;
- pfloat++;
- }
- *pfloat++ = point->x;
- *pfloat++ = point->y;
- real_size += _commandSize_float[VLC_OP_MOVE];
- #if (CHIPID==0x355 || CHIPID==0x255)
- if (last_opcode == VLC_OP_CLOSE)
- real_size -= 4;
- #endif
- for (point = point->next; point; prev_point = point, point = point->next)
- {
- if (point->curve_type == CURVE_LINE)
- {
- if (point->x == prev_point->x && point->y == prev_point->y)
- {
- path->stroke_size -= _commandSize_float[VLC_OP_LINE];
- /* Skip zero-length lines. */
- continue;
- }
- /* Add new command. */
- cpath = (char *)pfloat;
- *cpath = VLC_OP_LINE;
- pfloat++;
- /* Set the coordinates. */
- *pfloat++ = point->x;
- *pfloat++ = point->y;
- real_size += _commandSize_float[VLC_OP_LINE];
- }
- else if (point->curve_type == CURVE_QUAD_CONTROL)
- {
- /* Add new command. */
- cpath = (char *)pfloat;
- *cpath = VLC_OP_QUAD;
- pfloat++;
- /* Set the coordinates. */
- prev_point = point, point = point->next;
- *pfloat++ = prev_point->x;
- *pfloat++ = prev_point->y;
- *pfloat++ = point->x;
- *pfloat++ = point->y;
- real_size += _commandSize_float[VLC_OP_QUAD];
- }
- else
- {
- vg_lite_path_point_ptr point_list, p, nextP;
- vg_lite_path_point_ptr p2;
- if (point->curve_type == CURVE_ARC_SCCW)
- {
- /* Convert an arc to Bezier curves. */
- VG_LITE_ERROR_HANDLER(_convert_circle_arc(stroke_conversion, half_width,
- point->tangentX, point->tangentY,
- prev_point->x, prev_point->y,
- point->x, point->y,
- 0, &point_list));
- }
- else
- {
- /* Convert a half circle to Bezier curves. */
- VG_LITE_ERROR_HANDLER(_convert_circle_arc(stroke_conversion, half_width,
- point->tangentX, point->tangentY,
- prev_point->x, prev_point->y,
- point->x, point->y,
- 1, &point_list));
- }
- if (point_list)
- {
- for (p = point_list; p; p = nextP)
- {
- /* Add new command. */
- cpath = (char *)pfloat;
- *cpath = VLC_OP_QUAD;
- pfloat++;
- /* Set the coordinates. */
- p2 = p->next;
- nextP = p2->next;
- *pfloat++ = p->x;
- *pfloat++ = p->y;
- *pfloat++ = p2->x;
- *pfloat++ = p2->y;
- real_size += _commandSize_float[VLC_OP_QUAD];
- vg_lite_os_free(p);
- vg_lite_os_free(p2);
- }
- }
- else
- {
- /* Handle special case of huge scaling. */
- /* Add new command. */
- cpath = (char *)pfloat;
- *cpath = VLC_OP_LINE;
- pfloat++;
- /* Set the coordinates. */
- *pfloat++ = point->x;
- *pfloat++ = point->y;
- real_size += _commandSize_float[VLC_OP_LINE];
- }
- }
- }
- /* Create a CLOSE_PATH command at the end. */
- cpath = (char *)pfloat;
- if (sub_path->next)
- *cpath = VLC_OP_CLOSE;
- else
- *cpath = VLC_OP_END;
- real_size += _commandSize_float[VLC_OP_CLOSE];
- path->stroke_size = temp_stroke_size + (int32_t)real_size;
- totalsize = 0;
- real_size = 0;
- sub_path = sub_path->next;
- #if (CHIPID==0x355 || CHIPID==0x255)
- last_opcode = *cpath;
- #endif
- }
- #if (CHIPID==0x355)
- /* Initialize command buffer postfix. */
- ((uint32_t*)buffer.memory)[(bytes >> 2) - 2] = VG_LITE_RETURN();
- ((uint32_t*)buffer.memory)[(bytes >> 2) - 1] = 0;
- /* Mark stroke as uploaded. */
- path->stroke->uploaded.handle = buffer.handle;
- path->stroke->uploaded.address = buffer.address;
- path->stroke->uploaded.memory = buffer.memory;
- path->stroke->uploaded.bytes = bytes;
- VLM_PATH_STROKE_ENABLE_UPLOAD(*path);
- #endif
- ErrorHandler:
- if (temp_stroke_data) {
- vg_lite_os_free(temp_stroke_data);
- temp_stroke_data = NULL;
- }
- return error;
- }
- static vg_lite_error_t _initialize_stroke_dash_parameters(
- vg_lite_stroke_t * stroke_conversion
- )
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- uint32_t count;
- uint32_t i;
- vg_lite_float_t *pattern_src;
- vg_lite_float_t *pattern,*temp_pattern;
- vg_lite_float_t length;
- if (!stroke_conversion)
- return VG_LITE_INVALID_ARGUMENT;
- count = stroke_conversion->pattern_count;
- if (count == 0 || !stroke_conversion->dash_pattern)
- return error;
- length = stroke_conversion->dash_phase;
- /* The last pattern is ignored if the number is odd. */
- if (count & 0x1) count--;
- pattern = (vg_lite_float_t *)vg_lite_os_malloc(count * sizeof(vg_lite_float_t));
- if (!pattern)
- return VG_LITE_OUT_OF_RESOURCES;
- temp_pattern = pattern;
- stroke_conversion->pattern_length = 0.0f;
- pattern_src = stroke_conversion->dash_pattern;
- for (i = 0; i < count; i++, pattern++, pattern_src++)
- {
- if (*pattern_src < 0.0f)
- {
- *pattern = 0.0f;
- }
- else
- {
- *pattern = *pattern_src;
- }
- stroke_conversion->pattern_length += *pattern;
- }
- if (stroke_conversion->pattern_length < FLOAT_EPSILON)
- {
- stroke_conversion->pattern_count = 0;
- vg_lite_os_free(temp_pattern);
- temp_pattern = NULL;
- return error;
- }
- while (length < 0.0f)
- {
- length += stroke_conversion->pattern_length;
- }
- while (length >= stroke_conversion->pattern_length)
- {
- length -= stroke_conversion->pattern_length;
- }
- pattern = stroke_conversion->dash_pattern;
- for (i = 0; i < stroke_conversion->pattern_count; i++, pattern++)
- {
- if (length <= *pattern) break;
- length -= *pattern;
- }
- stroke_conversion->dash_index = i;
- stroke_conversion->dash_length = *pattern - length;
- vg_lite_os_free(temp_pattern);
- temp_pattern = NULL;
- return error;
- }
- vg_lite_error_t vg_lite_update_stroke(
- vg_lite_path_t *path
- )
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- vg_lite_stroke_t * stroke_conversion;
- vg_lite_path_list_ptr cur_list;
- #if gcFEATURE_VG_TRACE_API
- VGLITE_LOG("vg_lite_update_stroke %p\n", path);
- #endif
- if (!path)
- return VG_LITE_INVALID_ARGUMENT;
- if (!path->path_length)
- return VG_LITE_SUCCESS;
- if (!path->path)
- return VG_LITE_INVALID_ARGUMENT;
- if (!path->stroke)
- return VG_LITE_INVALID_ARGUMENT;
- stroke_conversion = path->stroke;
- cur_list = stroke_conversion->cur_list;
- #if (CHIPID==0x355)
- if (path->stroke && path->stroke->uploaded.handle != NULL) {
- vg_lite_kernel_free_t free_cmd;
- free_cmd.memory_handle = path->stroke->uploaded.handle;
- error = vg_lite_kernel(VG_LITE_FREE, &free_cmd);
- if (error != VG_LITE_SUCCESS)
- return error;
- path->stroke->uploaded.address = 0;
- path->stroke->uploaded.bytes = 0;
- path->stroke->uploaded.handle = NULL;
- path->stroke->uploaded.memory = NULL;
- }
- #endif
- /* Free the existing stroke path. */
- if (path->stroke_path)
- {
- vg_lite_os_free(path->stroke_path);
- /* Reset the stroke. */
- path->stroke_path = NULL;
- }
- if (stroke_conversion->line_width >= FLOAT_FAT_LINE_WIDTH
- && stroke_conversion->line_width >= 1.0f)
- {
- stroke_conversion->fattened = 1;
- }
- stroke_conversion->add_end = path->add_end;
- VG_LITE_RETURN_ERROR(_initialize_stroke_dash_parameters(stroke_conversion));
- VG_LITE_RETURN_ERROR(_flatten_path(stroke_conversion, path));
- for (cur_list = stroke_conversion->path_list_divide; cur_list; cur_list = cur_list->next)
- {
- stroke_conversion->path_end = cur_list->path_end;
- stroke_conversion->path_points = cur_list->path_points;
- stroke_conversion->point_count = cur_list->point_count;
- stroke_conversion->closed = cur_list->closed;
- VG_LITE_RETURN_ERROR(_create_stroke_path(stroke_conversion));
- }
- if (stroke_conversion->path_list_divide)
- {
- stroke_conversion->path_end = stroke_conversion->path_list_divide->path_end;
- stroke_conversion->path_points = stroke_conversion->path_list_divide->path_points;
- stroke_conversion->point_count = stroke_conversion->path_list_divide->point_count;
- }
- VG_LITE_RETURN_ERROR(_copy_stroke_path(stroke_conversion, path));
- /* add VLC_OP_END if stroke_path is empty. */
- if (path->stroke_size == 0) {
- path->stroke_path = vg_lite_os_malloc(_commandSize_float[VLC_OP_END]);
- if (!path->stroke_path)
- return VG_LITE_OUT_OF_RESOURCES;
- *(uint8_t*)path->stroke_path = VLC_OP_END;
- path->stroke_size = _commandSize_float[VLC_OP_END];
- }
- return error;
- }
- vg_lite_error_t vg_lite_set_stroke(
- vg_lite_path_t *path,
- vg_lite_cap_style_t cap_style,
- vg_lite_join_style_t join_style,
- vg_lite_float_t line_width,
- vg_lite_float_t miter_limit,
- vg_lite_float_t *dash_pattern,
- vg_lite_uint32_t pattern_count,
- vg_lite_float_t dash_phase,
- vg_lite_color_t stroke_color
- )
- {
- #if gcFEATURE_VG_TRACE_API
- VGLITE_LOG("vg_lite_set_stroke %p %d %d %f %f %p %d %f 0x%08X\n", path, cap_style, join_style, line_width, miter_limit, dash_pattern, pattern_count, dash_phase, stroke_color);
- #endif
- if (!path || line_width <= 0)
- return VG_LITE_INVALID_ARGUMENT;
- if (miter_limit < 1.0f)
- miter_limit = 1.0f;
- if (!path->stroke) {
- path->stroke = (vg_lite_stroke_t *)vg_lite_os_malloc(sizeof(vg_lite_stroke_t));
- if (!path->stroke)
- return VG_LITE_OUT_OF_RESOURCES;
- memset(path->stroke, 0, sizeof(vg_lite_stroke_t));
- }
- else {
- if (path->stroke) {
- if (path->stroke->path_list_divide) {
- vg_lite_path_list_ptr cur_list;
- while (path->stroke->path_list_divide) {
- cur_list = path->stroke->path_list_divide->next;
- if (path->stroke->path_list_divide->path_points) {
- vg_lite_path_point_ptr temp_point;
- while (path->stroke->path_list_divide->path_points) {
- temp_point = path->stroke->path_list_divide->path_points->next;
- vg_lite_os_free(path->stroke->path_list_divide->path_points);
- path->stroke->path_list_divide->path_points = temp_point;
- }
- temp_point = NULL;
- }
- vg_lite_os_free(path->stroke->path_list_divide);
- path->stroke->path_list_divide = cur_list;
- }
- cur_list = NULL;
- }
- if (path->stroke->stroke_paths) {
- vg_lite_sub_path_ptr temp_sub_path;
- while (path->stroke->stroke_paths) {
- temp_sub_path = path->stroke->stroke_paths->next;
- if (path->stroke->stroke_paths->point_list) {
- vg_lite_path_point_ptr temp_point;
- while (path->stroke->stroke_paths->point_list) {
- temp_point = path->stroke->stroke_paths->point_list->next;
- vg_lite_os_free(path->stroke->stroke_paths->point_list);
- path->stroke->stroke_paths->point_list = temp_point;
- }
- temp_point = NULL;
- }
- vg_lite_os_free(path->stroke->stroke_paths);
- path->stroke->stroke_paths = temp_sub_path;
- }
- temp_sub_path = NULL;
- }
- if (path->stroke->dash_pattern)
- vg_lite_os_free(path->stroke->dash_pattern);
- path->stroke_valid = 0;
- }
- memset(path->stroke, 0, sizeof(vg_lite_stroke_t));
- path->stroke_size = 0;
- }
- /* Clamp dash pattern and phase. */
- pattern_count &= 0xFFFFFFFE;
- float* dash_pattern_copy = NULL;
- if (pattern_count > 0) {
- dash_pattern_copy = vg_lite_os_malloc(pattern_count * sizeof(float));
- if (!dash_pattern_copy)
- return VG_LITE_OUT_OF_RESOURCES;
- }
- for (uint32_t i = 0; i < pattern_count; ++i)
- dash_pattern_copy[i] = (dash_pattern[i] > 0.f) ? dash_pattern[i] : 0.f;
- if (dash_phase < 0.f) {
- float dash_total_length = 0.f;
- for (uint32_t i = 0; i < pattern_count; ++i)
- dash_total_length += dash_pattern_copy[i];
- if (dash_total_length > 0.f)
- dash_phase += (int)(-dash_phase / dash_total_length + 1) * dash_total_length;
- else
- dash_phase = 0.f;
- }
- path->stroke->cap_style = cap_style;
- path->stroke->join_style = join_style;
- path->stroke->line_width = line_width;
- path->stroke->miter_limit = miter_limit;
- path->stroke->half_width = line_width / 2.0f;
- path->stroke->miter_square = path->stroke->miter_limit * path->stroke->miter_limit;
- path->stroke->dash_pattern = dash_pattern_copy;
- path->stroke->pattern_count = pattern_count;
- path->stroke->dash_phase = dash_phase;
- path->stroke_color = stroke_color;
- return VG_LITE_SUCCESS;
- }
- #else /* gcFEATURE_VG_STROKE_PATH */
- vg_lite_error_t vg_lite_update_stroke(
- vg_lite_path_t *path
- )
- {
- return VG_LITE_NOT_SUPPORT;
- }
- vg_lite_error_t vg_lite_set_stroke(
- vg_lite_path_t* path,
- vg_lite_cap_style_t cap_style,
- vg_lite_join_style_t join_style,
- vg_lite_float_t line_width,
- vg_lite_float_t miter_limit,
- vg_lite_float_t* dash_pattern,
- vg_lite_uint32_t pattern_count,
- vg_lite_float_t dash_phase,
- vg_lite_color_t stroke_color
- )
- {
- return VG_LITE_NOT_SUPPORT;
- }
- #endif /* gcFEATURE_VG_STROKE_PATH */
- #if gcFEATURE_VG_ARC_PATH
- static vg_lite_float_t _angle(
- vg_lite_float_t Ux,
- vg_lite_float_t Uy,
- vg_lite_float_t Vx,
- vg_lite_float_t Vy
- )
- {
- vg_lite_float_t dot, length, angle, cosVal;
- int32_t sign;
- dot = Ux * Vx + Uy * Vy;
- length = SQRTF(Ux * Ux + Uy * Uy) * SQRTF(Vx * Vx + Vy * Vy);
- sign = (Ux * Vy - Uy * Vx < 0) ? -1 : 1;
- cosVal = dot / length;
- cosVal = CLAMP(cosVal, -1.0f, 1.0f);
- angle = sign * ACOSF(cosVal);
- return angle;
- }
- void compute_quadpathbounds(vg_lite_path_t* path, float currentX, float currentY, float controlX, float controlY, float lastX, float lastY)
- {
- int j = 0;
- float newPointX = 0;
- float newPointY = 0;
- for (j = 1; j <= 256; j++) {
- float t = (float)j / 256;
- float u = 1.0f - t;
- float term1 = u * u;
- float term2 = t * u * 2.0f;
- float term3 = t * t;
- newPointX = currentX * term1 + controlX * term2 + lastX * term3;
- newPointY = currentY * term1 + controlY * term2 + lastY * term3;
- path->bounding_box[0] = MIN(path->bounding_box[0], newPointX);
- path->bounding_box[1] = MIN(path->bounding_box[1], newPointY);
- path->bounding_box[2] = MAX(path->bounding_box[2], newPointX);
- path->bounding_box[3] = MAX(path->bounding_box[3], newPointY);
- }
- }
- vg_lite_error_t _convert_hline(
- vg_lite_float_t EndX,
- vg_lite_float_t EndY,
- uint8_t Relative,
- vg_lite_control_coord_t* coords,
- void** path_data,
- uint32_t* offset,
- uint32_t last_size
- )
- {
- vg_lite_float_t endX, endY;
- uint8_t segmentCommand;
- int32_t segs;
- uint32_t bufferSize;
- char* pchar, * linePath;
- vg_lite_float_t* pfloat;
- /*******************************************************************
- ** Converting.
- */
- if (path_data == NULL || *path_data == NULL || offset == NULL || coords == NULL)
- return VG_LITE_INVALID_ARGUMENT;
- segs = 1;
- if (Relative)
- {
- endX = EndX + coords->lastX;
- endY = EndY + coords->lastY;
- }
- else
- {
- endX = EndX;
- endY = EndY;
- }
- /* Determine the segment command. */
- segmentCommand = Relative
- ? VLC_OP_LINE_REL
- : VLC_OP_LINE;
- /* Determine the size of the buffer required. */
- bufferSize = (1 + 2) * SIZEOF(vg_lite_float_t) * segs;
- linePath = (char*)vg_lite_os_malloc(*offset + bufferSize + last_size);
- if (linePath == NULL)
- return VG_LITE_OUT_OF_RESOURCES;
- #if(CHIPID == 0x355)
- memset(linePath, 0, *offset + bufferSize + last_size);
- #endif
- memcpy(linePath, (char*)*path_data, *offset);
- vg_lite_os_free(*path_data);
- *path_data = linePath;
- pchar = linePath + *offset;
- pfloat = (vg_lite_float_t*)pchar;
- while (segs-- > 0)
- {
- /* Adjust relative coordinates. */
- pchar = (char*)pfloat;
- *pchar = segmentCommand;
- pfloat++;
- if (Relative) {
- *pfloat++ = EndX;
- *pfloat++ = 0;
- }
- else {
- *pfloat++ = EndX;
- *pfloat++ = EndY;
- }
- *offset += (1 + 2) * SIZEOF(vg_lite_float_t);
- }
- /* Update the control coordinates. */
- coords->lastX = endX;
- coords->lastY = endY;
- coords->controlX = endX;
- coords->controlY = endY;
- return VG_LITE_SUCCESS;
- }
- vg_lite_error_t _convert_vline(
- vg_lite_float_t EndX,
- vg_lite_float_t EndY,
- uint8_t Relative,
- vg_lite_control_coord_t* coords,
- void** path_data,
- uint32_t* offset,
- uint32_t last_size
- )
- {
- vg_lite_float_t endX, endY;
- uint8_t segmentCommand;
- int32_t segs;
- uint32_t bufferSize;
- char* pchar, * linePath;
- vg_lite_float_t* pfloat;
- /*******************************************************************
- ** Converting.
- */
- if (path_data == NULL || *path_data == NULL || offset == NULL || coords == NULL)
- return VG_LITE_INVALID_ARGUMENT;
- segs = 1;
- if (Relative)
- {
- endX = EndX + coords->lastX;
- endY = EndY + coords->lastY;
- }
- else
- {
- endX = EndX;
- endY = EndY;
- }
- /* Determine the segment command. */
- segmentCommand = Relative
- ? VLC_OP_LINE_REL
- : VLC_OP_LINE;
- /* Determine the size of the buffer required. */
- bufferSize = (1 + 2) * SIZEOF(vg_lite_float_t) * segs;
- linePath = (char*)vg_lite_os_malloc(*offset + bufferSize + last_size);
- if (linePath == NULL)
- return VG_LITE_OUT_OF_RESOURCES;
- #if(CHIPID == 0x355)
- memset(linePath, 0, *offset + bufferSize + last_size);
- #endif
- memcpy(linePath, (char*)*path_data, *offset);
- vg_lite_os_free(*path_data);
- *path_data = linePath;
- pchar = linePath + *offset;
- pfloat = (vg_lite_float_t*)pchar;
- while (segs-- > 0)
- {
- /* Adjust relative coordinates. */
- pchar = (char*)pfloat;
- *pchar = segmentCommand;
- pfloat++;
- if (Relative) {
- *pfloat++ = 0;
- *pfloat++ = EndY;
- }
- else {
- *pfloat++ = EndX;
- *pfloat++ = EndY;
- }
- *offset += (1 + 2) * SIZEOF(vg_lite_float_t);
- }
- /* Update the control coordinates. */
- coords->lastX = endX;
- coords->lastY = endY;
- coords->controlX = endX;
- coords->controlY = endY;
- return VG_LITE_SUCCESS;
- }
- vg_lite_error_t _convert_scubic(
- vg_lite_float_t EndX,
- vg_lite_float_t EndY,
- vg_lite_float_t ControlX,
- vg_lite_float_t ControlY,
- uint8_t Relative,
- vg_lite_control_coord_t* coords,
- void** path_data,
- uint32_t* offset,
- uint32_t last_size
- )
- {
- vg_lite_float_t endX, endY;
- uint8_t segmentCommand;
- int32_t segs;
- uint32_t bufferSize;
- char* pchar, * cubicPath;
- vg_lite_float_t* pfloat;
- vg_lite_float_t controlX;
- vg_lite_float_t controlY;
- /*******************************************************************
- ** Converting.
- */
- if (path_data == NULL || *path_data == NULL || offset == NULL || coords == NULL)
- return VG_LITE_INVALID_ARGUMENT;
- segs = 1;
- if (Relative)
- {
- endX = EndX + coords->lastX;
- endY = EndY + coords->lastY;
- controlX = coords->lastX + ControlX;
- controlY = coords->lastY + ControlY;
- }
- else
- {
- endX = EndX;
- endY = EndY;
- controlX = ControlX;
- controlY = ControlY;
- }
- /* Determine the segment command. */
- segmentCommand = Relative
- ? VLC_OP_CUBIC_REL
- : VLC_OP_CUBIC;
- /* Determine the size of the buffer required. */
- bufferSize = (1 + 6) * SIZEOF(vg_lite_float_t) * segs;
- cubicPath = (char*)vg_lite_os_malloc(*offset + bufferSize + last_size);
- if (cubicPath == NULL)
- return VG_LITE_OUT_OF_RESOURCES;
- #if(CHIPID == 0x355)
- memset(cubicPath, 0, *offset + bufferSize + last_size);
- #endif
- memcpy(cubicPath, (char*)*path_data, *offset);
- vg_lite_os_free(*path_data);
- *path_data = cubicPath;
- pchar = cubicPath + *offset;
- pfloat = (vg_lite_float_t*)pchar;
- while (segs-- > 0)
- {
- /* Adjust relative coordinates. */
- pchar = (char*)pfloat;
- *pchar = segmentCommand;
- pfloat++;
- if (Relative) {
- /* Calculate the first control point and convert to relative coordinates. */
- *pfloat++ = (2 * coords->lastX - coords->controlX) - coords->lastX;
- *pfloat++ = (2 * coords->lastY - coords->controlY) - coords->lastY;
- *pfloat++ = ControlX;
- *pfloat++ = ControlY;
- *pfloat++ = EndX;
- *pfloat++ = EndY;
- *offset += (1 + 6) * SIZEOF(vg_lite_float_t);
- }
- else {
- *pfloat++ = 2 * coords->lastX - coords->controlX;
- *pfloat++ = 2 * coords->lastY - coords->controlY;
- *pfloat++ = ControlX;
- *pfloat++ = ControlY;
- *pfloat++ = EndX;
- *pfloat++ = EndY;
- *offset += (1 + 6) * SIZEOF(vg_lite_float_t);
- }
- }
- /* Update the control coordinates. */
- coords->lastX = endX;
- coords->lastY = endY;
- coords->controlX = controlX;
- coords->controlY = controlY;
- return VG_LITE_SUCCESS;
- }
- vg_lite_error_t _convert_squad(
- vg_lite_float_t EndX,
- vg_lite_float_t EndY,
- uint8_t Relative,
- vg_lite_control_coord_t* coords,
- void** path_data,
- uint32_t* offset,
- uint32_t last_size
- )
- {
- vg_lite_float_t endX, endY;
- uint8_t segmentCommand;
- int32_t segs;
- uint32_t bufferSize;
- char* pchar, * quadPath;
- vg_lite_float_t* pfloat;
- vg_lite_float_t ControlX1;
- vg_lite_float_t ControlY1;
- vg_lite_float_t controlX;
- vg_lite_float_t controlY;
- /*******************************************************************
- ** Converting.
- */
- if (path_data == NULL || *path_data == NULL || offset == NULL || coords == NULL)
- return VG_LITE_INVALID_ARGUMENT;
- segs = 1;
- if (Relative)
- {
- endX = EndX + coords->lastX;
- endY = EndY + coords->lastY;
- }
- else
- {
- endX = EndX;
- endY = EndY;
- }
- /* Determine the segment command. */
- segmentCommand = Relative
- ? VLC_OP_QUAD_REL
- : VLC_OP_QUAD;
- /* Determine the size of the buffer required. */
- bufferSize = (1 + 4) * SIZEOF(vg_lite_float_t) * segs;
- quadPath = (char*)vg_lite_os_malloc(*offset + bufferSize + last_size);
- if (quadPath == NULL)
- return VG_LITE_OUT_OF_RESOURCES;
- #if(CHIPID == 0x355)
- memset(quadPath, 0, *offset + bufferSize + last_size);
- #endif
- memcpy(quadPath, (char*)*path_data, *offset);
- vg_lite_os_free(*path_data);
- *path_data = quadPath;
- pchar = quadPath + *offset;
- pfloat = (vg_lite_float_t*)pchar;
- while (segs-- > 0)
- {
- /* Adjust relative coordinates. */
- pchar = (char*)pfloat;
- *pchar = segmentCommand;
- pfloat++;
- if (Relative) {
- ControlX1 = *pfloat++ = (2 * coords->lastX - coords->controlX) - coords->lastX;
- ControlY1 = *pfloat++ = (2 * coords->lastY - coords->controlY) - coords->lastY;
- controlX = ControlX1 + coords->lastX;
- controlY = ControlY1 + coords->lastY;
- *pfloat++ = EndX;
- *pfloat++ = EndY;
- *offset += (1 + 4) * SIZEOF(vg_lite_float_t);
- }
- else {
- controlX = *pfloat++ = 2 * coords->lastX - coords->controlX;
- controlY = *pfloat++ = 2 * coords->lastY - coords->controlY;
- *pfloat++ = EndX;
- *pfloat++ = EndY;
- *offset += (1 + 4) * SIZEOF(vg_lite_float_t);
- }
- }
- /* Update the control coordinates. */
- coords->startX = coords->lastX;
- coords->startY = coords->lastY;
- coords->lastX = endX;
- coords->lastY = endY;
- coords->controlX = controlX;
- coords->controlY = controlY;
- return VG_LITE_SUCCESS;
- }
- /*!
- @discussion
- Convert arc to multi-segment bezier curve.
- @param HorRadius
- Major axis radius.
- @param VerRadius
- minor axis radius.
- @param RotAngle
- Rotation angle.
- @param EndX
- End coordinate x.
- @param EndX
- End coordinate y.
- @param CounterClockwise
- If this is 0,anticlockwise rotation,if this is 1,clockwise rotation.
- @param Large
- 1 means big arc,0 means little arc.
- @param Relative
- 1 means absolute coordinates,0 means relative coordinates.
- @param coords
- Including the start point coordinates of the path,the control point of the last segment of the path,
- and the end point of the last segment of the path.
- @param path_data
- Path data usr for internal conversion.
- @param offset
- The offset of path_data.
- @param last_size
- The remain unconverted size of the original path data.
- @result
- Error code. VG_LITE_INVALID_ARGUMENTS to indicate the parameters are wrong.
- */
- vg_lite_error_t _convert_arc(
- vg_lite_float_t HorRadius,
- vg_lite_float_t VerRadius,
- vg_lite_float_t RotAngle,
- vg_lite_float_t EndX,
- vg_lite_float_t EndY,
- uint8_t CounterClockwise,
- uint8_t Large,
- uint8_t Relative,
- vg_lite_control_coord_t* coords,
- void ** path_data,
- uint32_t *offset,
- uint32_t last_size
- )
- {
- vg_lite_float_t endX, endY;
- uint8_t segmentCommand;
- vg_lite_float_t phi, cosPhi, sinPhi;
- vg_lite_float_t dxHalf, dyHalf;
- vg_lite_float_t x1Prime, y1Prime;
- vg_lite_float_t rx, ry;
- vg_lite_float_t x1PrimeSquare, y1PrimeSquare;
- vg_lite_float_t lambda;
- vg_lite_float_t rxSquare, rySquare;
- int32_t sign;
- vg_lite_float_t sq, signedSq;
- vg_lite_float_t cxPrime, cyPrime;
- vg_lite_float_t theta1, thetaSpan;
- int32_t segs;
- vg_lite_float_t theta, ax, ay, x, y;
- vg_lite_float_t controlX, controlY, anchorX, anchorY;
- vg_lite_float_t lastX, lastY;
- uint32_t bufferSize;
- char *pchar, *arcPath;
- vg_lite_float_t *pfloat;
- /*******************************************************************
- ** Converting.
- */
- if (path_data == NULL || *path_data == NULL || offset == NULL || coords == NULL)
- return VG_LITE_INVALID_ARGUMENT;
- if (Relative)
- {
- endX = EndX + coords->lastX;
- endY = EndY + coords->lastY;
- }
- else
- {
- endX = EndX;
- endY = EndY;
- }
- phi = RotAngle / 180.0f * PI;
- cosPhi = COSF(phi);
- sinPhi = SINF(phi);
- if (Relative)
- {
- dxHalf = - EndX / 2.0f;
- dyHalf = - EndY / 2.0f;
- }
- else
- {
- dxHalf = (coords->lastX - endX) / 2.0f;
- dyHalf = (coords->lastY - endY) / 2.0f;
- }
- x1Prime = cosPhi * dxHalf + sinPhi * dyHalf;
- y1Prime = -sinPhi * dxHalf + cosPhi * dyHalf;
- rx = FABSF(HorRadius);
- ry = FABSF(VerRadius);
- x1PrimeSquare = x1Prime * x1Prime;
- y1PrimeSquare = y1Prime * y1Prime;
- lambda = x1PrimeSquare / (rx * rx) + y1PrimeSquare / (ry * ry);
- if (lambda > 1.0f)
- {
- rx *= SQRTF(lambda);
- ry *= SQRTF(lambda);
- }
- rxSquare = rx * rx;
- rySquare = ry * ry;
- sign = (Large == CounterClockwise) ? -1 : 1;
- sq = ( rxSquare * rySquare
- - rxSquare * y1PrimeSquare
- - rySquare * x1PrimeSquare
- )
- /
- ( rxSquare * y1PrimeSquare
- + rySquare * x1PrimeSquare
- );
- signedSq = sign * ((sq < 0) ? 0 : SQRTF(sq));
- cxPrime = signedSq * (rx * y1Prime / ry);
- cyPrime = signedSq * -(ry * x1Prime / rx);
- theta1 = _angle(1, 0, (x1Prime - cxPrime) / rx, (y1Prime - cyPrime) / ry);
- theta1 = FMODF(theta1, 2 * PI);
- thetaSpan = _angle(( x1Prime - cxPrime) / rx, ( y1Prime - cyPrime) / ry,
- (-x1Prime - cxPrime) / rx, (-y1Prime - cyPrime) / ry);
- if (!CounterClockwise && (thetaSpan > 0))
- {
- thetaSpan -= 2 * PI;
- }
- else if (CounterClockwise && (thetaSpan < 0))
- {
- thetaSpan += 2 * PI;
- }
- thetaSpan = FMODF(thetaSpan, 2 * PI);
- /*******************************************************************
- ** Drawing.
- */
- segs = (int32_t) (CEILF(FABSF(thetaSpan) / (45.0f / 180.0f * PI)));
- theta = thetaSpan / segs;
- ax = coords->lastX - COSF(theta1) * rx;
- ay = coords->lastY - SINF(theta1) * ry;
- if (FABSF(HorRadius) != 0 &&
- FABSF(VerRadius) != 0 &&
- (endX != coords->lastX || endY != coords->lastY)) {
- /* Determine the segment command. */
- segmentCommand = Relative
- ? VLC_OP_QUAD_REL
- : VLC_OP_QUAD;
- /* Determine the size of the buffer required. */
- bufferSize = (1 + 2 * 2) * SIZEOF(vg_lite_float_t) * segs;
- arcPath = (char*)vg_lite_os_malloc(*offset + bufferSize + last_size);
- if (arcPath == NULL)
- return VG_LITE_OUT_OF_RESOURCES;
- #if(CHIPID == 0x355)
- memset(arcPath, 0, *offset + bufferSize + last_size);
- #endif
- memcpy(arcPath, (char*)*path_data, *offset);
- vg_lite_os_free(*path_data);
- *path_data = arcPath;
- pchar = arcPath + *offset;
- pfloat = (vg_lite_float_t*)pchar;
- /* Set initial last point. */
- lastX = coords->lastX;
- lastY = coords->lastY;
- while (segs-- > 0)
- {
- theta1 += theta;
- controlX = ax + COSF(theta1 - (theta / 2.0f)) * rx / COSF(theta / 2.0f);
- controlY = ay + SINF(theta1 - (theta / 2.0f)) * ry / COSF(theta / 2.0f);
- anchorX = ax + COSF(theta1) * rx;
- anchorY = ay + SINF(theta1) * ry;
- if (RotAngle != 0)
- {
- x = coords->lastX + cosPhi * (controlX - coords->lastX) - sinPhi * (controlY - coords->lastY);
- y = coords->lastY + sinPhi * (controlX - coords->lastX) + cosPhi * (controlY - coords->lastY);
- controlX = x;
- controlY = y;
- x = coords->lastX + cosPhi * (anchorX - coords->lastX) - sinPhi * (anchorY - coords->lastY);
- y = coords->lastY + sinPhi * (anchorX - coords->lastX) + cosPhi * (anchorY - coords->lastY);
- anchorX = x;
- anchorY = y;
- }
- if (segs == 0)
- {
- /* Use end point directly to avoid accumulated errors. */
- anchorX = endX;
- anchorY = endY;
- }
- /* Adjust relative coordinates. */
- if (Relative)
- {
- vg_lite_float_t nextLastX = anchorX;
- vg_lite_float_t nextLastY = anchorY;
- controlX -= lastX;
- controlY -= lastY;
- anchorX -= lastX;
- anchorY -= lastY;
- lastX = nextLastX;
- lastY = nextLastY;
- }
- pchar = (char*)pfloat;
- *pchar = segmentCommand;
- pfloat++;
- *pfloat++ = controlX;
- *pfloat++ = controlY;
- *pfloat++ = anchorX;
- *pfloat++ = anchorY;
- *offset += (1 + 2 * 2) * SIZEOF(vg_lite_float_t);
- }
- }
- else {
- /* Determine the segment command. */
- segmentCommand = Relative
- ? VLC_OP_LINE_REL
- : VLC_OP_LINE;
- /* Determine the size of the buffer required. */
- bufferSize = (1 + 2) * SIZEOF(vg_lite_float_t);
- arcPath = (char*)vg_lite_os_malloc(*offset + bufferSize + last_size);
- if (arcPath == NULL)
- return VG_LITE_OUT_OF_RESOURCES;
- memcpy(arcPath, (char*)*path_data, *offset);
- vg_lite_os_free(*path_data);
- *path_data = arcPath;
- pchar = arcPath + *offset;
- pfloat = (vg_lite_float_t*)pchar;
- pchar = (char*)pfloat;
- *pchar = segmentCommand;
- pfloat++;
- *pfloat++ = Relative ? EndX : endX;
- *pfloat++ = Relative ? EndY : endY;
- *offset += (1 + 2) * SIZEOF(vg_lite_float_t);
- }
- /* Update the control coordinates. */
- coords->lastX = endX;
- coords->lastY = endY;
- coords->controlX = endX;
- coords->controlY = endY;
- return VG_LITE_SUCCESS;
- }
- vg_lite_error_t vg_lite_init_arc_path(vg_lite_path_t* path,
- vg_lite_format_t data_format,
- vg_lite_quality_t quality,
- vg_lite_uint32_t path_length,
- vg_lite_pointer path_data,
- vg_lite_float_t min_x, vg_lite_float_t min_y,
- vg_lite_float_t max_x, vg_lite_float_t max_y)
- {
- vg_lite_error_t error = VG_LITE_SUCCESS;
- uint32_t i = 0, j, command = 0, offset = 0;
- vg_lite_float_t moveToX, moveToY, lineToX, lineToY, controlX, controlY, quadToX, quadToY;
- vg_lite_float_t controlX1, controlY1, controlX2, controlY2, cubicToX, cubicToY;
- vg_lite_float_t horRadius, verRadius, rotAngle, endX, endY;
- float* pfloat, * fpath;
- char* cpath, * pathdata;
- vg_lite_control_coord_t coords;
- char add_end = path->add_end;
- vg_lite_int32_t bytes;
- vg_lite_pointer path_data_fp32 = path_data;
- int8_t cmd, * path_data_s8_ptr;
- int16_t* path_data_s16_ptr;
- int32_t* path_data_s32_ptr;
- float* path_data_fp32_ptr;
- int32_t data_size, num = 0;
- memset(&coords, 0, sizeof(vg_lite_control_coord_t));
- coords.lastX = s_context.path_lastX;
- coords.lastY = s_context.path_lastY;
- #if gcFEATURE_VG_TRACE_API
- VGLITE_LOG("vg_lite_init_arc_path %p %d %d %d %p %f %f %f %f\n", path, data_format, quality, path_length, path_data, min_x, min_y, max_x, max_y);
- #endif
- if (path == NULL || path_data == NULL)
- return VG_LITE_INVALID_ARGUMENT;
- /* Path data cannot end with a CLOSE op. Replace CLOSE with END for path_data */
- data_size = get_data_size(data_format);
- num = path_length / data_size;
- switch (data_format)
- {
- case VG_LITE_S8:
- if (path_data && (*((char*)path_data + num - 1) == VLC_OP_CLOSE))
- {
- *(char*)((int*)path_data + num - 1) = VLC_OP_END;
- }
- break;
- case VG_LITE_S16:
- if (path_data && (*(char*)((short*)path_data + num - 1) == VLC_OP_CLOSE))
- {
- *(char*)((short*)path_data + num - 1) = VLC_OP_END;
- }
- break;
- case VG_LITE_S32:
- if (path_data && (*(char*)((int*)path_data + num - 1) == VLC_OP_CLOSE))
- {
- *(char*)((int*)path_data + num - 1) = VLC_OP_END;
- }
- break;
- case VG_LITE_FP32:
- if (path_data && (*(char*)((float*)path_data + num - 1) == VLC_OP_CLOSE))
- {
- *(char*)((float*)path_data + num - 1) = VLC_OP_END;
- }
- break;
- default:
- break;
- }
- /* Convert path format into float. */
- switch (data_format)
- {
- case VG_LITE_S8:
- /* src_s8, dst_fp32 */
- bytes = path_length * 4;
- path_data_fp32 = vg_lite_os_malloc(bytes);
- if (path_data_fp32 == NULL)
- return VG_LITE_OUT_OF_RESOURCES;
- memset(path_data_fp32, 0, bytes);
- path_data_fp32_ptr = path_data_fp32;
- path_data_s8_ptr = (int8_t*)path_data;
- i = 0;
- while (i < path_length){
- cmd = *(uint8_t*)path_data_s8_ptr;
- *(uint8_t*)path_data_fp32_ptr = cmd;
- path_data_s8_ptr++;
- path_data_fp32_ptr++;
- for (j = 0; j < _commandSize_float[cmd] / 4 - 1; j++) {
- *path_data_fp32_ptr = (float)(*path_data_s8_ptr);
- path_data_fp32_ptr++;
- path_data_s8_ptr++;
- }
- i += _commandSize_float[cmd] / 4;
- }
- path_length *= 4;
- break;
- case VG_LITE_S16:
- /* src_s16, dst_fp32 */
- bytes = path_length * 2;
- path_data_fp32 = vg_lite_os_malloc(bytes);
- if (path_data_fp32 == NULL)
- return VG_LITE_OUT_OF_RESOURCES;
- memset(path_data_fp32, 0, bytes);
- path_data_fp32_ptr = path_data_fp32;
- path_data_s16_ptr = (int16_t*)path_data;
- i = 0;
- while (i < path_length) {
- cmd = *(uint8_t*)path_data_s16_ptr;
- *(uint8_t*)path_data_fp32_ptr = cmd;
- path_data_s16_ptr++;
- path_data_fp32_ptr++;
- for (j = 0; j < _commandSize_float[cmd] / 4 - 1; j++) {
- *path_data_fp32_ptr = (float)(*path_data_s16_ptr);
- path_data_fp32_ptr++;
- path_data_s16_ptr++;
- }
- i += _commandSize_float[cmd] / 2;
- }
- path_length *= 2;
- break;
- case VG_LITE_S32:
- /* src_s32, dst_fp32 */
- bytes = path_length;
- path_data_fp32 = vg_lite_os_malloc(bytes);
- if (path_data_fp32 == NULL)
- return VG_LITE_OUT_OF_RESOURCES;
- memset(path_data_fp32, 0, bytes);
- path_data_fp32_ptr = path_data_fp32;
- path_data_s32_ptr = (int32_t*)path_data;
- i = 0;
- while (i < path_length) {
- cmd = *(uint8_t*)path_data_s32_ptr;
- *(uint8_t*)path_data_fp32_ptr = cmd;
- path_data_s32_ptr++;
- path_data_fp32_ptr++;
- for (j = 0; j < _commandSize_float[cmd] / 4 - 1; j++) {
- *path_data_fp32_ptr = (float)(*path_data_s32_ptr);
- path_data_fp32_ptr++;
- path_data_s32_ptr++;
- }
- i += _commandSize_float[cmd];
- }
- break;
- case VG_LITE_FP32: {
- /* src_fp32, dst_fp32 */
- bytes = path_length;
- path_data_fp32 = vg_lite_os_malloc(bytes);
- if (path_data_fp32 == NULL)
- return VG_LITE_OUT_OF_RESOURCES;
- #if(CHIPID == 0x355)
- memset(path_data_fp32, 0, bytes);
- #endif
- memcpy(path_data_fp32, path_data, bytes);
- break;
- }
- default:
- break;
- }
- vg_lite_clear_path(path);
- data_format = VG_LITE_FP32;
- if (!path_length)
- {
- path->format = data_format;
- path->quality = quality;
- path->bounding_box[0] = min_x;
- path->bounding_box[1] = min_y;
- path->bounding_box[2] = max_x;
- path->bounding_box[3] = max_y;
- path->path_length = 0;
- path->path = NULL;
- path->pdata_internal = 1;
- path->path_changed = 1;
- path->uploaded.address = 0;
- path->uploaded.bytes = 0;
- path->uploaded.handle = NULL;
- path->uploaded.memory = NULL;
- return VG_LITE_SUCCESS;
- }
- path->add_end = add_end;
- path->bounding_box[0] = min_x;
- path->bounding_box[1] = min_y;
- path->bounding_box[2] = max_x;
- path->bounding_box[3] = max_y;
- pathdata = (char*)vg_lite_os_malloc(path_length);
- if (pathdata == NULL)
- return VG_LITE_OUT_OF_RESOURCES;
- #if(CHIPID == 0x355)
- memset(pathdata, 0, path_length);
- #endif
- pfloat = (vg_lite_float_t*)path_data_fp32;
- i = 0;
- while (i < path_length)
- {
- cpath = (char*)pfloat;
- command = (uint32_t)*cpath;
- pfloat++;
- switch (command)
- {
- case VLC_OP_END:
- cpath = (char*)pathdata + offset;
- fpath = (vg_lite_float_t*)cpath;
- *cpath = VLC_OP_END;
- offset += _commandSize_float[VLC_OP_END];
- i += _commandSize_float[VLC_OP_END];
- break;
- case VLC_OP_CLOSE:
- /* Update the control coordinates. */
- coords.lastX = coords.startX;
- coords.lastY = coords.startY;
- coords.controlX = coords.startX;
- coords.controlY = coords.startY;
- cpath = (char*)pathdata + offset;
- fpath = (vg_lite_float_t*)cpath;
- *cpath = VLC_OP_CLOSE;
- offset += _commandSize_float[VLC_OP_CLOSE];
- i += _commandSize_float[VLC_OP_CLOSE];
- break;
- case VLC_OP_MOVE:
- moveToX = *pfloat;
- pfloat++;
- moveToY = *pfloat;
- pfloat++;
- /* Update the control coordinates. */
- coords.startX = moveToX;
- coords.startY = moveToY;
- coords.lastX = moveToX;
- coords.lastY = moveToY;
- coords.controlX = moveToX;
- coords.controlY = moveToY;
- cpath = (char*)pathdata + offset;
- fpath = (vg_lite_float_t*)cpath;
- *cpath = VLC_OP_MOVE;
- fpath++;
- *fpath = moveToX;
- fpath++;
- *fpath = moveToY;
- fpath++;
- offset += _commandSize_float[VLC_OP_MOVE];
- i += _commandSize_float[VLC_OP_MOVE];
- break;
- case VLC_OP_MOVE_REL:
- moveToX = *pfloat;
- pfloat++;
- moveToY = *pfloat;
- pfloat++;
- cpath = (char*)pathdata + offset;
- fpath = (vg_lite_float_t*)cpath;
- *cpath = VLC_OP_MOVE_REL;
- fpath++;
- *fpath = moveToX;
- fpath++;
- *fpath = moveToY;
- fpath++;
- offset += _commandSize_float[VLC_OP_MOVE_REL];
- i += _commandSize_float[VLC_OP_MOVE_REL];
- /* Determine the absolute coordinates. */
- moveToX += coords.lastX;
- moveToY += coords.lastY;
- /* Update the control coordinates. */
- coords.startX = moveToX;
- coords.startY = moveToY;
- coords.lastX = moveToX;
- coords.lastY = moveToY;
- coords.controlX = moveToX;
- coords.controlY = moveToY;
- break;
- case VLC_OP_LINE:
- lineToX = *pfloat;
- pfloat++;
- lineToY = *pfloat;
- pfloat++;
- /* Update the control coordinates. */
- coords.lastX = lineToX;
- coords.lastY = lineToY;
- coords.controlX = lineToX;
- coords.controlY = lineToY;
- cpath = (char*)pathdata + offset;
- fpath = (vg_lite_float_t*)cpath;
- *cpath = VLC_OP_LINE;
- fpath++;
- *fpath = lineToX;
- fpath++;
- *fpath = lineToY;
- fpath++;
- offset += _commandSize_float[VLC_OP_LINE];
- i += _commandSize_float[VLC_OP_LINE];
- break;
- case VLC_OP_LINE_REL:
- lineToX = *pfloat;
- pfloat++;
- lineToY = *pfloat;
- pfloat++;
- cpath = (char*)pathdata + offset;
- fpath = (vg_lite_float_t*)cpath;
- *cpath = VLC_OP_LINE_REL;
- fpath++;
- *fpath = lineToX;
- fpath++;
- *fpath = lineToY;
- fpath++;
- offset += _commandSize_float[VLC_OP_LINE_REL];
- i += _commandSize_float[VLC_OP_LINE_REL];
- /* Determine the absolute coordinates. */
- lineToX += coords.lastX;
- lineToY += coords.lastY;
- /* Update the control coordinates. */
- coords.lastX = lineToX;
- coords.lastY = lineToY;
- coords.controlX = lineToX;
- coords.controlY = lineToY;
- break;
- case VLC_OP_QUAD:
- controlX = *pfloat;
- pfloat++;
- controlY = *pfloat;
- pfloat++;
- quadToX = *pfloat;
- pfloat++;
- quadToY = *pfloat;
- pfloat++;
- compute_quadpathbounds(path, coords.lastX, coords.lastY, controlX, controlY, quadToX, quadToY);
- /* Update the control coordinates. */
- coords.lastX = quadToX;
- coords.lastY = quadToY;
- coords.controlX = controlX;
- coords.controlY = controlY;
- cpath = (char*)pathdata + offset;
- fpath = (vg_lite_float_t*)cpath;
- *cpath = VLC_OP_QUAD;
- fpath++;
- *fpath = controlX;
- fpath++;
- *fpath = controlY;
- fpath++;
- *fpath = quadToX;
- fpath++;
- *fpath = quadToY;
- fpath++;
- offset += _commandSize_float[VLC_OP_QUAD];
- i += _commandSize_float[VLC_OP_QUAD];
- break;
- case VLC_OP_SQUAD:
- quadToX = *pfloat;
- pfloat++;
- quadToY = *pfloat;
- pfloat++;
- i += _commandSize_float[VLC_OP_SQUAD];
- /* Update the control coordinates. */
- VG_LITE_ERROR_HANDLER(_convert_squad(quadToX, quadToY, VGL_FALSE, &coords, (void*)&pathdata, &offset, path_length - i));
- compute_quadpathbounds(path, coords.startX, coords.startY, coords.controlX, coords.controlY, quadToX, quadToY);
- break;
- case VLC_OP_SQUAD_REL:
- quadToX = *pfloat;
- pfloat++;
- quadToY = *pfloat;
- pfloat++;
- i += _commandSize_float[VLC_OP_SQUAD_REL];
- /* Update the control coordinates. */
- VG_LITE_ERROR_HANDLER(_convert_squad(quadToX, quadToY, VGL_TRUE, &coords, (void*)&pathdata, &offset, path_length - i));
- break;
- case VLC_OP_QUAD_REL:
- controlX = *pfloat;
- pfloat++;
- controlY = *pfloat;
- pfloat++;
- quadToX = *pfloat;
- pfloat++;
- quadToY = *pfloat;
- pfloat++;
- cpath = (char*)pathdata + offset;
- fpath = (vg_lite_float_t*)cpath;
- *cpath = VLC_OP_QUAD_REL;
- fpath++;
- *fpath = controlX;
- fpath++;
- *fpath = controlY;
- fpath++;
- *fpath = quadToX;
- fpath++;
- *fpath = quadToY;
- fpath++;
- offset += _commandSize_float[VLC_OP_QUAD_REL];
- i += _commandSize_float[VLC_OP_QUAD_REL];
- /* Determine the absolute coordinates. */
- controlX += coords.lastX;
- controlY += coords.lastY;
- quadToX += coords.lastX;
- quadToY += coords.lastY;
- /* Update the control coordinates. */
- coords.lastX = quadToX;
- coords.lastY = quadToY;
- coords.controlX = controlX;
- coords.controlY = controlY;
- break;
- case VLC_OP_CUBIC:
- controlX1 = *pfloat;
- pfloat++;
- controlY1 = *pfloat;
- pfloat++;
- controlX2 = *pfloat;
- pfloat++;
- controlY2 = *pfloat;
- pfloat++;
- cubicToX = *pfloat;
- pfloat++;
- cubicToY = *pfloat;
- pfloat++;
- /* Update the control coordinates. */
- coords.lastX = cubicToX;
- coords.lastY = cubicToY;
- coords.controlX = controlX2;
- coords.controlY = controlY2;
- cpath = (char*)pathdata + offset;
- fpath = (vg_lite_float_t*)cpath;
- *cpath = VLC_OP_CUBIC;
- fpath++;
- *fpath = controlX1;
- fpath++;
- *fpath = controlY1;
- fpath++;
- *fpath = controlX2;
- fpath++;
- *fpath = controlY2;
- fpath++;
- *fpath = cubicToX;
- fpath++;
- *fpath = cubicToY;
- fpath++;
- offset += _commandSize_float[VLC_OP_CUBIC];
- i += _commandSize_float[VLC_OP_CUBIC];
- break;
- case VLC_OP_CUBIC_REL:
- controlX1 = *pfloat;
- pfloat++;
- controlY1 = *pfloat;
- pfloat++;
- controlX2 = *pfloat;
- pfloat++;
- controlY2 = *pfloat;
- pfloat++;
- cubicToX = *pfloat;
- pfloat++;
- cubicToY = *pfloat;
- pfloat++;
- cpath = (char*)pathdata + offset;
- fpath = (vg_lite_float_t*)cpath;
- *cpath = VLC_OP_CUBIC_REL;
- fpath++;
- *fpath = controlX1;
- fpath++;
- *fpath = controlY1;
- fpath++;
- *fpath = controlX2;
- fpath++;
- *fpath = controlY2;
- fpath++;
- *fpath = cubicToX;
- fpath++;
- *fpath = cubicToY;
- fpath++;
- offset += _commandSize_float[VLC_OP_CUBIC_REL];
- i += _commandSize_float[VLC_OP_CUBIC_REL];
- /* Determine the absolute coordinates. */
- controlX2 += coords.lastX;
- controlY2 += coords.lastY;
- cubicToX += coords.lastX;
- cubicToY += coords.lastY;
- /* Update the control coordinates. */
- coords.lastX = cubicToX;
- coords.lastY = cubicToY;
- coords.controlX = controlX2;
- coords.controlY = controlY2;
- break;
- case VLC_OP_SCUBIC:
- controlX1 = *pfloat;
- pfloat++;
- controlY1 = *pfloat;
- pfloat++;
- cubicToX = *pfloat;
- pfloat++;
- cubicToY = *pfloat;
- pfloat++;
- i += _commandSize_float[VLC_OP_SCUBIC];
- /* Update the control coordinates. */
- VG_LITE_ERROR_HANDLER(_convert_scubic(cubicToX, cubicToY, controlX1, controlY1, VGL_FALSE, &coords, (void*)&pathdata, &offset, path_length - i));
- break;
- case VLC_OP_SCUBIC_REL:
- controlX1 = *pfloat;
- pfloat++;
- controlY1 = *pfloat;
- pfloat++;
- cubicToX = *pfloat;
- pfloat++;
- cubicToY = *pfloat;
- pfloat++;
- i += _commandSize_float[VLC_OP_SCUBIC_REL];
- /* Update the control coordinates. */
- VG_LITE_ERROR_HANDLER(_convert_scubic(cubicToX, cubicToY, controlX1, controlY1, VGL_TRUE, &coords, (void*)&pathdata, &offset, path_length - i));
- break;
- case VLC_OP_HLINE:
- lineToX = *pfloat;
- pfloat++;
- lineToY = coords.lastY;
- i += _commandSize_float[VLC_OP_HLINE];
- /* Update the control coordinates. */
- VG_LITE_ERROR_HANDLER(_convert_hline(lineToX, lineToY, VGL_FALSE, &coords, (void*)&pathdata, &offset, path_length - i));
- break;
- case VLC_OP_HLINE_REL:
- lineToX = *pfloat;
- pfloat++;
- lineToY = coords.lastY;
- i += _commandSize_float[VLC_OP_HLINE_REL];
- /* Update the control coordinates. */
- VG_LITE_ERROR_HANDLER(_convert_hline(lineToX, lineToY, VGL_TRUE, &coords, (void*)&pathdata, &offset, path_length - i));
- break;
- case VLC_OP_VLINE:
- lineToX = coords.lastX;
- lineToY = *pfloat;
- pfloat++;
- i += _commandSize_float[VLC_OP_VLINE];
- /* Update the control coordinates. */
- VG_LITE_ERROR_HANDLER(_convert_vline(lineToX, lineToY, VGL_FALSE, &coords, (void*)&pathdata, &offset, path_length - i));
- break;
- case VLC_OP_VLINE_REL:
- lineToX = coords.lastX;
- lineToY = *pfloat;
- pfloat++;
- i += _commandSize_float[VLC_OP_VLINE_REL];
- /* Update the control coordinates. */
- VG_LITE_ERROR_HANDLER(_convert_vline(lineToX, lineToY, VGL_TRUE, &coords, (void*)&pathdata, &offset, path_length - i));
- break;
- case VLC_OP_SCCWARC:
- horRadius = *pfloat;
- pfloat++;
- verRadius = *pfloat;
- pfloat++;
- rotAngle = *pfloat;
- pfloat++;
- endX = *pfloat;
- pfloat++;
- endY = *pfloat;
- pfloat++;
- i += _commandSize_float[VLC_OP_SCCWARC];
- VG_LITE_ERROR_HANDLER(_convert_arc(horRadius, verRadius, rotAngle, endX, endY, VGL_FALSE, VGL_FALSE, VGL_FALSE, &coords, (void*)&pathdata, &offset, path_length - i));
- break;
- case VLC_OP_SCCWARC_REL:
- horRadius = *pfloat;
- pfloat++;
- verRadius = *pfloat;
- pfloat++;
- rotAngle = *pfloat;
- pfloat++;
- endX = *pfloat;
- pfloat++;
- endY = *pfloat;
- pfloat++;
- i += _commandSize_float[VLC_OP_SCCWARC_REL];
- VG_LITE_ERROR_HANDLER(_convert_arc(horRadius, verRadius, rotAngle, endX, endY, VGL_FALSE, VGL_FALSE, VGL_TRUE, &coords, (void*)&pathdata, &offset, path_length - i));
- break;
- case VLC_OP_SCWARC:
- horRadius = *pfloat;
- pfloat++;
- verRadius = *pfloat;
- pfloat++;
- rotAngle = *pfloat;
- pfloat++;
- endX = *pfloat;
- pfloat++;
- endY = *pfloat;
- pfloat++;
- i += _commandSize_float[VLC_OP_SCCWARC_REL];
- VG_LITE_ERROR_HANDLER(_convert_arc(horRadius, verRadius, rotAngle, endX, endY, VGL_TRUE, VGL_FALSE, VGL_FALSE, &coords, (void*)&pathdata, &offset, path_length - i));
- break;
- case VLC_OP_SCWARC_REL:
- horRadius = *pfloat;
- pfloat++;
- verRadius = *pfloat;
- pfloat++;
- rotAngle = *pfloat;
- pfloat++;
- endX = *pfloat;
- pfloat++;
- endY = *pfloat;
- pfloat++;
- i += _commandSize_float[VLC_OP_SCCWARC_REL];
- VG_LITE_ERROR_HANDLER(_convert_arc(horRadius, verRadius, rotAngle, endX, endY, VGL_TRUE, VGL_FALSE, VGL_TRUE, &coords, (void*)&pathdata, &offset, path_length - i));
- break;
- case VLC_OP_LCCWARC:
- horRadius = *pfloat;
- pfloat++;
- verRadius = *pfloat;
- pfloat++;
- rotAngle = *pfloat;
- pfloat++;
- endX = *pfloat;
- pfloat++;
- endY = *pfloat;
- pfloat++;
- i += _commandSize_float[VLC_OP_SCCWARC_REL];
- VG_LITE_ERROR_HANDLER(_convert_arc(horRadius, verRadius, rotAngle, endX, endY, VGL_FALSE, VGL_TRUE, VGL_FALSE, &coords, (void*)&pathdata, &offset, path_length - i));
- break;
- case VLC_OP_LCCWARC_REL:
- horRadius = *pfloat;
- pfloat++;
- verRadius = *pfloat;
- pfloat++;
- rotAngle = *pfloat;
- pfloat++;
- endX = *pfloat;
- pfloat++;
- endY = *pfloat;
- pfloat++;
- i += _commandSize_float[VLC_OP_SCCWARC_REL];
- VG_LITE_ERROR_HANDLER(_convert_arc(horRadius, verRadius, rotAngle, endX, endY, VGL_FALSE, VGL_TRUE, VGL_TRUE, &coords, (void*)&pathdata, &offset, path_length - i));
- break;
- case VLC_OP_LCWARC:
- horRadius = *pfloat;
- pfloat++;
- verRadius = *pfloat;
- pfloat++;
- rotAngle = *pfloat;
- pfloat++;
- endX = *pfloat;
- pfloat++;
- endY = *pfloat;
- pfloat++;
- i += _commandSize_float[VLC_OP_SCCWARC_REL];
- VG_LITE_ERROR_HANDLER(_convert_arc(horRadius, verRadius, rotAngle, endX, endY, VGL_TRUE, VGL_TRUE, VGL_FALSE, &coords, (void*)&pathdata, &offset, path_length - i));
- break;
- case VLC_OP_LCWARC_REL:
- horRadius = *pfloat;
- pfloat++;
- verRadius = *pfloat;
- pfloat++;
- rotAngle = *pfloat;
- pfloat++;
- endX = *pfloat;
- pfloat++;
- endY = *pfloat;
- pfloat++;
- i += _commandSize_float[VLC_OP_SCCWARC_REL];
- VG_LITE_ERROR_HANDLER(_convert_arc(horRadius, verRadius, rotAngle, endX, endY, VGL_TRUE, VGL_TRUE, VGL_TRUE, &coords, (void*)&pathdata, &offset, path_length - i));
- break;
- default:
- break;
- }
- }
- if (path_data_fp32 != NULL)
- vg_lite_os_free(path_data_fp32);
- path->format = VG_LITE_FP32;
- path->quality = quality;
- path->path_length = offset;
- path->path = pathdata;
- path->pdata_internal = 1;
- path->path_changed = 1;
- path->uploaded.address = 0;
- path->uploaded.bytes = 0;
- path->uploaded.handle = NULL;
- path->uploaded.memory = NULL;
- s_context.path_lastX = coords.lastX;
- s_context.path_lastY = coords.lastY;
- return VG_LITE_SUCCESS;
- ErrorHandler:
- vg_lite_os_free(pathdata);
- pathdata = NULL;
- return error;
- }
- #else /* gcFEATURE_VG_ARC_PATH */
- vg_lite_error_t vg_lite_init_arc_path(vg_lite_path_t* path,
- vg_lite_format_t data_format,
- vg_lite_quality_t quality,
- vg_lite_uint32_t path_length,
- vg_lite_pointer path_data,
- vg_lite_float_t min_x, vg_lite_float_t min_y,
- vg_lite_float_t max_x, vg_lite_float_t max_y)
- {
- return VG_LITE_NOT_SUPPORT;
- }
- #endif /* gcFEATURE_VG_ARC_PATH */
|