vg_lite_stroke.c 179 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636
  1. /****************************************************************************
  2. *
  3. * Copyright 2012 - 2023 Vivante Corporation, Santa Clara, California.
  4. * All Rights Reserved.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining
  7. * a copy of this software and associated documentation files (the
  8. * 'Software'), to deal in the Software without restriction, including
  9. * without limitation the rights to use, copy, modify, merge, publish,
  10. * distribute, sub license, and/or sell copies of the Software, and to
  11. * permit persons to whom the Software is furnished to do so, subject
  12. * to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice (including the
  15. * next paragraph) shall be included in all copies or substantial
  16. * portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
  19. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21. * IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
  22. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25. *
  26. *****************************************************************************/
  27. #include "vg_lite_context.h"
  28. #define PI 3.141592653589793238462643383279502f
  29. #define SINF(x) ((vg_lite_float_t) sin(x))
  30. #define COSF(x) ((vg_lite_float_t) cos(x))
  31. #define FABSF(x) ((vg_lite_float_t) fabs(x))
  32. #define SQRTF(x) ((vg_lite_float_t) sqrt(x))
  33. #define CLAMP(x, min, max) (((x) < (min)) ? (min) : \
  34. ((x) > (max)) ? (max) : (x))
  35. #define ACOSF(x) ((vg_lite_float_t) acos(x))
  36. #define FMODF(x, y) ((vg_lite_float_t) fmod((x), (y)))
  37. #define CEILF(x) ((vg_lite_float_t) ceil(x))
  38. #define SIZEOF(a) ((size_t)(sizeof(a)))
  39. #define PTR2SIZE(p) ((uintptr_t)(p))
  40. #define FLOAT_EPSILON 0.001f
  41. #define SWING_NO 0
  42. #define SWING_OUT 1
  43. #define SWING_IN 2
  44. /* Point curve type for generated stroke path. */
  45. #define CURVE_LINE 0
  46. #define CURVE_QUAD_CONTROL 1
  47. #define CURVE_QUAD_ANCHOR 2
  48. #define CURVE_ARC_SCCW 3
  49. #define CURVE_ARC_SCCW_HALF 4
  50. #define FLOAT_PI 3.141592654f
  51. #define FLOAT_PI_TWO 6.283185307f
  52. #define FLOAT_PI_THREE_QUARTER 2.356194490f
  53. #define FLOAT_PI_HALF 1.570796327f
  54. #define FLOAT_PI_QUARTER 0.7853981634f
  55. #define FLOAT_PI_EIGHTH 0.3926990817f
  56. /* cos(PI/8) */
  57. #define FLOAT_COS_PI_EIGHTH 0.9238795325f
  58. #define FLOAT_DIFF_EPSILON 0.125f
  59. #define FLOAT_SWING_CENTER_RANGE 0.125f
  60. #define FLOAT_ANGLE_EPSILON 0.0045f
  61. #define FLOAT_ANGLE_EPSILON_COS 0.99999f
  62. #define FLOAT_MIN_ARC_ANGLE 0.044f
  63. #define FLOAT_MIN_ARC_ANGLE_COS 0.999f
  64. /* Float constants. */
  65. #define gcvMAX_POS_FLOAT ((vg_lite_float_t) 3.4028235e+038)
  66. #define gcvMAX_NEG_FLOAT ((vg_lite_float_t) -3.4028235e+038)
  67. #define FLOAT_MIN gcvMAX_NEG_FLOAT
  68. #define FLOAT_MAX gcvMAX_POS_FLOAT
  69. #define FLOAT_FAT_LINE_WIDTH 2.5f
  70. /* Point flatten type for flattened line segments. */
  71. #define vgcFLATTEN_NO 0
  72. #define vgcFLATTEN_START 1
  73. #define vgcFLATTEN_MIDDLE 2
  74. #define vgcFLATTEN_END 3
  75. typedef struct vg_lite_control_coord
  76. {
  77. vg_lite_float_t startX;
  78. vg_lite_float_t startY;
  79. vg_lite_float_t lastX;
  80. vg_lite_float_t lastY;
  81. vg_lite_float_t controlX;
  82. vg_lite_float_t controlY;
  83. } vg_lite_control_coord_t;
  84. /* Command size calculation shortcuts. */
  85. #define COMMANDSIZE(CoordinateCount, CoordinateType) \
  86. ((1+CoordinateCount) * SIZEOF(CoordinateType))
  87. extern int32_t get_data_size(vg_lite_format_t format);
  88. static uint32_t _commandSize_float[] =
  89. {
  90. COMMANDSIZE(0, vg_lite_float_t), /* 0: END */
  91. COMMANDSIZE(0, vg_lite_float_t), /* 1: CLOSE */
  92. COMMANDSIZE(2, vg_lite_float_t), /* 2: MOVE */
  93. COMMANDSIZE(2, vg_lite_float_t), /* 3: MOVE_REL */
  94. COMMANDSIZE(2, vg_lite_float_t), /* 4: LINE */
  95. COMMANDSIZE(2, vg_lite_float_t), /* 5: LINE_REL */
  96. COMMANDSIZE(4, vg_lite_float_t), /* 6: QUAD */
  97. COMMANDSIZE(4, vg_lite_float_t), /* 7: QUAD_REL */
  98. COMMANDSIZE(6, vg_lite_float_t), /* 8: CUBIC */
  99. COMMANDSIZE(6, vg_lite_float_t), /* 9: CUBIC_REL */
  100. COMMANDSIZE(0, vg_lite_float_t), /* 10: BREAK */
  101. COMMANDSIZE(1, vg_lite_float_t), /* 11: HLINE */
  102. COMMANDSIZE(1, vg_lite_float_t), /* 12: HLINE_REL */
  103. COMMANDSIZE(1, vg_lite_float_t), /* 13: VLINE */
  104. COMMANDSIZE(1, vg_lite_float_t), /* 14: VLINE_REL */
  105. COMMANDSIZE(2, vg_lite_float_t), /* 15: SQUAD */
  106. COMMANDSIZE(2, vg_lite_float_t), /* 16: SQUAD_REL */
  107. COMMANDSIZE(4, vg_lite_float_t), /* 17: SCUBIC */
  108. COMMANDSIZE(4, vg_lite_float_t), /* 18: SCUBIC_REL */
  109. COMMANDSIZE(5, vg_lite_float_t), /* 19: SCCWARC */
  110. COMMANDSIZE(5, vg_lite_float_t), /* 20: SCCWARC_REL */
  111. COMMANDSIZE(5, vg_lite_float_t), /* 21: SCWARC */
  112. COMMANDSIZE(5, vg_lite_float_t), /* 22: SCWARC_REL */
  113. COMMANDSIZE(5, vg_lite_float_t), /* 23: LCCWARC */
  114. COMMANDSIZE(5, vg_lite_float_t), /* 24: LCCWARC_REL */
  115. COMMANDSIZE(5, vg_lite_float_t), /* 25: LCWARC */
  116. COMMANDSIZE(5, vg_lite_float_t), /* 26: LCWARC_REL */
  117. };
  118. #if gcFEATURE_VG_STROKE_PATH
  119. static vg_lite_float_t _GetS8_NS_NB(int8_t * Data)
  120. {
  121. int8_t x0 = *((int8_t *) Data);
  122. vg_lite_float_t x = (vg_lite_float_t) x0;
  123. return x;
  124. }
  125. static vg_lite_float_t _GetS16_NS_NB(int8_t * Data)
  126. {
  127. int16_t x0 = *((int16_t *) Data);
  128. vg_lite_float_t x = (vg_lite_float_t) x0;
  129. return x;
  130. }
  131. static vg_lite_float_t _GetS32_NS_NB(int8_t * Data)
  132. {
  133. int32_t x0 = *((int32_t *) Data);
  134. vg_lite_float_t x = (vg_lite_float_t) x0;
  135. return x;
  136. }
  137. static vg_lite_float_t _GetF_NS_NB(int8_t * Data)
  138. {
  139. vg_lite_float_t x = *((vg_lite_float_t *) Data);
  140. return x;
  141. }
  142. /* Special sqrt(1.0f + x) for quick calculation when 0 <= x <= 1. */
  143. static vg_lite_float_t _Sqrt(
  144. vg_lite_float_t X
  145. )
  146. {
  147. vg_lite_float_t x = X;
  148. vg_lite_float_t s = 1.0f;
  149. s += x * 0.5f;
  150. x *= X;
  151. s -= x * 0.12445995211601257f;
  152. x *= X;
  153. s += x * 0.058032196015119553f;
  154. x *= X;
  155. s -= x * 0.025314478203654289f;
  156. x *= X;
  157. s += x * 0.0059584137052297592f;
  158. return s;
  159. }
  160. static vg_lite_error_t _set_point_tangent(
  161. vg_lite_path_point_ptr Point,
  162. vg_lite_float_t Dx,
  163. vg_lite_float_t Dy
  164. )
  165. {
  166. if (!Point)
  167. return VG_LITE_INVALID_ARGUMENT;
  168. if (Dx == 0.0f)
  169. {
  170. if (Dy == 0.0f)
  171. {
  172. if (Point->prev)
  173. {
  174. Point->length = 0.0f;
  175. Point->tangentX = Point->prev->tangentX;
  176. Point->tangentY = Point->prev->tangentY;
  177. }
  178. else
  179. {
  180. Point->length = 0.0f;
  181. Point->tangentX = 0.0f;
  182. Point->tangentY = 0.0f;
  183. }
  184. }
  185. else
  186. {
  187. Point->tangentX = 0.0f;
  188. if (Dy > 0.0f)
  189. {
  190. Point->length = Dy;
  191. Point->tangentY = 1.0f;
  192. }
  193. else
  194. {
  195. Point->length = -Dy;
  196. Point->tangentY = -1.0f;
  197. }
  198. }
  199. }
  200. else if (Dy == 0.0f)
  201. {
  202. Point->tangentY = 0.0f;
  203. if (Dx > 0.0f)
  204. {
  205. Point->length = Dx;
  206. Point->tangentX = 1.0f;
  207. }
  208. else
  209. {
  210. Point->length = -Dx;
  211. Point->tangentX = -1.0f;
  212. }
  213. }
  214. else
  215. {
  216. vg_lite_float_t l, tx, ty;
  217. vg_lite_float_t dx, dy;
  218. vg_lite_float_t t, t2;
  219. dx = (Dx >= 0.0f ? Dx : -Dx);
  220. dy = (Dy >= 0.0f ? Dy : -Dy);
  221. if (dx >= dy)
  222. {
  223. t = dy / dx;
  224. t2 = t * t;
  225. l = _Sqrt(t2);
  226. Point->length = l * dx;
  227. tx = 1.0f / l;
  228. ty = tx * t;
  229. }
  230. else
  231. {
  232. t = dx / dy;
  233. t2 = t * t;
  234. l = _Sqrt(t2);
  235. Point->length = l * dy;
  236. ty = 1.0f / l;
  237. tx = ty * t;
  238. }
  239. if (Dx < 0.0f) tx = -tx;
  240. if (Dy < 0.0f) ty = -ty;
  241. tx = CLAMP(tx, -1.0f, 1.0f);
  242. ty = CLAMP(ty, -1.0f, 1.0f);
  243. Point->tangentX = tx;
  244. Point->tangentY = ty;
  245. }
  246. return VG_LITE_SUCCESS;
  247. }
  248. static vg_lite_error_t _add_point_to_point_list_wdelta(
  249. vg_lite_stroke_t * stroke_conversion,
  250. vg_lite_float_t X,
  251. vg_lite_float_t Y,
  252. vg_lite_float_t DX,
  253. vg_lite_float_t DY,
  254. uint8_t flatten_flag
  255. )
  256. {
  257. vg_lite_error_t error = VG_LITE_SUCCESS;
  258. vg_lite_path_point_ptr last_point;
  259. vg_lite_path_point_ptr point;
  260. if (!stroke_conversion)
  261. return VG_LITE_INVALID_ARGUMENT;
  262. last_point = stroke_conversion->path_end;
  263. point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*point));
  264. if (!point)
  265. return VG_LITE_OUT_OF_RESOURCES;
  266. memset(point, 0, sizeof(*point));
  267. point->x = X;
  268. point->y = Y;
  269. point->flatten_flag = flatten_flag;
  270. /* Calculate tangent for last_point. */
  271. VG_LITE_ERROR_HANDLER(_set_point_tangent(last_point, DX, DY));
  272. last_point->next = point;
  273. stroke_conversion->path_end = point;
  274. point->prev = last_point;
  275. stroke_conversion->point_count++;
  276. stroke_conversion->cur_list->path_end = point;
  277. stroke_conversion->cur_list->point_count++;
  278. return error;
  279. ErrorHandler:
  280. vg_lite_os_free(point);
  281. point = NULL;
  282. return error;
  283. }
  284. static vg_lite_error_t _create_new_point_list(
  285. vg_lite_stroke_t* stroke_conversion,
  286. vg_lite_float_t X,
  287. vg_lite_float_t Y,
  288. uint8_t flatten_flag
  289. )
  290. {
  291. vg_lite_error_t status = VG_LITE_SUCCESS;
  292. vg_lite_path_point_ptr point;
  293. vg_lite_path_list_ptr path_list_divide;
  294. if (!stroke_conversion)
  295. return VG_LITE_INVALID_ARGUMENT;
  296. point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*point));
  297. if (!point)
  298. return VG_LITE_OUT_OF_RESOURCES;
  299. memset(point, 0, sizeof(*point));
  300. point->x = X;
  301. point->y = Y;
  302. point->flatten_flag = flatten_flag;
  303. point->prev = NULL;
  304. stroke_conversion->point_count = 0;
  305. stroke_conversion->path_end = stroke_conversion->path_points = point;
  306. stroke_conversion->point_count++;
  307. path_list_divide = (vg_lite_path_list_ptr)vg_lite_os_malloc(sizeof(*path_list_divide));
  308. if (!path_list_divide)
  309. return VG_LITE_OUT_OF_RESOURCES;
  310. memset(path_list_divide, 0, sizeof(*path_list_divide));
  311. path_list_divide->path_end = path_list_divide->path_points = point;
  312. path_list_divide->point_count++;
  313. if (stroke_conversion->cur_list == NULL)
  314. {
  315. stroke_conversion->cur_list = path_list_divide;
  316. stroke_conversion->path_list_divide = path_list_divide;
  317. }
  318. else
  319. {
  320. stroke_conversion->cur_list->next = path_list_divide;
  321. stroke_conversion->cur_list = stroke_conversion->cur_list->next;
  322. }
  323. return status;
  324. }
  325. static vg_lite_error_t _add_point_to_point_list(
  326. vg_lite_stroke_t * stroke_conversion,
  327. vg_lite_float_t X,
  328. vg_lite_float_t Y,
  329. uint8_t flatten_flag
  330. )
  331. {
  332. vg_lite_error_t status = VG_LITE_SUCCESS;
  333. vg_lite_path_point_ptr last_point;
  334. vg_lite_path_point_ptr point;
  335. if (!stroke_conversion)
  336. return VG_LITE_INVALID_ARGUMENT;
  337. last_point = stroke_conversion->path_end;
  338. if (last_point == NULL)
  339. {
  340. point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*point));
  341. if (!point)
  342. return VG_LITE_OUT_OF_RESOURCES;
  343. memset(point, 0, sizeof(*point));
  344. point->x = X;
  345. point->y = Y;
  346. point->flatten_flag = flatten_flag;
  347. point->prev = NULL;
  348. stroke_conversion->path_end = stroke_conversion->path_points = point;
  349. stroke_conversion->point_count++;
  350. status = VG_LITE_SUCCESS;
  351. }
  352. else
  353. {
  354. vg_lite_float_t dX = X - last_point->x;
  355. vg_lite_float_t dY = Y - last_point->y;
  356. vg_lite_float_t deltaX = (dX >= 0.0f ? dX : -dX);
  357. vg_lite_float_t deltaY = (dY >= 0.0f ? dY : -dY);
  358. /* Check for degenerated line. */
  359. if (deltaX == 0.0f && deltaY == 0.0f)
  360. {
  361. /* Skip degenerated line. */
  362. status = VG_LITE_SUCCESS;
  363. goto ErrorHandler;
  364. }
  365. if (deltaX < FLOAT_EPSILON && deltaY < FLOAT_EPSILON)
  366. {
  367. vg_lite_float_t ratioX, ratioY;
  368. if (deltaX == 0.0f)
  369. {
  370. ratioX = 0.0f;
  371. }
  372. else if (X == 0.0f)
  373. {
  374. ratioX = deltaX;
  375. }
  376. else
  377. {
  378. ratioX = deltaX / X;
  379. if (ratioX < 0.0f) ratioX = -ratioX;
  380. }
  381. if (deltaY == 0.0f)
  382. {
  383. ratioY = 0.0f;
  384. }
  385. else if (Y == 0.0f)
  386. {
  387. ratioY = deltaY;
  388. }
  389. else
  390. {
  391. ratioY = deltaY / Y;
  392. if (ratioY < 0.0f) ratioY = -ratioY;
  393. }
  394. if (ratioX < 1.0e-6f && ratioY < 1.0e-6f)
  395. {
  396. /* Skip degenerated line. */
  397. status = VG_LITE_SUCCESS;
  398. goto ErrorHandler;
  399. }
  400. }
  401. status = _add_point_to_point_list_wdelta(stroke_conversion, X, Y, dX, dY, flatten_flag);
  402. }
  403. ErrorHandler:
  404. return status;
  405. }
  406. #define gcFEATURE_VG_SIMPLYFIED_BEZIER 1
  407. #if gcFEATURE_VG_SIMPLYFIED_BEZIER
  408. void quad_bezier(float* x, float* y, const float curve[6], float t) {
  409. const float* v0, * v1, * v2;
  410. float mt, t2, mt2, res[2];
  411. v0 = &curve[0];
  412. v1 = &curve[2];
  413. v2 = &curve[4];
  414. mt = 1 - t;
  415. t2 = t * t;
  416. mt2 = mt * mt;
  417. for (uint8_t i = 0; i < 2; ++i) {
  418. res[i] = v0[i] * mt2 + 2 * v1[i] * mt * t + v2[i] * t2;
  419. }
  420. *x = res[0];
  421. *y = res[1];
  422. }
  423. void cubic_bezier(float* x, float* y, const float curve[8], float t) {
  424. const float* v0, * v1, * v2, * v3;
  425. float mt, t2, mt2, t3, mt3, res[2];
  426. v0 = &curve[0];
  427. v1 = &curve[2];
  428. v2 = &curve[4];
  429. v3 = &curve[6];
  430. mt = 1 - t;
  431. t2 = t * t;
  432. t3 = t2 * t;
  433. mt2 = mt * mt;
  434. mt3 = mt2 * mt;
  435. for (uint8_t i = 0; i < 2; ++i) {
  436. res[i] = v0[i] * mt3 + 3 * v1[i] * mt2 * t + 3 * v2[i] * mt * t2 + v3[i] * t3;
  437. }
  438. *x = res[0];
  439. *y = res[1];
  440. }
  441. void pointer_warp_affine(float out[2], float pt[2], vg_lite_matrix_t* matrix) {
  442. float x, y;
  443. x = pt[0];
  444. y = pt[1];
  445. out[0] = matrix->m[0][0] * x + matrix->m[1][0] * y + matrix->m[2][0];
  446. out[1] = matrix->m[0][1] * x + matrix->m[1][1] * y + matrix->m[2][1];
  447. }
  448. void get_aligned_quad(float out[6], float curve[6]) {
  449. float* v0, * v1, * v2;
  450. float angle, dx, dy;
  451. vg_lite_matrix_t matrix;
  452. v0 = &curve[0];
  453. v1 = &curve[2];
  454. v2 = &curve[4];
  455. dx = v2[0] - v0[0];
  456. dy = v2[1] - v0[1];
  457. angle = (dy >= 0) ? acosf(dx / sqrtf(dx * dx + dy * dy)) : (2 * 3.1415926535f - acosf(dx / sqrtf(dx * dx + dy * dy)));
  458. vg_lite_identity(&matrix);
  459. vg_lite_translate(-v0[0], -v0[1], &matrix);
  460. vg_lite_rotate(-angle, &matrix);
  461. pointer_warp_affine(&out[0], v0, &matrix);
  462. pointer_warp_affine(&out[2], v1, &matrix);
  463. pointer_warp_affine(&out[4], v2, &matrix);
  464. }
  465. void get_aligned_cubic(float out[8], float curve[8]) {
  466. float* v0, * v1, * v2, * v3;
  467. float angle, dx, dy;
  468. vg_lite_matrix_t matrix;
  469. v0 = &curve[0];
  470. v1 = &curve[2];
  471. v2 = &curve[4];
  472. v3 = &curve[6];
  473. dx = v3[0] - v0[0];
  474. dy = v3[1] - v0[1];
  475. angle = (dy >= 0) ? acosf(dx / sqrtf(dx * dx + dy * dy)) : (2 * 3.1415926535f - acosf(dx / sqrtf(dx * dx + dy * dy)));
  476. vg_lite_identity(&matrix);
  477. vg_lite_translate(-v0[0], -v0[1], &matrix);
  478. vg_lite_rotate(-angle, &matrix);
  479. pointer_warp_affine(&out[0], v0, &matrix);
  480. pointer_warp_affine(&out[2], v1, &matrix);
  481. pointer_warp_affine(&out[4], v2, &matrix);
  482. pointer_warp_affine(&out[6], v3, &matrix);
  483. }
  484. void split_quad(float out1[6], float out2[6], float curve[6], float split) {
  485. float* v0, * v1, * v2;
  486. float s, s2, ms, ms2;
  487. v0 = &curve[0];
  488. v1 = &curve[2];
  489. v2 = &curve[4];
  490. s = split;
  491. ms = 1 - split;
  492. s2 = s * s;
  493. ms2 = ms * ms;
  494. float B[2][3] = {
  495. {v0[0], v1[0], v2[0]},
  496. {v0[1], v1[1], v2[1]}
  497. };
  498. /* First curve */
  499. {
  500. float C[2][3] = { {0} };
  501. float A[9] = {
  502. 1, 0, 0,
  503. ms, s, 0,
  504. ms2, 2 * ms * s, s2
  505. };
  506. /* C = A ¡Á B */
  507. for (uint8_t i = 0; i < 2; ++i) {
  508. for (size_t y = 0; y < 3; ++y)
  509. for (size_t x = 0; x < 1; ++x)
  510. for (size_t z = 0; z < 3; ++z) {
  511. C[i][x + y * 1] += A[z + y * 3] * B[i][x + z * 1];
  512. }
  513. }
  514. out1[0] = C[0][0]; out1[1] = C[1][0];
  515. out1[2] = C[0][1]; out1[3] = C[1][1];
  516. out1[4] = C[0][2]; out1[5] = C[1][2];
  517. }
  518. /* Second curve */
  519. {
  520. float C[2][3] = { {0} };
  521. float A[9] = {
  522. ms2, 2 * s * ms, s2,
  523. 0, ms, s,
  524. 0, 0, 1
  525. };
  526. /* C = A ¡Á B */
  527. for (uint8_t i = 0; i < 2; ++i) {
  528. for (size_t y = 0; y < 3; ++y)
  529. for (size_t x = 0; x < 1; ++x)
  530. for (size_t z = 0; z < 3; ++z) {
  531. C[i][x + y * 1] += A[z + y * 3] * B[i][x + z * 1];
  532. }
  533. }
  534. out2[0] = C[0][0]; out2[1] = C[1][0];
  535. out2[2] = C[0][1]; out2[3] = C[1][1];
  536. out2[4] = C[0][2]; out2[5] = C[1][2];
  537. }
  538. }
  539. void split_cubic(float out1[8], float out2[8], float curve[8], float split) {
  540. float* v0, * v1, * v2, * v3;
  541. float s, s2, s3, ms, ms2, ms3;
  542. v0 = &curve[0];
  543. v1 = &curve[2];
  544. v2 = &curve[4];
  545. v3 = &curve[6];
  546. s = split;
  547. ms = 1 - split;
  548. s2 = s * s;
  549. ms2 = ms * ms;
  550. s3 = s2 * s;
  551. ms3 = ms2 * ms;
  552. float B[2][4] = {
  553. {v0[0], v1[0], v2[0], v3[0]},
  554. {v0[1], v1[1], v2[1], v3[1]}
  555. };
  556. /* First curve */
  557. {
  558. float C[2][4] = { {0} };
  559. float A[16] = {
  560. 1, 0, 0, 0,
  561. ms, s, 0, 0,
  562. ms2, 2 * ms * s, s2, 0,
  563. ms3, 3 * s * ms2, 3 * s2 * ms, s3
  564. };
  565. /* C = A ¡Á B */
  566. for (uint8_t i = 0; i < 2; ++i) {
  567. for (size_t y = 0; y < 4; ++y)
  568. for (size_t x = 0; x < 1; ++x)
  569. for (size_t z = 0; z < 4; ++z) {
  570. C[i][x + y * 1] += A[z + y * 4] * B[i][x + z * 1];
  571. }
  572. }
  573. out1[0] = C[0][0]; out1[1] = C[1][0];
  574. out1[2] = C[0][1]; out1[3] = C[1][1];
  575. out1[4] = C[0][2]; out1[5] = C[1][2];
  576. out1[6] = C[0][3]; out1[7] = C[1][3];
  577. }
  578. /* Second curve */
  579. {
  580. float C[2][4] = { {0} };
  581. float A[16] = {
  582. ms3, 3 * s * ms2, 3 * s2 * ms, s3,
  583. 0, ms2, 2 * ms * s, s2,
  584. 0, 0, ms, s,
  585. 0, 0, 0, 1
  586. };
  587. /* C = A ¡Á B */
  588. for (uint8_t i = 0; i < 2; ++i) {
  589. for (size_t y = 0; y < 4; ++y)
  590. for (size_t x = 0; x < 1; ++x)
  591. for (size_t z = 0; z < 4; ++z) {
  592. C[i][x + y * 1] += A[z + y * 4] * B[i][x + z * 1];
  593. }
  594. }
  595. out2[0] = C[0][0]; out2[1] = C[1][0];
  596. out2[2] = C[0][1]; out2[3] = C[1][1];
  597. out2[4] = C[0][2]; out2[5] = C[1][2];
  598. out2[6] = C[0][3]; out2[7] = C[1][3];
  599. }
  600. }
  601. static vg_lite_error_t _flatten_quad_bezier(
  602. vg_lite_stroke_t* stroke_conversion,
  603. vg_lite_float_t rootCurve[6],
  604. vg_lite_float_t subCurve[6],
  605. vg_lite_uint8_t level)
  606. {
  607. vg_lite_error_t error = VG_LITE_SUCCESS;
  608. float* v0, * v1, * v2;
  609. float dx2, dy2, d1;
  610. float subCurve1[6], subCurve2[6];
  611. vg_lite_path_point_ptr point0, point1;
  612. vg_lite_float_t* curve;
  613. curve = (level == 0) ? rootCurve : subCurve;
  614. if (!stroke_conversion)
  615. return VG_LITE_INVALID_ARGUMENT;
  616. if (level > 10) return error;
  617. v0 = &curve[0];
  618. v1 = &curve[2];
  619. v2 = &curve[4];
  620. if (level == 0) {
  621. /* Add extra P0 for incoming tangent. */
  622. point0 = stroke_conversion->path_end;
  623. /* First add P1 to calculate incoming tangent, which is saved in P0. */
  624. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v1[0], v1[1], vgcFLATTEN_START));
  625. point1 = stroke_conversion->path_end;
  626. /* Change the point1's coordinates back to P0. */
  627. point1->x = v0[0];
  628. point1->y = v0[1];
  629. point0->length = 0.0f;
  630. }
  631. dx2 = v2[0] - v0[0];
  632. dy2 = v2[1] - v0[1];
  633. d1 = fabsf((v1[0] - v2[0]) * dy2 - (v1[1] - v2[1]) * dx2);
  634. if (d1 * d1 < 0.25 * (dx2 * dx2 + dy2 * dy2)) {
  635. float bound[4];
  636. bound[0] = MIN(v0[0], v2[0]);
  637. bound[1] = MIN(v0[1], v2[1]);
  638. bound[2] = MAX(v0[0], v2[0]);
  639. bound[3] = MAX(v0[1], v2[1]);
  640. if (!(v1[0] >= bound[0] && v1[0] <= bound[2] && v1[1] >= bound[1] && v1[1] <= bound[3])) {
  641. /* Compute root. */
  642. float alignedCurve[6];
  643. float d, n, t, pt[2];
  644. get_aligned_quad(alignedCurve, curve);
  645. n = alignedCurve[0] - alignedCurve[2];
  646. d = alignedCurve[0] - 2.f * alignedCurve[2] + alignedCurve[4];
  647. if (fabsf(d) > 1e-12f) {
  648. t = n / d;
  649. if (t > 1e-12f && t < 1.f - 1e-12f) {
  650. quad_bezier(&pt[0], &pt[1], curve, t);
  651. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, pt[0], pt[1], vgcFLATTEN_MIDDLE));
  652. }
  653. }
  654. }
  655. else if(level == 0) {
  656. float pt[2];
  657. uint8_t n = 16;
  658. for (uint8_t i = 1; i < n; i++) {
  659. vg_lite_float_t t = (vg_lite_float_t)i / (vg_lite_float_t)n;
  660. quad_bezier(&pt[0], &pt[1], curve, t);
  661. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, pt[0], pt[1], vgcFLATTEN_MIDDLE));
  662. }
  663. }
  664. if (level == 0)
  665. {
  666. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_END));
  667. }
  668. else if((v2[0] != rootCurve[4]) || (v2[1] != rootCurve[5]))
  669. {
  670. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_MIDDLE));
  671. }
  672. if (level == 0) {
  673. /* Add extra P2 for outgoing tangent. */
  674. /* First change P2(point0)'s coordinates to P1. */
  675. point0 = stroke_conversion->path_end;
  676. point0->x = v1[0];
  677. point0->y = v1[1];
  678. /* Add P2 to calculate outgoing tangent. */
  679. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_NO));
  680. point1 = stroke_conversion->path_end;
  681. /* Change point0's coordinates back to P2. */
  682. point0->x = v2[0];
  683. point0->y = v2[1];
  684. point0->length = 0.0f;
  685. }
  686. return error;
  687. }
  688. split_quad(subCurve1, subCurve2, curve, 0.5);
  689. VG_LITE_ERROR_HANDLER(_flatten_quad_bezier(stroke_conversion, rootCurve, subCurve1, level + 1));
  690. VG_LITE_ERROR_HANDLER(_flatten_quad_bezier(stroke_conversion, rootCurve, subCurve2, level + 1));
  691. if (level == 0) {
  692. /* Add point 2 separately to avoid cumulative errors. */
  693. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_END));
  694. /* Add extra P2 for outgoing tangent. */
  695. /* First change P2(point0)'s coordinates to P1. */
  696. point0 = stroke_conversion->path_end;
  697. point0->x = v1[0];
  698. point0->y = v1[1];
  699. /* Add P2 to calculate outgoing tangent. */
  700. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_NO));
  701. point1 = stroke_conversion->path_end;
  702. /* Change point0's coordinates back to P2. */
  703. point0->x = v2[0];
  704. point0->y = v2[1];
  705. point0->length = 0.0f;
  706. }
  707. ErrorHandler:
  708. return error;
  709. }
  710. static vg_lite_error_t _flatten_quad_bezier_original(
  711. vg_lite_stroke_t* stroke_conversion,
  712. vg_lite_float_t curve[6],
  713. vg_lite_uint8_t level)
  714. {
  715. vg_lite_error_t error = VG_LITE_SUCCESS;
  716. float* v0, * v1, * v2;
  717. float dx2, dy2, d1;
  718. float subCurve1[6], subCurve2[6];
  719. vg_lite_path_point_ptr point0, point1;
  720. if (!stroke_conversion)
  721. return VG_LITE_INVALID_ARGUMENT;
  722. if (level > 10) return error;
  723. v0 = &curve[0];
  724. v1 = &curve[2];
  725. v2 = &curve[4];
  726. if (level == 0) {
  727. /* Add extra P0 for incoming tangent. */
  728. point0 = stroke_conversion->path_end;
  729. /* First add P1 to calculate incoming tangent, which is saved in P0. */
  730. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v1[0], v1[1], vgcFLATTEN_NO));
  731. point1 = stroke_conversion->path_end;
  732. /* Change the point1's coordinates back to P0. */
  733. point1->x = v0[0];
  734. point1->y = v0[1];
  735. point0->length = 0.0f;
  736. }
  737. dx2 = v2[0] - v0[0];
  738. dy2 = v2[1] - v0[1];
  739. d1 = fabsf((v1[0] - v2[0]) * dy2 - (v1[1] - v2[1]) * dx2);
  740. if (d1 * d1 < 0.25 * (dx2 * dx2 + dy2 * dy2)) {
  741. float bound[4];
  742. bound[0] = MIN(v0[0], v2[0]);
  743. bound[1] = MIN(v0[1], v2[1]);
  744. bound[2] = MAX(v0[0], v2[0]);
  745. bound[3] = MAX(v0[1], v2[1]);
  746. if (!(v1[0] >= bound[0] && v1[0] <= bound[2] && v1[1] >= bound[1] && v1[1] <= bound[3])) {
  747. /* Compute root. */
  748. float alignedCurve[6];
  749. float d, n, t, pt[2];
  750. get_aligned_quad(alignedCurve, curve);
  751. n = alignedCurve[0] - alignedCurve[2];
  752. d = alignedCurve[0] - 2.f * alignedCurve[2] + alignedCurve[4];
  753. if (fabsf(d) > 1e-12f) {
  754. t = n / d;
  755. if (t > 1e-12f && t < 1.f - 1e-12f) {
  756. quad_bezier(&pt[0], &pt[1], curve, t);
  757. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, pt[0], pt[1], vgcFLATTEN_NO));
  758. }
  759. }
  760. }
  761. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_NO));
  762. return error;
  763. }
  764. split_quad(subCurve1, subCurve2, curve, 0.5);
  765. VG_LITE_ERROR_HANDLER(_flatten_quad_bezier_original(stroke_conversion, subCurve1, level + 1));
  766. VG_LITE_ERROR_HANDLER(_flatten_quad_bezier_original(stroke_conversion, subCurve2, level + 1));
  767. if (level == 0) {
  768. /* Add point 2 separately to avoid cumulative errors. */
  769. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_NO));
  770. /* Add extra P2 for outgoing tangent. */
  771. /* First change P2(point0)'s coordinates to P1. */
  772. point0 = stroke_conversion->path_end;
  773. point0->x = v1[0];
  774. point0->y = v1[1];
  775. /* Add P2 to calculate outgoing tangent. */
  776. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_NO));
  777. point1 = stroke_conversion->path_end;
  778. /* Change point0's coordinates back to P2. */
  779. point0->x = v2[0];
  780. point0->y = v2[1];
  781. point0->length = 0.0f;
  782. }
  783. ErrorHandler:
  784. return error;
  785. }
  786. static vg_lite_error_t _flatten_cubic_bezier(
  787. vg_lite_stroke_t* stroke_conversion,
  788. vg_lite_float_t rootCurve[8],
  789. vg_lite_float_t subCurve[8],
  790. vg_lite_uint8_t level)
  791. {
  792. vg_lite_error_t error = VG_LITE_SUCCESS;
  793. float* v0, * v1, * v2, * v3;
  794. float dx3, dy3, d1, d2;
  795. float subCurve1[8], subCurve2[8];
  796. vg_lite_path_point_ptr point0, point1;
  797. vg_lite_float_t* curve;
  798. if (!stroke_conversion)
  799. return VG_LITE_INVALID_ARGUMENT;
  800. if (level > 10) return error;
  801. curve = (level == 0) ? rootCurve : subCurve;
  802. v0 = &curve[0];
  803. v1 = &curve[2];
  804. v2 = &curve[4];
  805. v3 = &curve[6];
  806. if (level == 0) {
  807. /* Add extra P0 for incoming tangent. */
  808. point0 = stroke_conversion->path_end;
  809. /* First add P1/P2/P3 to calculate incoming tangent, which is saved in P0. */
  810. if (v0[0] != v1[0] || v0[1] != v1[1])
  811. {
  812. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v1[0], v1[1], vgcFLATTEN_START));
  813. }
  814. else if (v0[0] != v2[0] || v0[1] != v2[1])
  815. {
  816. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_START));
  817. }
  818. else
  819. {
  820. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_START));
  821. }
  822. point1 = stroke_conversion->path_end;
  823. /* Change the point1's coordinates back to P0. */
  824. point1->x = v0[0];
  825. point1->y = v0[1];
  826. point0->length = 0.0f;
  827. }
  828. dx3 = v3[0] - v0[0];
  829. dy3 = v3[1] - v0[1];
  830. d1 = fabsf((v1[0] - v3[0]) * dy3 - (v1[1] - v3[1]) * dx3);
  831. d2 = fabsf((v2[0] - v3[0]) * dy3 - (v2[1] - v3[1]) * dx3);
  832. if ((d1 + d2) * (d1 + d2) < 0.25f * (dx3 * dx3 + dy3 * dy3)) {
  833. float bound[4];
  834. bound[0] = MIN(v0[0], v3[0]);
  835. bound[1] = MIN(v0[1], v3[1]);
  836. bound[2] = MAX(v0[0], v3[0]);
  837. bound[3] = MAX(v0[1], v3[1]);
  838. if (!(v1[0] >= bound[0] && v1[0] <= bound[2] && v1[1] >= bound[1] && v1[1] <= bound[3]) ||
  839. !(v2[0] >= bound[0] && v2[0] <= bound[2] && v2[1] >= bound[1] && v2[1] <= bound[3])) {
  840. /* Compute root. */
  841. float alignedCurve[8];
  842. float a, b, c, b2ac, root[2], t, pt[2];
  843. uint8_t rootNum;
  844. get_aligned_cubic(alignedCurve, curve);
  845. a = -3.f * alignedCurve[0] + 9.f * alignedCurve[2] - 9.f * alignedCurve[4] + 3.f * alignedCurve[6];
  846. b = 6.f * alignedCurve[0] - 12.f * alignedCurve[2] + 6.f * alignedCurve[4];
  847. c = -3.f * alignedCurve[0] + 3.f * alignedCurve[2];
  848. rootNum = 0;
  849. if (fabs(a) < 1e-12f) { // linear solution
  850. t = -c / b;
  851. if (t > 1e-12f && t < 1.f - 1e-12f)
  852. root[rootNum++] = t;
  853. }
  854. else { // quadtratic solution
  855. b2ac = b * b - 4.f * a * c;
  856. if (b2ac > 1e-12f) {
  857. t = (-b + (float)sqrt(b2ac)) / (2.f * a);
  858. if (t > 1e-12f && t < 1.f - 1e-12f)
  859. root[rootNum++] = t;
  860. t = (-b - (float)sqrt(b2ac)) / (2.f * a);
  861. if (t > 1e-12f && t < 1.f - 1e-12f)
  862. root[rootNum++] = t;
  863. }
  864. }
  865. if (rootNum == 2 && root[0] > root[1]) {
  866. /* Exchange root. */
  867. float tmp;
  868. tmp = root[0];
  869. root[0] = root[1];
  870. root[1] = tmp;
  871. }
  872. if ((rootNum <= 2) && (level == 0)) {
  873. float pt[2];
  874. uint8_t n = 8;
  875. if (rootNum == 2)
  876. {
  877. float step = (root[1] - root[0]) / 8;
  878. float t = root[0];
  879. while (t < root[1])
  880. {
  881. cubic_bezier(&pt[0], &pt[1], curve, t);
  882. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, pt[0], pt[1], vgcFLATTEN_MIDDLE));
  883. t += step;
  884. }
  885. }
  886. else
  887. {
  888. for (uint8_t i = 1; i < n; i++) {
  889. vg_lite_float_t t = (vg_lite_float_t)i / (vg_lite_float_t)n;
  890. cubic_bezier(&pt[0], &pt[1], curve, t);
  891. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, pt[0], pt[1], vgcFLATTEN_MIDDLE));
  892. }
  893. }
  894. }
  895. else {
  896. for (uint8_t i = 0; i < rootNum; i++) {
  897. cubic_bezier(&pt[0], &pt[1], curve, root[i]);
  898. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, pt[0], pt[1], vgcFLATTEN_MIDDLE));
  899. }
  900. }
  901. }
  902. else if (level == 0) {
  903. vg_lite_float_t a1x, a1y, a2x, a2y, a3x, a3y;
  904. vg_lite_float_t ddf0, ddf1, t1, t2, upper_bound;
  905. vg_lite_uint32_t n;
  906. vg_lite_float_t pt[2];
  907. a1x = 3 * (v1[0] - v0[0]);
  908. a1y = 3 * (v1[1] - v0[1]);
  909. a2x = 3 * (v0[0] - v1[0] - v1[0] + v2[0]);
  910. a2y = 3 * (v0[1] - v1[1] - v1[1] + v2[1]);
  911. a3x = 3 * (v1[0] - v2[0]) + v3[0] - v0[0];
  912. a3y = 3 * (v1[1] - v2[1]) + v3[1] - v0[1];
  913. ddf0 = a2x * a2x + a2y * a2y;
  914. t1 = a2x + a3x + a3x + a3x;
  915. t2 = a2y + a3y + a3y + a3y;
  916. ddf1 = t1 * t1 + t2 * t2;
  917. upper_bound = ddf0 > ddf1 ? ddf0 : ddf1;
  918. upper_bound = SQRTF(upper_bound);
  919. upper_bound += upper_bound;
  920. upper_bound = SQRTF(upper_bound);
  921. if (stroke_conversion->fattened)
  922. {
  923. upper_bound *= stroke_conversion->line_width;
  924. }
  925. n = (vg_lite_uint32_t)ceil(upper_bound);
  926. if (n == 0 || n > 64)
  927. {
  928. n = (vg_lite_uint8_t)(64 / (level + 1));
  929. }
  930. for (vg_lite_uint32_t i = 1; i < n; i++) {
  931. vg_lite_float_t t = (vg_lite_float_t)i / (vg_lite_float_t)n;
  932. cubic_bezier(&pt[0], &pt[1], curve, t);
  933. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, pt[0], pt[1], vgcFLATTEN_MIDDLE));
  934. }
  935. }
  936. if (level == 0) {
  937. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_END));
  938. }
  939. else
  940. {
  941. vg_lite_float_t pt[2], t;
  942. for (int i = 1; i < 4; i++)
  943. {
  944. t = (vg_lite_float_t)i / 4;
  945. cubic_bezier(&pt[0], &pt[1], curve, t);
  946. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, pt[0], pt[1], vgcFLATTEN_MIDDLE));
  947. }
  948. if ((v3[0] != rootCurve[6]) || (v3[1] != rootCurve[7]))
  949. {
  950. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_MIDDLE));
  951. }
  952. }
  953. /* Add extra P3 for outgoing tangent. */
  954. /* First change P3(point0)'s coordinates to P0/P1/P2. */
  955. if (level == 0) {
  956. point0 = stroke_conversion->path_end;
  957. if (v3[0] != v2[0] || v3[1] != v2[1])
  958. {
  959. point0->x = v2[0];
  960. point0->y = v2[1];
  961. }
  962. else if (v3[0] != v1[0] || v3[1] != v1[1])
  963. {
  964. point0->x = v1[0];
  965. point0->y = v1[1];
  966. }
  967. else
  968. {
  969. point0->x = v0[0];
  970. point0->y = v0[1];
  971. }
  972. /* Add P3 to calculate outgoing tangent. */
  973. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_NO));
  974. point1 = stroke_conversion->path_end;
  975. /* Change point0's coordinates back to P3. */
  976. point0->x = v3[0];
  977. point0->y = v3[1];
  978. point0->length = 0.0f;
  979. }
  980. return error;
  981. }
  982. split_cubic(subCurve1, subCurve2, curve, 0.5);
  983. VG_LITE_ERROR_HANDLER(_flatten_cubic_bezier(stroke_conversion, rootCurve, subCurve1, level + 1));
  984. VG_LITE_ERROR_HANDLER(_flatten_cubic_bezier(stroke_conversion, rootCurve, subCurve2, level + 1));
  985. if (level == 0) {
  986. /* Add point 3 separately to avoid cumulative errors. */
  987. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_END));
  988. /* Add extra P3 for outgoing tangent. */
  989. /* First change P3(point0)'s coordinates to P0/P1/P2. */
  990. point0 = stroke_conversion->path_end;
  991. if (v3[0] != v2[0] || v3[1] != v2[1])
  992. {
  993. point0->x = v2[0];
  994. point0->y = v2[1];
  995. }
  996. else if (v3[0] != v1[0] || v3[1] != v1[1])
  997. {
  998. point0->x = v1[0];
  999. point0->y = v1[1];
  1000. }
  1001. else
  1002. {
  1003. point0->x = v0[0];
  1004. point0->y = v0[1];
  1005. }
  1006. /* Add P3 to calculate outgoing tangent. */
  1007. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_NO));
  1008. point1 = stroke_conversion->path_end;
  1009. /* Change point0's coordinates back to P3. */
  1010. point0->x = v3[0];
  1011. point0->y = v3[1];
  1012. point0->length = 0.0f;
  1013. }
  1014. ErrorHandler:
  1015. return error;
  1016. }
  1017. static vg_lite_error_t _flatten_cubic_bezier_original(
  1018. vg_lite_stroke_t* stroke_conversion,
  1019. vg_lite_float_t curve[8],
  1020. vg_lite_uint8_t level)
  1021. {
  1022. vg_lite_error_t error = VG_LITE_SUCCESS;
  1023. float* v0, * v1, * v2, * v3;
  1024. float dx3, dy3, d1, d2;
  1025. float subCurve1[8], subCurve2[8];
  1026. vg_lite_path_point_ptr point0, point1;
  1027. if (!stroke_conversion)
  1028. return VG_LITE_INVALID_ARGUMENT;
  1029. if (level > 10) return error;
  1030. v0 = &curve[0];
  1031. v1 = &curve[2];
  1032. v2 = &curve[4];
  1033. v3 = &curve[6];
  1034. if (level == 0) {
  1035. /* Add extra P0 for incoming tangent. */
  1036. point0 = stroke_conversion->path_end;
  1037. /* First add P1/P2/P3 to calculate incoming tangent, which is saved in P0. */
  1038. if (v0[0] != v1[0] || v0[1] != v1[1])
  1039. {
  1040. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v1[0], v1[1], vgcFLATTEN_NO));
  1041. }
  1042. else if (v0[0] != v2[0] || v0[1] != v2[1])
  1043. {
  1044. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v2[0], v2[1], vgcFLATTEN_NO));
  1045. }
  1046. else
  1047. {
  1048. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_NO));
  1049. }
  1050. point1 = stroke_conversion->path_end;
  1051. /* Change the point1's coordinates back to P0. */
  1052. point1->x = v0[0];
  1053. point1->y = v0[1];
  1054. point0->length = 0.0f;
  1055. }
  1056. dx3 = v3[0] - v0[0];
  1057. dy3 = v3[1] - v0[1];
  1058. d1 = fabsf((v1[0] - v3[0]) * dy3 - (v1[1] - v3[1]) * dx3);
  1059. d2 = fabsf((v2[0] - v3[0]) * dy3 - (v2[1] - v3[1]) * dx3);
  1060. if ((d1 + d2) * (d1 + d2) < 0.25f * (dx3 * dx3 + dy3 * dy3)) {
  1061. float bound[4];
  1062. bound[0] = MIN(v0[0], v3[0]);
  1063. bound[1] = MIN(v0[1], v3[1]);
  1064. bound[2] = MAX(v0[0], v3[0]);
  1065. bound[3] = MAX(v0[1], v3[1]);
  1066. if (!(v1[0] >= bound[0] && v1[0] <= bound[2] && v1[1] >= bound[1] && v1[1] <= bound[3]) ||
  1067. !(v2[0] >= bound[0] && v2[0] <= bound[2] && v2[1] >= bound[1] && v2[1] <= bound[3])) {
  1068. /* Compute root. */
  1069. float alignedCurve[8];
  1070. float a, b, c, b2ac, root[2], t, pt[2];
  1071. uint8_t rootNum;
  1072. get_aligned_cubic(alignedCurve, curve);
  1073. a = -3.f * alignedCurve[0] + 9.f * alignedCurve[2] - 9.f * alignedCurve[4] + 3.f * alignedCurve[6];
  1074. b = 6.f * alignedCurve[0] - 12.f * alignedCurve[2] + 6.f * alignedCurve[4];
  1075. c = -3.f * alignedCurve[0] + 3.f * alignedCurve[2];
  1076. rootNum = 0;
  1077. if (fabs(a) < 1e-12f) { // linear solution
  1078. t = -c / b;
  1079. if (t > 1e-12f && t < 1.f - 1e-12f)
  1080. root[rootNum++] = t;
  1081. }
  1082. else { // quadtratic solution
  1083. b2ac = b * b - 4.f * a * c;
  1084. if (b2ac > 1e-12f) {
  1085. t = (-b + (float)sqrt(b2ac)) / (2.f * a);
  1086. if (t > 1e-12f && t < 1.f - 1e-12f)
  1087. root[rootNum++] = t;
  1088. t = (-b - (float)sqrt(b2ac)) / (2.f * a);
  1089. if (t > 1e-12f && t < 1.f - 1e-12f)
  1090. root[rootNum++] = t;
  1091. }
  1092. }
  1093. if (rootNum == 2 && root[0] > root[1]) {
  1094. /* Exchange root. */
  1095. float tmp;
  1096. tmp = root[0];
  1097. root[0] = root[1];
  1098. root[1] = tmp;
  1099. }
  1100. for (uint8_t i = 0; i < rootNum; ++i) {
  1101. cubic_bezier(&pt[0], &pt[1], curve, root[i]);
  1102. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, pt[0], pt[1], vgcFLATTEN_NO));
  1103. }
  1104. }
  1105. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_NO));
  1106. return error;
  1107. }
  1108. split_cubic(subCurve1, subCurve2, curve, 0.5);
  1109. VG_LITE_ERROR_HANDLER(_flatten_cubic_bezier_original(stroke_conversion, subCurve1, level + 1));
  1110. VG_LITE_ERROR_HANDLER(_flatten_cubic_bezier_original(stroke_conversion, subCurve2, level + 1));
  1111. if (level == 0) {
  1112. /* Add point 3 separately to avoid cumulative errors. */
  1113. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_NO));
  1114. /* Add extra P3 for outgoing tangent. */
  1115. /* First change P3(point0)'s coordinates to P0/P1/P2. */
  1116. point0 = stroke_conversion->path_end;
  1117. if (v3[0] != v2[0] || v3[1] != v2[1])
  1118. {
  1119. point0->x = v2[0];
  1120. point0->y = v2[1];
  1121. }
  1122. else if (v3[0] != v1[0] || v3[1] != v1[1])
  1123. {
  1124. point0->x = v1[0];
  1125. point0->y = v1[1];
  1126. }
  1127. else
  1128. {
  1129. point0->x = v0[0];
  1130. point0->y = v0[1];
  1131. }
  1132. /* Add P3 to calculate outgoing tangent. */
  1133. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, v3[0], v3[1], vgcFLATTEN_NO));
  1134. point1 = stroke_conversion->path_end;
  1135. /* Change point0's coordinates back to P3. */
  1136. point0->x = v3[0];
  1137. point0->y = v3[1];
  1138. point0->length = 0.0f;
  1139. }
  1140. ErrorHandler:
  1141. return error;
  1142. }
  1143. #else
  1144. static vg_lite_error_t
  1145. _flatten_quad_bezier(
  1146. vg_lite_stroke_t * stroke_conversion,
  1147. vg_lite_float_t X0,
  1148. vg_lite_float_t Y0,
  1149. vg_lite_float_t X1,
  1150. vg_lite_float_t Y1,
  1151. vg_lite_float_t X2,
  1152. vg_lite_float_t Y2
  1153. )
  1154. {
  1155. vg_lite_error_t error = VG_LITE_SUCCESS;
  1156. uint32_t n;
  1157. vg_lite_path_point_ptr point0, point1;
  1158. vg_lite_float_t x, y;
  1159. vg_lite_float_t a1x, a1y, a2x, a2y;
  1160. vg_lite_float_t f1, f2, t1, t2, upper_bound;
  1161. if (!stroke_conversion)
  1162. return VG_LITE_INVALID_ARGUMENT;
  1163. /* Formula.
  1164. * f(t) = (1 - t)^2 * p0 + 2 * t * (1 - t) * p1 + t^2 * p2
  1165. * = a0 + a1 * t + a2 * t^2
  1166. * a0 = p0
  1167. * a1 = 2 * (-p0 + p1)
  1168. * a2 = p0 - 2 * p1 + p2
  1169. */
  1170. x = X1 - X0;
  1171. a1x = x + x;
  1172. y = Y1 - Y0;
  1173. a1y = y + y;
  1174. a2x = X0 - X1 - X1 + X2;
  1175. a2y = Y0 - Y1 - Y1 + Y2;
  1176. /* Step 1: Calculate N. */
  1177. /* Lefan's method. */
  1178. /* dist(t) = ...
  1179. * t2 = ...
  1180. * if 0 <= t2 <= 1
  1181. * upper_bound = dist(t2)
  1182. * else
  1183. * upper_bound = max(dist(0), dist(1))
  1184. * N = ceil(sqrt(upper_bound / epsilon / 8))
  1185. */
  1186. /* Prepare dist(t). */
  1187. f1 = a1x * a2y - a2x * a1y;
  1188. if (f1 != 0.0f)
  1189. {
  1190. if (f1 < 0.0f) f1 = -f1;
  1191. /* Calculate t2. */
  1192. t1 = a2x * a2x + a2y * a2y;
  1193. t2 = -(x * a2x + y * a2y) / t1;
  1194. /* Calculate upper_bound. */
  1195. if (t2 >= 0.0f && t2 <= 1.0f)
  1196. {
  1197. f2 = x + a2x * t2;
  1198. f2 *= f2;
  1199. t1 = y + a2y * t2;
  1200. t1 *= t1;
  1201. upper_bound = t1 + f2;
  1202. }
  1203. else
  1204. {
  1205. f2 = x + a2x;
  1206. f2 *= f2;
  1207. t1 = y + a2y;
  1208. t1 *= t1;
  1209. t2 = t1 + f2;
  1210. t1 = x * x + y * y;
  1211. upper_bound = t1 < t2 ? t1 : t2;
  1212. }
  1213. /* Calculate n. */
  1214. upper_bound = f1 / SQRTF(upper_bound);
  1215. upper_bound = SQRTF(upper_bound);
  1216. if (stroke_conversion->fattened)
  1217. {
  1218. upper_bound *= stroke_conversion->line_width;
  1219. }
  1220. n = (uint32_t) ceil(upper_bound);
  1221. }
  1222. else
  1223. {
  1224. /* n = 0 => n = 256. */
  1225. n = 256;
  1226. }
  1227. if (n == 0 || n > 256)
  1228. {
  1229. n = 256;
  1230. }
  1231. /* Add extra P0 for incoming tangent. */
  1232. point0 = stroke_conversion->path_end;
  1233. /* First add P1 to calculate incoming tangent, which is saved in P0. */
  1234. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X1, Y1, vgcFLATTEN_START));
  1235. point1 = stroke_conversion->path_end;
  1236. /* Change the point1's coordinates back to P0. */
  1237. point1->x = X0;
  1238. point1->y = Y0;
  1239. point0->length = 0.0f;
  1240. if (n > 1)
  1241. {
  1242. vg_lite_float_t d, dsquare, dx, dy, ddx, ddy;
  1243. vg_lite_float_t ratioX, ratioY;
  1244. uint32_t i;
  1245. /* Step 2: Calculate deltas. */
  1246. /* Df(t) = f(t + d) - f(t)
  1247. * = a1 * d + a2 * d^2 + 2 * a2 * d * t
  1248. * DDf(t) = Df(t + d) - Df(t)
  1249. * = 2 * a2 * d^2
  1250. * f(0) = a0
  1251. * Df(0) = a1 * d + a2 * d^2
  1252. * DDf(0) = 2 * a2 * d^2
  1253. */
  1254. d = 1.0f / (vg_lite_float_t) n;
  1255. dsquare = d * d;
  1256. ddx = a2x * dsquare;
  1257. ddy = a2y * dsquare;
  1258. dx = a1x * d + ddx;
  1259. dy = a1y * d + ddy;
  1260. ddx += ddx;
  1261. ddy += ddy;
  1262. /* Step 3: Add points. */
  1263. ratioX = dx / X0;
  1264. if (ratioX < 0.0f) ratioX = -ratioX;
  1265. ratioY = dy / Y0;
  1266. if (ratioY < 0.0f) ratioY = -ratioY;
  1267. if (ratioX > 1.0e-6f && ratioY > 1.0e-6f)
  1268. {
  1269. x = X0;
  1270. y = Y0;
  1271. for (i = 1; i < n; i++)
  1272. {
  1273. x += dx;
  1274. y += dy;
  1275. /* Add a point to subpath. */
  1276. VG_LITE_ERROR_HANDLER(_add_point_to_point_list_wdelta(stroke_conversion, x, y, dx, dy, vgcFLATTEN_MIDDLE));
  1277. dx += ddx;
  1278. dy += ddy;
  1279. }
  1280. }
  1281. else
  1282. {
  1283. for (i = 1; i < n; i++)
  1284. {
  1285. vg_lite_float_t t = (vg_lite_float_t) i / (vg_lite_float_t) n;
  1286. vg_lite_float_t u = 1.0f - t;
  1287. vg_lite_float_t a0 = u * u;
  1288. vg_lite_float_t a1 = 2.0f * t * u;
  1289. vg_lite_float_t a2 = t * t;
  1290. x = a0 * X0 + a1 * X1 + a2 * X2;
  1291. y = a0 * Y0 + a1 * Y1 + a2 * Y2;
  1292. /* Add a point to subpath. */
  1293. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, x, y, vgcFLATTEN_MIDDLE));
  1294. }
  1295. }
  1296. }
  1297. /* Add point 2 separately to avoid cumulative errors. */
  1298. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X2, Y2, vgcFLATTEN_END));
  1299. /* Add extra P2 for outgoing tangent. */
  1300. /* First change P2(point0)'s coordinates to P1. */
  1301. point0 = stroke_conversion->path_end;
  1302. point0->x = X1;
  1303. point0->y = Y1;
  1304. /* Add P2 to calculate outgoing tangent. */
  1305. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X2, Y2, vgcFLATTEN_NO));
  1306. point1 = stroke_conversion->path_end;
  1307. /* Change point0's coordinates back to P2. */
  1308. point0->x = X2;
  1309. point0->y = Y2;
  1310. point0->length = 0.0f;
  1311. ErrorHandler:
  1312. return error;
  1313. }
  1314. static vg_lite_error_t
  1315. _flatten_cubic_bezier(
  1316. vg_lite_stroke_t * stroke_conversion,
  1317. vg_lite_float_t X0,
  1318. vg_lite_float_t Y0,
  1319. vg_lite_float_t X1,
  1320. vg_lite_float_t Y1,
  1321. vg_lite_float_t X2,
  1322. vg_lite_float_t Y2,
  1323. vg_lite_float_t X3,
  1324. vg_lite_float_t Y3
  1325. )
  1326. {
  1327. vg_lite_error_t error = VG_LITE_SUCCESS;
  1328. uint32_t n;
  1329. vg_lite_path_point_ptr point0, point1;
  1330. vg_lite_float_t x, y;
  1331. vg_lite_float_t a1x, a1y, a2x, a2y, a3x, a3y;
  1332. vg_lite_float_t ddf0, ddf1, t1, t2, upper_bound;
  1333. if (!stroke_conversion)
  1334. return VG_LITE_INVALID_ARGUMENT;
  1335. /* Formula.
  1336. * f(t) = (1 - t)^3 * p0 + 3 * t * (1 - t)^2 * p1 + 3 * t^2 * (1 - t) * p2 + t^3 * p3
  1337. * = a0 + a1 * t + a2 * t^2 + a3 * t^3
  1338. */
  1339. x = X1 - X0;
  1340. a1x = x + x + x;
  1341. y = Y1 - Y0;
  1342. a1y = y + y + y;
  1343. x = X0 - X1 - X1 + X2;
  1344. a2x = x + x + x;
  1345. y = Y0 - Y1 - Y1 + Y2;
  1346. a2y = y + y + y;
  1347. x = X1 - X2;
  1348. a3x = x + x + x + X3 - X0;
  1349. y = Y1 - Y2;
  1350. a3y = y + y + y + Y3 - Y0;
  1351. /* Step 1: Calculate N. */
  1352. /* Lefan's method. */
  1353. /* df(t)/dt = a1 + 2 * a2 * t + 3 * a3 * t^2
  1354. * d2f(t)/dt2 = 2 * a2 + 6 * a3 * t
  1355. * N = ceil(sqrt(max(ddfx(0)^2 + ddfy(0)^2, ddfx(1)^2 + ddyf(1)^2) / epsilon / 8))
  1356. */
  1357. ddf0 = a2x * a2x + a2y * a2y;
  1358. t1 = a2x + a3x + a3x + a3x;
  1359. t2 = a2y + a3y + a3y + a3y;
  1360. ddf1 = t1 * t1 + t2 * t2;
  1361. upper_bound = ddf0 > ddf1 ? ddf0: ddf1;
  1362. upper_bound = SQRTF(upper_bound);
  1363. upper_bound += upper_bound;
  1364. upper_bound = SQRTF(upper_bound);
  1365. if (stroke_conversion->fattened)
  1366. {
  1367. upper_bound *= stroke_conversion->line_width;
  1368. }
  1369. n = (uint32_t) ceil(upper_bound);
  1370. if (n == 0 || n > 256)
  1371. {
  1372. n = 256;
  1373. }
  1374. /* Add extra P0 for incoming tangent. */
  1375. point0 = stroke_conversion->path_end;
  1376. /* First add P1/P2/P3 to calculate incoming tangent, which is saved in P0. */
  1377. if (X0 != X1 || Y0 != Y1)
  1378. {
  1379. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X1, Y1, vgcFLATTEN_START));
  1380. }
  1381. else if (X0 != X2 || Y0 != Y2)
  1382. {
  1383. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X2, Y2, vgcFLATTEN_START));
  1384. }
  1385. else
  1386. {
  1387. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X3, Y3, vgcFLATTEN_START));
  1388. }
  1389. point1 = stroke_conversion->path_end;
  1390. /* Change the point1's coordinates back to P0. */
  1391. point1->x = X0;
  1392. point1->y = Y0;
  1393. point0->length = 0.0f;
  1394. if (n > 1)
  1395. {
  1396. vg_lite_float_t d, dsquare, dcube, dx, dy, ddx, ddy, dddx, dddy;
  1397. vg_lite_float_t ratioX, ratioY;
  1398. uint32_t i;
  1399. /* Step 2: Calculate deltas */
  1400. /* Df(t) = f(t + d) - f(t)
  1401. * DDf(t) = Df(t + d) - Df(t)
  1402. * DDDf(t) = DDf(t + d) - DDf(t)
  1403. * f(0) = a0
  1404. * Df(0) = a1 * d + a2 * d^2 + a3 * d^3
  1405. * DDf(0) = 2 * a2 * d^2 + 6 * a3 * d^3
  1406. * DDDf(0) = 6 * a3 * d^3
  1407. */
  1408. d = 1.0f / (vg_lite_float_t) n;
  1409. dsquare = d * d;
  1410. dcube = dsquare * d;
  1411. ddx = a2x * dsquare;
  1412. ddy = a2y * dsquare;
  1413. dddx = a3x * dcube;
  1414. dddy = a3y * dcube;
  1415. dx = a1x * d + ddx + dddx;
  1416. dy = a1y * d + ddy + dddy;
  1417. ddx += ddx;
  1418. ddy += ddy;
  1419. dddx *= 6.0f;
  1420. dddy *= 6.0f;
  1421. ddx += dddx;
  1422. ddy += dddy;
  1423. /* Step 3: Add points. */
  1424. ratioX = dx / X0;
  1425. if (ratioX < 0.0f) ratioX = -ratioX;
  1426. ratioY = dy / Y0;
  1427. if (ratioY < 0.0f) ratioY = -ratioY;
  1428. if (ratioX > 1.0e-6f && ratioY > 1.0e-6f)
  1429. {
  1430. x = X0;
  1431. y = Y0;
  1432. for (i = 1; i < n; i++)
  1433. {
  1434. x += dx;
  1435. y += dy;
  1436. /* Add a point to subpath. */
  1437. VG_LITE_ERROR_HANDLER(_add_point_to_point_list_wdelta(stroke_conversion, x, y, dx, dy, vgcFLATTEN_MIDDLE));
  1438. dx += ddx; ddx += dddx;
  1439. dy += ddy; ddy += dddy;
  1440. }
  1441. }
  1442. else
  1443. {
  1444. for (i = 1; i < n; i++)
  1445. {
  1446. vg_lite_float_t t = (vg_lite_float_t) i / (vg_lite_float_t) n;
  1447. vg_lite_float_t tSquare = t * t;
  1448. vg_lite_float_t tCube = tSquare * t;
  1449. vg_lite_float_t a0 = 1.0f - 3.0f * t + 3.0f * tSquare - tCube;
  1450. vg_lite_float_t a1 = 3.0f * t - 6.0f * tSquare + 3.0f * tCube;
  1451. vg_lite_float_t a2 = 3.0f * tSquare - 3.0f * tCube;
  1452. vg_lite_float_t a3 = tCube;
  1453. x = a0 * X0 + a1 * X1 + a2 * X2 + a3 * X3;
  1454. y = a0 * Y0 + a1 * Y1 + a2 * Y2 + a3 * Y3;
  1455. /* Add a point to subpath. */
  1456. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, x, y, vgcFLATTEN_MIDDLE));
  1457. }
  1458. }
  1459. }
  1460. /* Add point 3 separately to avoid cumulative errors. */
  1461. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X3, Y3, vgcFLATTEN_END));
  1462. /* Add extra P3 for outgoing tangent. */
  1463. /* First change P3(point0)'s coordinates to P0/P1/P2. */
  1464. point0 = stroke_conversion->path_end;
  1465. if (X3 != X2 || Y3 != Y2)
  1466. {
  1467. point0->x = X2;
  1468. point0->y = Y2;
  1469. }
  1470. else if (X3 != X1 || Y3 != Y1)
  1471. {
  1472. point0->x = X1;
  1473. point0->y = Y1;
  1474. }
  1475. else
  1476. {
  1477. point0->x = X0;
  1478. point0->y = Y0;
  1479. }
  1480. /* Add P3 to calculate outgoing tangent. */
  1481. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X3, Y3, vgcFLATTEN_NO));
  1482. point1 = stroke_conversion->path_end;
  1483. /* Change point0's coordinates back to P3. */
  1484. point0->x = X3;
  1485. point0->y = Y3;
  1486. point0->length = 0.0f;
  1487. ErrorHandler:
  1488. return error;
  1489. }
  1490. #endif /* gcFEATURE_VG_SIMPLYFIED_BEZIER */
  1491. #define GETINCREMENT(pointer, datatype_size) \
  1492. (datatype_size - (PTR2SIZE(pointer) & (datatype_size - 1)))
  1493. #define SKIPTODATA(pointer, datatype_size, SIZE) \
  1494. /* Determine the increment value. */ \
  1495. increment = GETINCREMENT(pointer, datatype_size); \
  1496. /* Skip to the data. */ \
  1497. pointer += increment; \
  1498. SIZE -= increment
  1499. #define VGSL_GETVALUE(X) \
  1500. X = get_value(data_pointer); \
  1501. data_pointer += data_type_size; \
  1502. size -= data_type_size
  1503. #define VGSL_GETCOORDXY(X, Y) \
  1504. VGSL_GETVALUE(X); \
  1505. VGSL_GETVALUE(Y); \
  1506. if (is_relative) { X += ox; Y += oy; }
  1507. typedef vg_lite_float_t(*vg_value_getter)(int8_t* Data);
  1508. static vg_lite_error_t _flatten_path(
  1509. vg_lite_stroke_t * stroke_conversion,
  1510. vg_lite_path_t *path
  1511. )
  1512. {
  1513. vg_lite_error_t error = VG_LITE_SUCCESS;
  1514. uint32_t increment;
  1515. uint8_t is_relative;
  1516. uint32_t size;
  1517. uint32_t path_command;
  1518. uint32_t prev_command;
  1519. uint8_t data_type_size;
  1520. int8_t* data_pointer = NULL;
  1521. int8_t* data_pointer_use = NULL;
  1522. vg_lite_float_t sx, sy;
  1523. vg_lite_float_t ox, oy;
  1524. vg_lite_float_t px, py;
  1525. vg_lite_float_t x0, y0, x1, y1, x2, y2;
  1526. vg_value_getter get_value = NULL;
  1527. if (!stroke_conversion || !path)
  1528. return VG_LITE_INVALID_ARGUMENT;
  1529. sx = sy = ox = oy = px = py = 0.0f;
  1530. prev_command = 0xFF;
  1531. /* Select the data picker. */
  1532. switch (path->format)
  1533. {
  1534. case VG_LITE_S8:
  1535. data_type_size = 1;
  1536. get_value = _GetS8_NS_NB;
  1537. break;
  1538. case VG_LITE_S16:
  1539. data_type_size = 2;
  1540. get_value = _GetS16_NS_NB;
  1541. break;
  1542. case VG_LITE_S32:
  1543. data_type_size = 4;
  1544. get_value = _GetS32_NS_NB;
  1545. break;
  1546. case VG_LITE_FP32:
  1547. data_type_size = 4;
  1548. get_value = _GetF_NS_NB;
  1549. break;
  1550. default:
  1551. error = VG_LITE_INVALID_ARGUMENT;
  1552. goto ErrorHandler;
  1553. }
  1554. if ((path->path_type == VG_LITE_DRAW_FILL_PATH) || (path->path_type == VG_LITE_DRAW_FILL_STROKE_PATH))
  1555. {
  1556. if (path->path_length % (3 * data_type_size) == 0)
  1557. {
  1558. /* add END_PATH if path_data have no END_PATH */
  1559. stroke_conversion->add_end = 1;
  1560. path->path_length = path->path_length + data_type_size;
  1561. data_pointer_use = (int8_t*)vg_lite_os_malloc(path->path_length);
  1562. if (!data_pointer_use)
  1563. return VG_LITE_OUT_OF_RESOURCES;
  1564. memset(data_pointer_use, 0, path->path_length);
  1565. memcpy((int8_t*)data_pointer_use, (int8_t*)path->path, path->path_length - data_type_size);
  1566. vg_lite_os_free(path->path);
  1567. path->path = data_pointer_use;
  1568. path->pdata_internal = 1;
  1569. }
  1570. if (path->add_end == 1)
  1571. {
  1572. stroke_conversion->add_end = 1;
  1573. }
  1574. else
  1575. {
  1576. stroke_conversion->add_end = 0;
  1577. }
  1578. }
  1579. /* Determine the data size. */
  1580. size = path->path_length;
  1581. /* Determine the beginning of the path data. */
  1582. data_pointer = (int8_t*)path->path;
  1583. /* Add an extra gcvVGCMD_MOVE 0.0 0.0 to handle the case the first command is not gcvVGCMD_MOVE. */
  1584. if ((*data_pointer & 0xfe) != VLC_OP_MOVE)
  1585. {
  1586. /* Add first point to subpath. */
  1587. VG_LITE_ERROR_HANDLER(_create_new_point_list(stroke_conversion, 0.f, 0.f, vgcFLATTEN_NO));
  1588. }
  1589. while (size > 0)
  1590. {
  1591. /* Get the command. */
  1592. path_command = *data_pointer & 0x1F;
  1593. /* Assume absolute. */
  1594. is_relative = VGL_FALSE;
  1595. switch (path_command)
  1596. {
  1597. case VLC_OP_END:
  1598. /* Skip the command. */
  1599. size -= 1;
  1600. if (prev_command == VLC_OP_END)
  1601. {
  1602. /* Continuous gcvVGCMD_CLOSE - do nothing. */
  1603. break;
  1604. }
  1605. if ((prev_command & 0xfe) == VLC_OP_MOVE) {
  1606. /* Delete the invalid path list. */
  1607. vg_lite_path_list_ptr path_list_divide = stroke_conversion->cur_list;
  1608. vg_lite_os_free(path_list_divide->path_points);
  1609. vg_lite_os_free(path_list_divide);
  1610. if (stroke_conversion->cur_list == stroke_conversion->path_list_divide) {
  1611. stroke_conversion->cur_list = stroke_conversion->path_list_divide = NULL;
  1612. stroke_conversion->path_end = NULL;
  1613. stroke_conversion->path_points = NULL;
  1614. stroke_conversion->point_count = 0;
  1615. }
  1616. else {
  1617. stroke_conversion->cur_list = stroke_conversion->path_list_divide;
  1618. while (stroke_conversion->cur_list->next != path_list_divide)
  1619. stroke_conversion->cur_list = stroke_conversion->cur_list->next;
  1620. stroke_conversion->path_end = stroke_conversion->cur_list->path_end;
  1621. stroke_conversion->point_count = stroke_conversion->cur_list->point_count;
  1622. stroke_conversion->cur_list->next = NULL;
  1623. }
  1624. break;
  1625. }
  1626. if (!stroke_conversion->add_end)
  1627. {
  1628. /* Check if subPath is already closed. */
  1629. if (ox != sx || oy != sy)
  1630. {
  1631. /* Add a line from current point to the first point of current subpath. */
  1632. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, sx, sy, vgcFLATTEN_NO));
  1633. }
  1634. if (stroke_conversion->path_points != stroke_conversion->path_end)
  1635. {
  1636. /* Copy tangent data from first point to last_point. */
  1637. vg_lite_path_point_ptr first_point = stroke_conversion->path_points;
  1638. vg_lite_path_point_ptr last_point = stroke_conversion->path_end;
  1639. last_point->length = first_point->length;
  1640. last_point->tangentX = first_point->tangentX;
  1641. last_point->tangentY = first_point->tangentY;
  1642. }
  1643. else
  1644. {
  1645. /* Single point path. */
  1646. vg_lite_path_point_ptr point = stroke_conversion->path_points;
  1647. point->tangentX = 0.0f;
  1648. point->tangentY = 0.0f;
  1649. point->length = 0.0f;
  1650. }
  1651. stroke_conversion->cur_list->closed = 1;
  1652. stroke_conversion->closed = 1;
  1653. stroke_conversion->path_end->next = NULL;
  1654. }
  1655. break;
  1656. case VLC_OP_CLOSE:
  1657. /* Skip the command. */
  1658. SKIPTODATA(data_pointer, data_type_size, size);
  1659. if (prev_command == VLC_OP_CLOSE)
  1660. {
  1661. /* Continuous gcvVGCMD_CLOSE - do nothing. */
  1662. break;
  1663. }
  1664. /* Check if subPath is already closed. */
  1665. if (ox != sx || oy != sy)
  1666. {
  1667. /* Add a line from current point to the first point of current subpath. */
  1668. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, sx, sy, vgcFLATTEN_NO));
  1669. }
  1670. if (stroke_conversion->path_points != stroke_conversion->path_end)
  1671. {
  1672. /* Copy tangent data from first point to last_point. */
  1673. vg_lite_path_point_ptr first_point = stroke_conversion->path_points;
  1674. vg_lite_path_point_ptr last_point = stroke_conversion->path_end;
  1675. last_point->length = first_point->length;
  1676. last_point->tangentX = first_point->tangentX;
  1677. last_point->tangentY = first_point->tangentY;
  1678. }
  1679. else
  1680. {
  1681. /* Single point path. */
  1682. vg_lite_path_point_ptr point = stroke_conversion->path_points;
  1683. point->tangentX = 0.0f;
  1684. point->tangentY = 0.0f;
  1685. point->length = 0.0f;
  1686. }
  1687. px = ox = sx;
  1688. py = oy = sy;
  1689. stroke_conversion->cur_list->closed = 1;
  1690. stroke_conversion->closed = 1;
  1691. break;
  1692. case VLC_OP_MOVE_REL:
  1693. is_relative = 1;
  1694. case VLC_OP_MOVE: /* Indicate the beginning of a new sub-path. */
  1695. /* Skip to the data. */
  1696. SKIPTODATA(data_pointer, data_type_size, size);
  1697. VGSL_GETCOORDXY(x0, y0);
  1698. if ((prev_command & 0xfe) == VLC_OP_MOVE) {
  1699. /* Continuous gcvVGCMD_MOVE draw nothing */
  1700. stroke_conversion->path_points->x = x0;
  1701. stroke_conversion->path_points->y = y0;
  1702. }
  1703. else {
  1704. /* First command is gcvVGCMD_MOVE. */
  1705. /* Add first point to subpath. */
  1706. VG_LITE_ERROR_HANDLER(_create_new_point_list(stroke_conversion, x0, y0, vgcFLATTEN_NO));
  1707. }
  1708. sx = px = ox = x0;
  1709. sy = py = oy = y0;
  1710. break;
  1711. case VLC_OP_LINE_REL:
  1712. is_relative = 1;
  1713. case VLC_OP_LINE:
  1714. /* Skip to the data. */
  1715. SKIPTODATA(data_pointer, data_type_size, size);
  1716. VGSL_GETCOORDXY(x0, y0);
  1717. /* Add a point to subpath. */
  1718. VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, x0, y0, vgcFLATTEN_NO));
  1719. px = ox = x0;
  1720. py = oy = y0;
  1721. break;
  1722. case VLC_OP_QUAD_REL:
  1723. is_relative = 1;
  1724. case VLC_OP_QUAD:
  1725. /* Skip to the data. */
  1726. SKIPTODATA(data_pointer, data_type_size, size);
  1727. VGSL_GETCOORDXY(x0, y0);
  1728. VGSL_GETCOORDXY(x1, y1);
  1729. if ((ox == x0 && oy == y0) && (ox == x1 && oy == y1))
  1730. {
  1731. /* Degenerated Bezier curve. Becomes a point. */
  1732. /* Discard zero-length segments. */
  1733. }
  1734. else if ((ox == x0 && oy == y0) || (x0 == x1 && y0 == y1))
  1735. {
  1736. /* Degenerated Bezier curve. Becomes a line. */
  1737. /* Add a point to subpath. */
  1738. VG_LITE_ERROR_HANDLER(_add_point_to_point_list( stroke_conversion, x1, y1, vgcFLATTEN_NO));
  1739. }
  1740. else
  1741. {
  1742. #if gcFEATURE_VG_SIMPLYFIED_BEZIER
  1743. vg_lite_float_t curve[6] = { ox, oy, x0, y0, x1, y1 };
  1744. #if (CHIPID != 0x265)
  1745. vg_lite_float_t subCurve[6] = { 0, 0, 0, 0, 0, 0};
  1746. VG_LITE_ERROR_HANDLER(_flatten_quad_bezier(stroke_conversion, curve, subCurve, 0));
  1747. #else
  1748. VG_LITE_ERROR_HANDLER(_flatten_quad_bezier_original(stroke_conversion, curve, 0));
  1749. #endif
  1750. #else
  1751. VG_LITE_ERROR_HANDLER(_flatten_quad_bezier(stroke_conversion, ox, oy, x0, y0, x1, y1));
  1752. #endif
  1753. }
  1754. px = x0;
  1755. py = y0;
  1756. ox = x1;
  1757. oy = y1;
  1758. break;
  1759. case VLC_OP_CUBIC_REL:
  1760. is_relative = 1;
  1761. case VLC_OP_CUBIC:
  1762. /* Skip to the data. */
  1763. SKIPTODATA(data_pointer, data_type_size, size);
  1764. VGSL_GETCOORDXY(x0, y0);
  1765. VGSL_GETCOORDXY(x1, y1);
  1766. VGSL_GETCOORDXY(x2, y2);
  1767. if ((ox == x0 && oy == y0) && (ox == x1 && oy == y1) && (ox == x2 && oy == y2))
  1768. {
  1769. /* Degenerated Bezier curve. Becomes a point. */
  1770. /* Discard zero-length segments. */
  1771. }
  1772. else
  1773. {
  1774. #if gcFEATURE_VG_SIMPLYFIED_BEZIER
  1775. vg_lite_float_t curve[8] = { ox, oy, x0, y0, x1, y1, x2, y2 };
  1776. #if (CHIPID != 0x265)
  1777. vg_lite_float_t subCurve[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  1778. VG_LITE_ERROR_HANDLER(_flatten_cubic_bezier(stroke_conversion, curve, subCurve, 0));
  1779. #else
  1780. VG_LITE_ERROR_HANDLER(_flatten_cubic_bezier_original(stroke_conversion, curve, 0));
  1781. #endif
  1782. #else
  1783. VG_LITE_ERROR_HANDLER(_flatten_cubic_bezier(stroke_conversion, ox, oy, x0, y0, x1, y1, x2, y2));
  1784. #endif
  1785. }
  1786. px = x1;
  1787. py = y1;
  1788. ox = x2;
  1789. oy = y2;
  1790. break;
  1791. default:
  1792. error = VG_LITE_INVALID_ARGUMENT;
  1793. goto ErrorHandler;
  1794. }
  1795. prev_command = path_command;
  1796. }
  1797. if ((prev_command != VLC_OP_END))
  1798. {
  1799. stroke_conversion->cur_list->path_end->next = NULL;
  1800. stroke_conversion->path_end->next = NULL;
  1801. if (stroke_conversion->point_count == 1)
  1802. {
  1803. /* Single point path. */
  1804. vg_lite_path_point_ptr point = stroke_conversion->path_points;
  1805. point->tangentX = 0.0f;
  1806. point->tangentY = 0.0f;
  1807. point->length = 0.0f;
  1808. }
  1809. }
  1810. ErrorHandler:
  1811. return error;
  1812. }
  1813. static vg_lite_error_t
  1814. _add_point_to_right_stroke_point_list_tail(
  1815. vg_lite_stroke_t * stroke_conversion,
  1816. vg_lite_float_t X,
  1817. vg_lite_float_t Y
  1818. )
  1819. {
  1820. vg_lite_error_t error = VG_LITE_SUCCESS;
  1821. vg_lite_path_point_ptr point;
  1822. if (!stroke_conversion)
  1823. return VG_LITE_INVALID_ARGUMENT;
  1824. point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*point));
  1825. if (!point)
  1826. return VG_LITE_OUT_OF_RESOURCES;
  1827. memset(point, 0, sizeof(*point));
  1828. point->x = X;
  1829. point->y = Y;
  1830. point->curve_type = CURVE_LINE;
  1831. point->prev = stroke_conversion->right_point;
  1832. point->next = NULL;
  1833. stroke_conversion->right_point->next = point;
  1834. stroke_conversion->right_point = point;
  1835. stroke_conversion->stroke_count++;
  1836. stroke_conversion->last_stroke->point_count++;
  1837. return error;
  1838. }
  1839. static vg_lite_error_t
  1840. _add_point_to_left_point_list_head(
  1841. vg_lite_stroke_t * stroke_conversion,
  1842. vg_lite_float_t X,
  1843. vg_lite_float_t Y
  1844. )
  1845. {
  1846. vg_lite_error_t error = VG_LITE_SUCCESS;
  1847. vg_lite_path_point_ptr point;
  1848. if (!stroke_conversion)
  1849. return VG_LITE_INVALID_ARGUMENT;
  1850. point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*point));
  1851. if (!point)
  1852. return VG_LITE_OUT_OF_RESOURCES;
  1853. memset(point, 0, sizeof(*point));
  1854. point->x = X;
  1855. point->y = Y;
  1856. point->curve_type = CURVE_LINE;
  1857. point->next = stroke_conversion->left_point;
  1858. point->prev = NULL;
  1859. stroke_conversion->left_point->prev = point;
  1860. stroke_conversion->left_point = point;
  1861. stroke_conversion->stroke_count++;
  1862. stroke_conversion->last_stroke->point_count++;
  1863. return error;
  1864. }
  1865. static vg_lite_error_t _add_stroke_sub_path(
  1866. vg_lite_stroke_t * stroke_conversion,
  1867. vg_lite_sub_path_ptr *sub_path
  1868. )
  1869. {
  1870. vg_lite_error_t error = VG_LITE_SUCCESS;
  1871. if (!stroke_conversion || !sub_path)
  1872. return VG_LITE_INVALID_ARGUMENT;
  1873. *sub_path = (vg_lite_sub_path_ptr)vg_lite_os_malloc(sizeof(**sub_path));
  1874. if (!*sub_path)
  1875. return VG_LITE_OUT_OF_RESOURCES;
  1876. memset(*sub_path, 0, sizeof(**sub_path));
  1877. if (stroke_conversion->last_stroke != NULL)
  1878. {
  1879. stroke_conversion->last_stroke->next = *sub_path;
  1880. stroke_conversion->last_stroke = *sub_path;
  1881. }
  1882. else
  1883. {
  1884. stroke_conversion->last_stroke = stroke_conversion->stroke_paths = *sub_path;
  1885. }
  1886. return error;
  1887. }
  1888. static vg_lite_error_t
  1889. _add_zero_length_stroke_sub_path(
  1890. vg_lite_stroke_t * stroke_conversion,
  1891. vg_lite_sub_path_ptr *stroke_subpath
  1892. )
  1893. {
  1894. vg_lite_error_t error = VG_LITE_SUCCESS;
  1895. vg_lite_path_point_ptr new_point,Point;
  1896. vg_lite_sub_path_ptr stroke_sub_path;
  1897. vg_lite_float_t half_width;
  1898. if (!stroke_conversion)
  1899. return VG_LITE_INVALID_ARGUMENT;
  1900. half_width = stroke_conversion->half_width;
  1901. Point = stroke_conversion->path_points;
  1902. if (stroke_conversion->cap_style == VG_LITE_CAP_BUTT)
  1903. {
  1904. /* No need to draw zero-length subPath for gcvCAP_BUTT. */
  1905. error = VG_LITE_SUCCESS;
  1906. goto ErrorHandler;
  1907. }
  1908. VG_LITE_ERROR_HANDLER(_add_stroke_sub_path(stroke_conversion, &stroke_sub_path));
  1909. if (stroke_conversion->cap_style == VG_LITE_CAP_SQUARE)
  1910. {
  1911. /* Draw a square along the point's direction. */
  1912. vg_lite_float_t dx, dy;
  1913. if (Point->tangentX == 0.0f || Point->tangentY == 0.0f)
  1914. {
  1915. dx = half_width;
  1916. dy = 0.0f;
  1917. }
  1918. else
  1919. {
  1920. dx = Point->tangentY * half_width;
  1921. dy = -Point->tangentX * half_width;
  1922. }
  1923. new_point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*new_point));
  1924. if (!new_point)
  1925. return VG_LITE_OUT_OF_RESOURCES;
  1926. memset(new_point, 0, sizeof(*new_point));
  1927. new_point->x = Point->x + dx + dy;
  1928. new_point->y = Point->y - dx + dy;
  1929. new_point->curve_type = CURVE_LINE;
  1930. stroke_sub_path->point_list = stroke_conversion->right_point = new_point;
  1931. stroke_sub_path->point_count = 1;
  1932. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
  1933. Point->x + dx - dy, Point->y + dx + dy));
  1934. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
  1935. Point->x - dx - dy, Point->y + dx - dy));
  1936. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
  1937. Point->x - dx + dy, Point->y - dx - dy));
  1938. }
  1939. else
  1940. {
  1941. /* Draw a circle. */
  1942. new_point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*new_point));
  1943. if (!new_point)
  1944. return VG_LITE_OUT_OF_RESOURCES;
  1945. memset(new_point, 0, sizeof(*new_point));
  1946. new_point->x = Point->x + half_width;
  1947. new_point->y = Point->y;
  1948. new_point->curve_type = CURVE_LINE;
  1949. stroke_sub_path->point_list = stroke_conversion->right_point = new_point;
  1950. stroke_sub_path->point_count = 1;
  1951. /* Add upper half circle. */
  1952. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
  1953. Point->x - half_width, Point->y));
  1954. stroke_conversion->right_point->curve_type = CURVE_ARC_SCCW_HALF;
  1955. stroke_conversion->right_point->tangentX = Point->x;
  1956. stroke_conversion->right_point->tangentY = Point->y;
  1957. /* Add lower half circle. */
  1958. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
  1959. Point->x + half_width, Point->y));
  1960. stroke_conversion->right_point->curve_type = CURVE_ARC_SCCW_HALF;
  1961. stroke_conversion->right_point->tangentX = Point->x;
  1962. stroke_conversion->right_point->tangentY = Point->y;
  1963. }
  1964. stroke_sub_path->end_point = stroke_conversion->right_point;
  1965. stroke_sub_path->end_point->next = NULL;
  1966. ErrorHandler:
  1967. return error;
  1968. }
  1969. /* Special asin(x) for quick calculation when -sqrt(0.5) <= x <= sqrt(0.5). */
  1970. static vg_lite_float_t _Asin(
  1971. vg_lite_float_t X
  1972. )
  1973. {
  1974. vg_lite_float_t x = X;
  1975. vg_lite_float_t x2 = X * X;
  1976. vg_lite_float_t s = X;
  1977. x *= x2;
  1978. s += x * 0.1660510562575219f;
  1979. x *= x2;
  1980. s += x * 0.084044676143618186f;
  1981. x *= x2;
  1982. s += x * 0.0023776176698039313f;
  1983. x *= x2;
  1984. s += x * 0.10211922020091345f;
  1985. return s;
  1986. }
  1987. /* Special cos(x) for quick calculation when -PI <= x <= PI. */
  1988. static vg_lite_float_t _Cos(
  1989. vg_lite_float_t X
  1990. )
  1991. {
  1992. vg_lite_float_t x2 = X * X;
  1993. vg_lite_float_t x = x2;
  1994. vg_lite_float_t s = 1.0f;
  1995. s -= x * 0.49985163079668843f;
  1996. x *= x2;
  1997. s += x * 0.041518066216932693f;
  1998. x *= x2;
  1999. s -= x * 0.0013422997970712939f;
  2000. x *= x2;
  2001. s += x * 0.000018930111278021357f;
  2002. return s;
  2003. }
  2004. /* Special sin(x) for quick calculation when -PI <= x <= PI. */
  2005. static vg_lite_float_t _Sine(
  2006. vg_lite_float_t X
  2007. )
  2008. {
  2009. vg_lite_float_t x = X;
  2010. vg_lite_float_t x2 = X * X;
  2011. vg_lite_float_t s = X;
  2012. x *= x2;
  2013. s -= x * 0.16664527099620879f;
  2014. x *= x2;
  2015. s += x * 0.0083154803736487041f;
  2016. x *= x2;
  2017. s -= x * 0.00019344151251408578f;
  2018. x *= x2;
  2019. s += x * 0.0000021810214160988925f;
  2020. return s;
  2021. }
  2022. static vg_lite_float_t
  2023. _Angle(
  2024. vg_lite_float_t X,
  2025. vg_lite_float_t Y,
  2026. vg_lite_float_t Length
  2027. )
  2028. {
  2029. vg_lite_float_t angle;
  2030. vg_lite_float_t ux = (X >= 0.0f ? X : -X);
  2031. vg_lite_float_t uy = (Y >= 0.0f ? Y : -Y);
  2032. if (ux > uy)
  2033. {
  2034. angle = ((uy > 0.0f && ux < Length) ? _Asin(uy / Length) : 0.0f);
  2035. }
  2036. else
  2037. {
  2038. angle = ((ux > 0.0f && uy < Length) ? (FLOAT_PI_HALF - _Asin(ux / Length)) : FLOAT_PI_HALF);
  2039. }
  2040. if (X < 0.0f) angle = FLOAT_PI - angle;
  2041. if (Y < 0.0f) angle = -angle;
  2042. return angle;
  2043. }
  2044. /* The arc is always counter clockwise and less than half circle (small). */
  2045. static vg_lite_error_t
  2046. _convert_circle_arc(
  2047. vg_lite_stroke_t *stroke_conversion,
  2048. vg_lite_float_t Radius,
  2049. vg_lite_float_t CenterX,
  2050. vg_lite_float_t CenterY,
  2051. vg_lite_float_t StartX,
  2052. vg_lite_float_t StartY,
  2053. vg_lite_float_t EndX,
  2054. vg_lite_float_t EndY,
  2055. uint8_t Half_circle,
  2056. vg_lite_path_point_ptr *point_list
  2057. )
  2058. {
  2059. vg_lite_error_t error = VG_LITE_SUCCESS;
  2060. /*gceVGCMD segmentCommand;*/
  2061. vg_lite_float_t theta1, theta_span;
  2062. uint32_t segs;
  2063. vg_lite_float_t theta, theta_half, theta2;
  2064. vg_lite_float_t cos_theta_half;
  2065. vg_lite_float_t control_ratio;
  2066. vg_lite_float_t controlX, controlY, anchorX, anchorY;
  2067. /*gctFLOAT lastX, lastY;*/
  2068. vg_lite_path_point_ptr point, start_point, last_point;
  2069. if (!stroke_conversion || !point_list)
  2070. return VG_LITE_INVALID_ARGUMENT;
  2071. /* Converting. */
  2072. theta1 = _Angle(StartX - CenterX, StartY - CenterY, Radius);
  2073. if (Half_circle)
  2074. {
  2075. theta_span = FLOAT_PI;
  2076. segs = 4;
  2077. theta = FLOAT_PI_QUARTER;
  2078. theta_half = FLOAT_PI_EIGHTH;
  2079. cos_theta_half = FLOAT_COS_PI_EIGHTH;
  2080. }
  2081. else
  2082. {
  2083. theta_span = _Angle(EndX - CenterX, EndY - CenterY, Radius) - theta1;
  2084. if (theta_span == 0.0f)
  2085. {
  2086. /* Handle specail case for huge scaling. */
  2087. *point_list = NULL;
  2088. error = VG_LITE_SUCCESS;
  2089. return error;
  2090. }
  2091. if ((theta_span < 0))
  2092. {
  2093. theta_span += FLOAT_PI_TWO;
  2094. }
  2095. /* Calculate the number of quadratic Bezier curves. */
  2096. /* Assumption: most of angles are small angles. */
  2097. if (theta_span <= FLOAT_PI_QUARTER) segs = 1;
  2098. else if (theta_span <= FLOAT_PI_HALF) segs = 2;
  2099. else if (theta_span <= FLOAT_PI_THREE_QUARTER) segs = 3;
  2100. else segs = 4;
  2101. theta = theta_span / segs;
  2102. theta_half = theta / 2.0f;
  2103. cos_theta_half = _Cos(theta_half);
  2104. }
  2105. /* Determine the segment command. */
  2106. /*egmentCommand = gcvVGCMD_ARC_QUAD;*/
  2107. /* Generate quadratic Bezier curves. */
  2108. start_point = last_point = NULL;
  2109. control_ratio = Radius / cos_theta_half;
  2110. while (segs-- > 0)
  2111. {
  2112. theta1 += theta;
  2113. theta2 = theta1 - theta_half;
  2114. if (theta2 > FLOAT_PI) theta2 -= FLOAT_PI_TWO;
  2115. controlX = CenterX + _Cos(theta2) * control_ratio;
  2116. controlY = CenterY + _Sine(theta2) * control_ratio;
  2117. theta2 = theta1;
  2118. if (theta2 > FLOAT_PI) theta2 -= FLOAT_PI_TWO;
  2119. anchorX = CenterX + _Cos(theta2) * Radius;
  2120. anchorY = CenterY + _Sine(theta2) * Radius;
  2121. if (segs == 0)
  2122. {
  2123. /* Use end point directly to avoid accumulated errors. */
  2124. anchorX = EndX;
  2125. anchorY = EndY;
  2126. }
  2127. /* Add control point. */
  2128. point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*point));
  2129. if (!point)
  2130. return VG_LITE_OUT_OF_RESOURCES;
  2131. memset(point, 0, sizeof(*point));
  2132. point->x = controlX;
  2133. point->y = controlY;
  2134. point->curve_type = CURVE_QUAD_CONTROL;
  2135. if (last_point)
  2136. {
  2137. last_point->next = point;
  2138. last_point = point;
  2139. }
  2140. else
  2141. {
  2142. start_point = last_point = point;
  2143. }
  2144. /* Add anchor point. */
  2145. point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*point));
  2146. if (!point) {
  2147. error = VG_LITE_OUT_OF_RESOURCES;
  2148. goto ErrorHandler;
  2149. }
  2150. memset(point, 0, sizeof(*point));
  2151. point->x = anchorX;
  2152. point->y = anchorY;
  2153. point->curve_type = CURVE_QUAD_ANCHOR;
  2154. last_point->next = point;
  2155. last_point = point;
  2156. }
  2157. if (last_point)
  2158. {
  2159. last_point->next = NULL;
  2160. }
  2161. *point_list = start_point;
  2162. return error;
  2163. ErrorHandler:
  2164. /* Return status. */
  2165. if (start_point) {
  2166. vg_lite_os_free(start_point);
  2167. start_point = last_point = NULL;
  2168. }
  2169. return error;
  2170. }
  2171. static vg_lite_error_t
  2172. _start_new_stroke_sub_path(
  2173. vg_lite_stroke_t * stroke_conversion,
  2174. vg_lite_float_t X,
  2175. vg_lite_float_t Y,
  2176. vg_lite_float_t Dx,
  2177. vg_lite_float_t Dy,
  2178. uint8_t add_end_cap,
  2179. vg_lite_sub_path_ptr *stroke_subpath
  2180. )
  2181. {
  2182. vg_lite_error_t error = VG_LITE_SUCCESS;
  2183. vg_lite_sub_path_ptr stroke_sub_path;
  2184. vg_lite_path_point_ptr new_point;
  2185. if (!stroke_conversion || !stroke_subpath)
  2186. return VG_LITE_INVALID_ARGUMENT;
  2187. VG_LITE_ERROR_HANDLER(_add_stroke_sub_path(stroke_conversion, &stroke_sub_path));
  2188. new_point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*new_point));
  2189. if (!new_point)
  2190. return VG_LITE_OUT_OF_RESOURCES;
  2191. memset(new_point, 0, sizeof(*new_point));
  2192. new_point->x = X + Dx;
  2193. new_point->y = Y + Dy;
  2194. new_point->prev = NULL;
  2195. new_point->curve_type = CURVE_LINE;
  2196. stroke_conversion->stroke_points = stroke_conversion->right_point = new_point;
  2197. stroke_sub_path->point_list = stroke_conversion->right_point = new_point;
  2198. new_point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*new_point));
  2199. if (!new_point)
  2200. return VG_LITE_OUT_OF_RESOURCES;
  2201. memset(new_point, 0, sizeof(*new_point));
  2202. new_point->x = X - Dx;
  2203. new_point->y = Y - Dy;
  2204. new_point->curve_type = CURVE_LINE;
  2205. new_point->next = NULL;
  2206. stroke_conversion->stroke_end = stroke_conversion->left_point = new_point;
  2207. stroke_conversion->stroke_count = 2;
  2208. stroke_sub_path->end_point = stroke_conversion->left_point = new_point;
  2209. stroke_sub_path->point_count = 2;
  2210. if (add_end_cap)
  2211. {
  2212. /* Add end cap if the subPath is not closed. */
  2213. switch (stroke_conversion->cap_style)
  2214. {
  2215. case VG_LITE_CAP_BUTT:
  2216. /* No adjustment needed. */
  2217. break;
  2218. case VG_LITE_CAP_ROUND:
  2219. /* Add curve. */
  2220. /* Add the starting point again as arc. */
  2221. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
  2222. stroke_sub_path->point_list->x, stroke_sub_path->point_list->y));
  2223. stroke_conversion->right_point->curve_type = CURVE_ARC_SCCW_HALF;
  2224. stroke_conversion->right_point->tangentX = X;
  2225. stroke_conversion->right_point->tangentY = Y;
  2226. /* Change the starting point to end point. */
  2227. stroke_sub_path->point_list->x = stroke_sub_path->end_point->x;
  2228. stroke_sub_path->point_list->y = stroke_sub_path->end_point->y;
  2229. break;
  2230. case VG_LITE_CAP_SQUARE:
  2231. stroke_conversion->right_point->x += Dy;
  2232. stroke_conversion->right_point->y -= Dx;
  2233. stroke_conversion->left_point->x += Dy;
  2234. stroke_conversion->left_point->y -= Dx;
  2235. break;
  2236. }
  2237. }
  2238. *stroke_subpath = stroke_sub_path;
  2239. ErrorHandler:
  2240. return error;
  2241. }
  2242. static void
  2243. _adjust_joint_point(
  2244. vg_lite_path_point_ptr Point,
  2245. vg_lite_path_point_ptr join_point,
  2246. vg_lite_float_t X,
  2247. vg_lite_float_t Y,
  2248. vg_lite_float_t Ratio
  2249. )
  2250. {
  2251. vg_lite_float_t mx = (join_point->x + X) / 2.0f;
  2252. vg_lite_float_t my = (join_point->y + Y) / 2.0f;
  2253. vg_lite_float_t dx = mx - Point->x;
  2254. vg_lite_float_t dy = my - Point->y;
  2255. dx = dx * Ratio;
  2256. dy = dy * Ratio;
  2257. join_point->x = Point->x + dx;
  2258. join_point->y = Point->y + dy;
  2259. }
  2260. static uint8_t
  2261. _is_angle_span_acute(
  2262. vg_lite_float_t Ux,
  2263. vg_lite_float_t Uy,
  2264. vg_lite_float_t Vx,
  2265. vg_lite_float_t Vy
  2266. )
  2267. {
  2268. return ((Ux * Vx + Uy * Vy) > 0.0f ? 1 : 0);
  2269. }
  2270. static vg_lite_error_t
  2271. _draw_swing_pie_area(
  2272. vg_lite_stroke_t *stroke_conversion,
  2273. vg_lite_path_point_ptr center_point,
  2274. uint8_t end_at_prev_point
  2275. )
  2276. {
  2277. vg_lite_error_t error = VG_LITE_SUCCESS;
  2278. if (!stroke_conversion)
  2279. return VG_LITE_INVALID_ARGUMENT;
  2280. if (stroke_conversion->swing_ccw)
  2281. {
  2282. vg_lite_path_point_ptr start_point = stroke_conversion->swing_stroke;
  2283. vg_lite_path_point_ptr end_point = NULL, real_end_point = NULL;
  2284. vg_lite_path_point_ptr point, prev_point;
  2285. uint32_t count = 0;
  2286. {
  2287. if (end_at_prev_point)
  2288. {
  2289. /* Detach the end point from leftStrokePoint. */
  2290. /* The end point will be added back later. */
  2291. real_end_point = stroke_conversion->left_point;
  2292. stroke_conversion->left_point = real_end_point->next;
  2293. stroke_conversion->left_point->prev = NULL;
  2294. }
  2295. VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion,
  2296. center_point->x, center_point->y));
  2297. end_point = stroke_conversion->left_point;
  2298. /* Reverse the point list from startPoint to endPoint. */
  2299. for (point = start_point; point; point = prev_point)
  2300. {
  2301. prev_point = point->prev;
  2302. point->prev = point->next;
  2303. point->next = prev_point;
  2304. count++;
  2305. }
  2306. if (end_point)
  2307. {
  2308. end_point->next = start_point->prev;
  2309. }
  2310. start_point->prev->prev = end_point;
  2311. start_point->prev = NULL;
  2312. stroke_conversion->left_point = start_point;
  2313. VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion,
  2314. center_point->x, center_point->y));
  2315. VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion,
  2316. stroke_conversion->swing_start->x,
  2317. stroke_conversion->swing_start->y));
  2318. VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion,
  2319. end_point->prev->x, end_point->prev->y));
  2320. if (end_at_prev_point)
  2321. {
  2322. if (real_end_point)
  2323. {
  2324. real_end_point->next = stroke_conversion->left_point;
  2325. }
  2326. stroke_conversion->left_point->prev = real_end_point;
  2327. stroke_conversion->left_point = real_end_point;
  2328. }
  2329. }
  2330. }
  2331. else
  2332. {
  2333. vg_lite_path_point_ptr start_point = stroke_conversion->swing_stroke;
  2334. vg_lite_path_point_ptr end_point = NULL, real_end_point = NULL;
  2335. vg_lite_path_point_ptr point, next_point;
  2336. uint32_t count = 0;
  2337. {
  2338. if (end_at_prev_point)
  2339. {
  2340. /* Detach the end point from leftStrokePoint. */
  2341. /* The end point will be added back later. */
  2342. real_end_point = stroke_conversion->right_point;
  2343. stroke_conversion->right_point = real_end_point->prev;
  2344. stroke_conversion->right_point->next = NULL;
  2345. }
  2346. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
  2347. center_point->x, center_point->y));
  2348. end_point = stroke_conversion->right_point;
  2349. /* Reverse the point list from startPoint to endPoint. */
  2350. for (point = start_point; point; point = next_point)
  2351. {
  2352. next_point = point->next;
  2353. point->next = point->prev;
  2354. point->prev = next_point;
  2355. count++;
  2356. }
  2357. end_point->prev = start_point->next;
  2358. start_point->next->next = end_point;
  2359. start_point->next = NULL;
  2360. stroke_conversion->right_point = start_point;
  2361. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
  2362. center_point->x, center_point->y));
  2363. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
  2364. stroke_conversion->swing_start->x,
  2365. stroke_conversion->swing_start->y));
  2366. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
  2367. end_point->next->x, end_point->next->y));
  2368. if (end_at_prev_point)
  2369. {
  2370. real_end_point->prev = stroke_conversion->right_point;
  2371. stroke_conversion->right_point->next = real_end_point;
  2372. stroke_conversion->right_point = real_end_point;
  2373. }
  2374. }
  2375. }
  2376. stroke_conversion->swing_handling = SWING_NO;
  2377. ErrorHandler:
  2378. return error;
  2379. }
  2380. static vg_lite_error_t
  2381. _process_line_joint(
  2382. vg_lite_stroke_t * stroke_conversion,
  2383. vg_lite_path_point_ptr Point,
  2384. vg_lite_float_t Length,
  2385. vg_lite_float_t prev_length,
  2386. uint32_t Swing_handling,
  2387. vg_lite_float_t X1,
  2388. vg_lite_float_t Y1,
  2389. vg_lite_float_t X2,
  2390. vg_lite_float_t Y2
  2391. )
  2392. {
  2393. vg_lite_error_t error = VG_LITE_SUCCESS;
  2394. vg_lite_join_style_t join_style;
  2395. vg_lite_float_t half_width;
  2396. vg_lite_float_t ratio;
  2397. vg_lite_float_t min_length_square;
  2398. vg_lite_float_t cos_theta;
  2399. uint8_t counter_clockwise;
  2400. uint8_t fat_line;
  2401. uint32_t swing_handling = SWING_NO;
  2402. uint8_t handle_short_line = 0;
  2403. if (!stroke_conversion)
  2404. return VG_LITE_INVALID_ARGUMENT;
  2405. join_style = stroke_conversion->join_style;
  2406. half_width = stroke_conversion->half_width;
  2407. fat_line = stroke_conversion->fattened;
  2408. if (stroke_conversion->swing_length < half_width)
  2409. {
  2410. if (stroke_conversion->need_swing)
  2411. {
  2412. swing_handling = SWING_OUT;
  2413. }
  2414. else
  2415. {
  2416. handle_short_line = 1;
  2417. }
  2418. }
  2419. else if (stroke_conversion->stroke_length - stroke_conversion->swing_length < half_width)
  2420. {
  2421. if (stroke_conversion->need_swing)
  2422. {
  2423. swing_handling = SWING_IN;
  2424. }
  2425. else
  2426. {
  2427. handle_short_line = 1;
  2428. }
  2429. }
  2430. if (swing_handling != Swing_handling)
  2431. {
  2432. error = VG_LITE_INVALID_ARGUMENT;
  2433. goto ErrorHandler;
  2434. }
  2435. /* For flattened curves/arcs, the join style is always round. */
  2436. if ((Point->flatten_flag != vgcFLATTEN_NO) && fat_line)
  2437. {
  2438. join_style = VG_LITE_JOIN_ROUND;
  2439. }
  2440. /* First, determine the turn is clockwise or counter-clockwise. */
  2441. cos_theta = Point->prev->tangentX * Point->tangentX + Point->prev->tangentY * Point->tangentY;
  2442. if (cos_theta > FLOAT_ANGLE_EPSILON_COS)
  2443. {
  2444. /* Straight line or semi-straight line--no need to handle join. */
  2445. if (stroke_conversion->swing_handling !=SWING_NO)
  2446. {
  2447. /* Begin to swing to the opposite direction. */
  2448. /* Draw the swing area (pie area). */
  2449. VG_LITE_ERROR_HANDLER(_draw_swing_pie_area(stroke_conversion, Point->prev, 1));
  2450. }
  2451. /* Add the new stroke points. */
  2452. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, X1, Y1));
  2453. VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, X2, Y2));
  2454. if (stroke_conversion->swing_handling != SWING_NO)
  2455. {
  2456. stroke_conversion->swing_count++;
  2457. }
  2458. goto endCheck;
  2459. }
  2460. else if (cos_theta < -FLOAT_ANGLE_EPSILON_COS)
  2461. {
  2462. /* Almost 180 degree turn. */
  2463. counter_clockwise = 1;
  2464. ratio = FLOAT_MAX;
  2465. min_length_square = FLOAT_MAX;
  2466. }
  2467. else
  2468. {
  2469. vg_lite_float_t angleSign = Point->prev->tangentX * Point->tangentY - Point->prev->tangentY * Point->tangentX;
  2470. counter_clockwise = (angleSign >= 0.0f ? 1 : 0);
  2471. ratio = 2.0f / (1.0f + cos_theta);
  2472. min_length_square = half_width * half_width * (1.0f - cos_theta) / (1.0f + cos_theta) + 0.02f;
  2473. }
  2474. if (stroke_conversion->swing_handling != SWING_NO)
  2475. {
  2476. if (counter_clockwise != stroke_conversion->swing_ccw)
  2477. {
  2478. /* Swing to the opposite direction. */
  2479. /* Draw the swing area (pie area). */
  2480. VG_LITE_ERROR_HANDLER(_draw_swing_pie_area(stroke_conversion, Point->prev, 1));
  2481. }
  2482. }
  2483. if (counter_clockwise)
  2484. {
  2485. if (stroke_conversion->swing_handling != SWING_NO)
  2486. {
  2487. vg_lite_path_point_ptr prev_point = stroke_conversion->left_point->next; /* Skip the line segment movement. */
  2488. vg_lite_float_t deltaX = X2 - prev_point->x;
  2489. vg_lite_float_t deltaY = Y2 - prev_point->y;
  2490. if (_is_angle_span_acute(stroke_conversion->swing_deltax,
  2491. stroke_conversion->swing_deltay,
  2492. deltaX, deltaY))
  2493. {
  2494. /* Continue swinging. */
  2495. stroke_conversion->swing_deltax = deltaX;
  2496. stroke_conversion->swing_deltay = deltaY;
  2497. }
  2498. else
  2499. {
  2500. /* Swing to the max. */
  2501. /* Draw the swing area (pie area). */
  2502. VG_LITE_ERROR_HANDLER(_draw_swing_pie_area(stroke_conversion, Point->prev, 1));
  2503. }
  2504. }
  2505. /* Check if the miter length is too long for inner intersection. */
  2506. if (stroke_conversion->swing_handling == SWING_NO
  2507. && ! handle_short_line
  2508. && min_length_square <= Length * Length
  2509. && min_length_square <= prev_length * prev_length)
  2510. {
  2511. /* Adjust leftStrokePoint to the intersection point. */
  2512. _adjust_joint_point(Point, stroke_conversion->left_point, X2, Y2, ratio);
  2513. }
  2514. else if (stroke_conversion->swing_handling == SWING_NO && Point->flatten_flag == vgcFLATTEN_NO)
  2515. {
  2516. /* Add the point to avoid incorrect sharp angle. */
  2517. VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, Point->x, Point->y));
  2518. /* Add the point to form a loop to avoid out-of-bound problem. */
  2519. VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, X2, Y2));
  2520. }
  2521. else if (stroke_conversion->swing_handling == SWING_NO && (! fat_line || Swing_handling == SWING_NO))
  2522. {
  2523. /* Flattened line segments should not have sharp angle. */
  2524. /* Add the point to form a loop to avoid out-of-bound problem. */
  2525. VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, X2, Y2));
  2526. }
  2527. else
  2528. {
  2529. if (stroke_conversion->swing_handling == SWING_NO)
  2530. {
  2531. vg_lite_path_point_ptr prev_point = stroke_conversion->left_point;
  2532. /* Start swing handling. */
  2533. stroke_conversion->swing_handling = Swing_handling;
  2534. stroke_conversion->swing_ccw = 1;
  2535. stroke_conversion->swing_start = Point;
  2536. stroke_conversion->swing_centlen = 0.0f;
  2537. stroke_conversion->swing_count= 0;
  2538. /* Save stroking path delta. */
  2539. stroke_conversion->swing_deltax = X2 - prev_point->x;
  2540. stroke_conversion->swing_deltay = Y2 - prev_point->y;
  2541. /* Add extra center point for swing out pie area. */
  2542. /* VIV: [todo] Should adjust prev_point, instead of adding new point? */
  2543. VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, Point->x, Point->y));
  2544. /* Add extra start stroke point for swing out pie area. */
  2545. VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, prev_point->x, prev_point->y));
  2546. stroke_conversion->swing_stroke = stroke_conversion->left_point;
  2547. }
  2548. /* Add curve. */
  2549. /* Note that the curve will be reversed, so the direction is CW. */
  2550. /* Then, left side is in reversed order, so the direction is CCW. */
  2551. VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, X2, Y2));
  2552. stroke_conversion->left_point->curve_type = CURVE_ARC_SCCW;
  2553. stroke_conversion->left_point->tangentX = Point->x;
  2554. stroke_conversion->left_point->tangentY = Point->y;
  2555. stroke_conversion->swing_count++;
  2556. }
  2557. switch (join_style)
  2558. {
  2559. case VG_LITE_JOIN_ROUND:
  2560. if (cos_theta > FLOAT_MIN_ARC_ANGLE_COS)
  2561. {
  2562. /* Add a point. */
  2563. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, X1, Y1));
  2564. }
  2565. else
  2566. {
  2567. /* Add curve. */
  2568. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, X1, Y1));
  2569. stroke_conversion->right_point->curve_type = CURVE_ARC_SCCW;
  2570. stroke_conversion->right_point->tangentX = Point->x;
  2571. stroke_conversion->right_point->tangentY = Point->y;
  2572. }
  2573. break;
  2574. case VG_LITE_JOIN_MITER:
  2575. if (ratio <= stroke_conversion->miter_square)
  2576. {
  2577. /* Adjust lastRightStrokePoint to the outer intersection point. */
  2578. _adjust_joint_point(Point, stroke_conversion->right_point, X1, Y1, ratio);
  2579. break;
  2580. }
  2581. /* Else use Bevel join style. */
  2582. case VG_LITE_JOIN_BEVEL:
  2583. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, X1, Y1));
  2584. break;
  2585. }
  2586. }
  2587. else
  2588. {
  2589. if (stroke_conversion->swing_handling != SWING_NO)
  2590. {
  2591. vg_lite_path_point_ptr prev_point = stroke_conversion->right_point->prev; /* Skip the line segment movement. */
  2592. vg_lite_float_t deltaX = X1 - prev_point->x;
  2593. vg_lite_float_t deltaY = Y1 - prev_point->y;
  2594. if (_is_angle_span_acute(stroke_conversion->swing_deltax,
  2595. stroke_conversion->swing_deltay,
  2596. deltaX, deltaY))
  2597. {
  2598. /* Continue swinging. */
  2599. stroke_conversion->swing_deltax = deltaX;
  2600. stroke_conversion->swing_deltay = deltaY;
  2601. }
  2602. else
  2603. {
  2604. /* Swing to the max. */
  2605. /* Draw the swing area (pie area). */
  2606. VG_LITE_ERROR_HANDLER(_draw_swing_pie_area(stroke_conversion, Point->prev, 1));
  2607. }
  2608. }
  2609. /* Check if the miter length is too long for inner intersection. */
  2610. if (stroke_conversion->swing_handling == SWING_NO
  2611. && ! handle_short_line
  2612. && min_length_square <= Length * Length
  2613. && min_length_square <= prev_length * prev_length)
  2614. {
  2615. /* Adjust lastRightStrokePoint to the intersection point. */
  2616. _adjust_joint_point(Point, stroke_conversion->right_point, X1, Y1, ratio);
  2617. }
  2618. else if (stroke_conversion->swing_handling == SWING_NO && Point->flatten_flag == vgcFLATTEN_NO)
  2619. {
  2620. /* Add the point to avoid incorrect sharp angle. */
  2621. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, Point->x, Point->y));
  2622. /* Add the point to form a loop to avoid out-of-bound problem. */
  2623. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, X1, Y1));
  2624. }
  2625. else if (stroke_conversion->swing_handling == SWING_NO && (! fat_line || Swing_handling == SWING_NO))
  2626. {
  2627. /* Flattened line segments should not have sharp angle. */
  2628. /* Add the point to form a loop to avoid out-of-bound problem. */
  2629. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, X1, Y1));
  2630. }
  2631. else
  2632. {
  2633. if (stroke_conversion->swing_handling == SWING_NO)
  2634. {
  2635. vg_lite_path_point_ptr prev_point = stroke_conversion->right_point;
  2636. /* Start swing handling. */
  2637. stroke_conversion->swing_handling = Swing_handling;
  2638. stroke_conversion->swing_ccw = 0;
  2639. stroke_conversion->swing_start = Point;
  2640. stroke_conversion->swing_centlen = 0.0f;
  2641. stroke_conversion->swing_count= 0;
  2642. /* Save stroking path delta. */
  2643. stroke_conversion->swing_deltax = X1 - prev_point->x;
  2644. stroke_conversion->swing_deltay = Y1 - prev_point->y;
  2645. /* Add extra center point for swing out pie area. */
  2646. /* VIV: [todo] Should adjust prev_point, instead of adding new point? */
  2647. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, Point->x, Point->y));
  2648. /* Add extra start stroke point for swing out pie area. */
  2649. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, prev_point->x, prev_point->y));
  2650. stroke_conversion->swing_stroke = stroke_conversion->right_point;
  2651. }
  2652. if (cos_theta > FLOAT_MIN_ARC_ANGLE_COS)
  2653. {
  2654. /* Add a point. */
  2655. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, X1, Y1));
  2656. }
  2657. else
  2658. {
  2659. /* Add curve. */
  2660. /* Note that the curve will be reversed, so the direction is CCW. */
  2661. stroke_conversion->right_point->curve_type = CURVE_ARC_SCCW;
  2662. stroke_conversion->right_point->tangentX = Point->x;
  2663. stroke_conversion->right_point->tangentY = Point->y;
  2664. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion, X1, Y1));
  2665. }
  2666. stroke_conversion->swing_count++;
  2667. }
  2668. switch (join_style)
  2669. {
  2670. case VG_LITE_JOIN_ROUND:
  2671. if (cos_theta > FLOAT_MIN_ARC_ANGLE_COS)
  2672. {
  2673. /* Add a point. */
  2674. VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, X2, Y2));
  2675. }
  2676. else
  2677. {
  2678. /* Add curve. */
  2679. stroke_conversion->left_point->curve_type = CURVE_ARC_SCCW;
  2680. stroke_conversion->left_point->tangentX = Point->x;
  2681. stroke_conversion->left_point->tangentY = Point->y;
  2682. VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, X2, Y2));
  2683. }
  2684. break;
  2685. case VG_LITE_JOIN_MITER:
  2686. if (ratio <= stroke_conversion->miter_square)
  2687. {
  2688. /* Adjust leftStrokePoint to the outer intersection point. */
  2689. _adjust_joint_point(Point, stroke_conversion->left_point, X2, Y2, ratio);
  2690. break;
  2691. }
  2692. /* Else use Bevel join style. */
  2693. case VG_LITE_JOIN_BEVEL:
  2694. VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion, X2, Y2));
  2695. break;
  2696. }
  2697. }
  2698. endCheck:
  2699. if (stroke_conversion->need_swing)
  2700. {
  2701. stroke_conversion->swing_length += Point->length;
  2702. }
  2703. if (stroke_conversion->swing_handling != SWING_NO)
  2704. {
  2705. if (Point->flatten_flag == vgcFLATTEN_END ||
  2706. (stroke_conversion->swing_handling == SWING_OUT &&
  2707. stroke_conversion->swing_length > half_width))
  2708. {
  2709. /* Draw the swing area (pie area). */
  2710. VG_LITE_ERROR_HANDLER(_draw_swing_pie_area(stroke_conversion, Point, 0));
  2711. }
  2712. else
  2713. {
  2714. /* Check if center line will move too far. */
  2715. stroke_conversion->swing_centlen += Point->length;
  2716. if (stroke_conversion->swing_centlen > FLOAT_SWING_CENTER_RANGE)
  2717. {
  2718. /* Draw the swing area (pie area). */
  2719. VG_LITE_ERROR_HANDLER(_draw_swing_pie_area(stroke_conversion, Point, 0));
  2720. }
  2721. }
  2722. }
  2723. ErrorHandler:
  2724. return error;
  2725. }
  2726. static vg_lite_error_t
  2727. _close_stroke_sub_path(
  2728. vg_lite_stroke_t * stroke_conversion,
  2729. vg_lite_path_point_ptr Point,
  2730. vg_lite_float_t Length,
  2731. vg_lite_float_t prev_length,
  2732. uint8_t Swing_handling,
  2733. vg_lite_path_point_ptr first_stroke_point,
  2734. vg_lite_path_point_ptr last_stroke_point
  2735. )
  2736. {
  2737. vg_lite_error_t error = VG_LITE_SUCCESS;
  2738. if (!stroke_conversion)
  2739. return VG_LITE_INVALID_ARGUMENT;
  2740. /* Handle line joint style for the first/last point in closed path. */
  2741. VG_LITE_ERROR_HANDLER(_process_line_joint(
  2742. stroke_conversion, Point,
  2743. Length, prev_length, Swing_handling,
  2744. first_stroke_point->x, first_stroke_point->y,
  2745. last_stroke_point->x, last_stroke_point->y
  2746. ));
  2747. if (stroke_conversion->cap_style == VG_LITE_CAP_SQUARE
  2748. && stroke_conversion->join_style == VG_LITE_JOIN_MITER
  2749. && stroke_conversion->pattern_count > 0) {
  2750. stroke_conversion->left_point->x = last_stroke_point->x;
  2751. stroke_conversion->left_point->y = last_stroke_point->y;
  2752. }
  2753. /* Adjust the two end ponts of the first point. */
  2754. first_stroke_point->x = stroke_conversion->right_point->x;
  2755. first_stroke_point->y = stroke_conversion->right_point->y;
  2756. last_stroke_point->x = stroke_conversion->left_point->x;
  2757. last_stroke_point->y = stroke_conversion->left_point->y;
  2758. /* Concatnate right and left point lists. */
  2759. stroke_conversion->right_point->next = stroke_conversion->left_point;
  2760. stroke_conversion->left_point->prev = stroke_conversion->right_point;
  2761. /*gcmERROR_RETURN(_CheckStrokeSubPath(stroke_conversion->lastStrokeSubPath));*/
  2762. ErrorHandler:
  2763. return error;
  2764. }
  2765. static vg_lite_error_t _end_stroke_sub_path(
  2766. vg_lite_stroke_t *stroke_conversion,
  2767. vg_lite_float_t X,
  2768. vg_lite_float_t Y,
  2769. vg_lite_float_t Dx,
  2770. vg_lite_float_t Dy
  2771. )
  2772. {
  2773. vg_lite_error_t error = VG_LITE_SUCCESS;
  2774. if (!stroke_conversion)
  2775. return VG_LITE_INVALID_ARGUMENT;
  2776. /* Add points for end of line. */
  2777. VG_LITE_RETURN_ERROR(_add_point_to_right_stroke_point_list_tail(stroke_conversion, X + Dx, Y + Dy));
  2778. VG_LITE_RETURN_ERROR(_add_point_to_left_point_list_head(stroke_conversion, X - Dx, Y - Dy));
  2779. /* Add end cap if the subPath is not closed. */
  2780. switch (stroke_conversion->cap_style)
  2781. {
  2782. case VG_LITE_CAP_BUTT:
  2783. /* No adjustment needed. */
  2784. break;
  2785. case VG_LITE_CAP_ROUND:
  2786. /* Add curve. */
  2787. stroke_conversion->left_point->curve_type = CURVE_ARC_SCCW_HALF;
  2788. stroke_conversion->left_point->tangentX = X;
  2789. stroke_conversion->left_point->tangentY = Y;
  2790. break;
  2791. case VG_LITE_CAP_SQUARE:
  2792. stroke_conversion->right_point->x -= Dy;
  2793. stroke_conversion->right_point->y += Dx;
  2794. stroke_conversion->left_point->x -= Dy;
  2795. stroke_conversion->left_point->y += Dx;
  2796. break;
  2797. }
  2798. /* Concatnate right and left point lists. */
  2799. stroke_conversion->right_point->next = stroke_conversion->left_point;
  2800. stroke_conversion->left_point->prev = stroke_conversion->right_point;
  2801. /*gcmERROR_RETURN(_CheckStrokeSubPath(stroke_conversion->lastStrokeSubPath));*/
  2802. return error;
  2803. }
  2804. static vg_lite_error_t _get_next_dash_length(
  2805. vg_lite_stroke_t * stroke_conversion,
  2806. uint32_t * dash_index,
  2807. vg_lite_float_t * dash_length
  2808. )
  2809. {
  2810. if (!stroke_conversion || !dash_index || !dash_length)
  2811. return VG_LITE_INVALID_ARGUMENT;
  2812. (*dash_index)++;
  2813. if (*dash_index == stroke_conversion->pattern_count)
  2814. {
  2815. *dash_index = 0;
  2816. }
  2817. *dash_length = stroke_conversion->dash_pattern[*dash_index];
  2818. return VG_LITE_SUCCESS;
  2819. }
  2820. static vg_lite_error_t
  2821. _create_stroke_path(
  2822. vg_lite_stroke_t * stroke_conversion
  2823. )
  2824. {
  2825. vg_lite_error_t error = VG_LITE_SUCCESS;
  2826. vg_lite_sub_path_ptr stroke_sub_path = NULL,first_stroke_sub_path = NULL;
  2827. vg_lite_path_point_ptr point, next_point;
  2828. vg_lite_float_t half_width;
  2829. vg_lite_float_t x, y;
  2830. vg_lite_float_t dx, dy, ux, uy;
  2831. vg_lite_float_t length, prev_length, first_length;
  2832. vg_lite_float_t dash_length;
  2833. uint32_t dash_index;
  2834. uint8_t dashing;
  2835. uint8_t add_end_cap;
  2836. uint8_t need_to_handle_swing = 1 /* (stroke_conversion->strokeCapStyle == gcvCAP_BUTT) */;
  2837. vg_lite_uint8_t dash_phase_reset;
  2838. vg_lite_path_point_ptr first_right_point = NULL;
  2839. vg_lite_path_point_ptr last_left_point = NULL;
  2840. vg_lite_float_t first_dx = 0.0f, first_dy = 0.0f;
  2841. uint8_t drawing = 0;
  2842. vg_lite_float_t total_length = 0.0f;
  2843. vg_lite_float_t accu_length = 0.0f;
  2844. uint32_t swing_handling = SWING_NO;
  2845. if (!stroke_conversion)
  2846. return VG_LITE_INVALID_ARGUMENT;
  2847. half_width = stroke_conversion->half_width;
  2848. dashing = stroke_conversion->pattern_count > 0 ? 1 : 0;
  2849. dash_index = stroke_conversion->dash_index;
  2850. dash_length = stroke_conversion->dash_length;
  2851. dash_phase_reset = stroke_conversion->dash_reset;
  2852. /* VIV: [todo] Need to check/debug closed stroke path. */
  2853. need_to_handle_swing = (stroke_conversion->cap_style == VG_LITE_CAP_BUTT || stroke_conversion->closed);
  2854. if (need_to_handle_swing)
  2855. {
  2856. uint8_t reallyneed_to_handle_swing = 0;
  2857. /* Calculate the total length. */
  2858. for (point = stroke_conversion->path_points; point; point = point->next)
  2859. {
  2860. total_length += point->length;
  2861. if (point->flatten_flag != vgcFLATTEN_NO)
  2862. {
  2863. reallyneed_to_handle_swing = 1;
  2864. }
  2865. }
  2866. stroke_conversion->stroke_length = total_length;
  2867. if (reallyneed_to_handle_swing)
  2868. {
  2869. swing_handling = SWING_OUT;
  2870. }
  2871. else
  2872. {
  2873. need_to_handle_swing = 0;
  2874. swing_handling = SWING_NO;
  2875. }
  2876. }
  2877. stroke_conversion->need_swing = need_to_handle_swing;
  2878. point = stroke_conversion->path_points;
  2879. next_point = point->next;
  2880. if (next_point == NULL)
  2881. {
  2882. if (!dashing || ((dash_index & 0x1) == 0))
  2883. {
  2884. /* Single point (zero-length) subpath. */
  2885. /* Note that one-MOVE_TO subpaths are removed during parsing. */
  2886. VG_LITE_ERROR_HANDLER(_add_zero_length_stroke_sub_path(stroke_conversion, &stroke_sub_path));
  2887. }
  2888. goto ErrorHandler;
  2889. }
  2890. /* Adjust closed status for dashing. */
  2891. if (dashing && stroke_conversion->closed && ((dash_index & 0x1) == 1))
  2892. {
  2893. stroke_conversion->closed = VGL_FALSE;
  2894. }
  2895. /* Set add_end_cap. */
  2896. add_end_cap = dashing ? 1: (stroke_conversion->closed ? 0 : 1);
  2897. /* Process first line. */
  2898. first_length = point->length;
  2899. ux = point->tangentX;
  2900. uy = point->tangentY;
  2901. dx = uy * half_width;
  2902. dy = -ux * half_width;
  2903. if (need_to_handle_swing)
  2904. {
  2905. stroke_conversion->swing_length = first_length;
  2906. }
  2907. if (dashing)
  2908. {
  2909. vg_lite_float_t delta_length;
  2910. /* Draw dashes. */
  2911. x = point->x;
  2912. y = point->y;
  2913. do
  2914. {
  2915. if ((dash_index & 0x1) == 0)
  2916. {
  2917. VG_LITE_ERROR_HANDLER(_start_new_stroke_sub_path(
  2918. stroke_conversion,
  2919. x, y,
  2920. dx, dy, add_end_cap,
  2921. &stroke_sub_path
  2922. ));
  2923. drawing = 1;
  2924. add_end_cap = 1;
  2925. if (stroke_conversion->closed && (first_stroke_sub_path == NULL))
  2926. {
  2927. first_stroke_sub_path = stroke_conversion->last_stroke;
  2928. first_right_point = stroke_conversion->right_point;
  2929. last_left_point = stroke_conversion->left_point;
  2930. first_dx = dx;
  2931. first_dy = dy;
  2932. }
  2933. }
  2934. delta_length = first_length - dash_length;
  2935. if (delta_length >= FLOAT_EPSILON)
  2936. {
  2937. /* Move (x, y) forward along the line by dash_length. */
  2938. x += ux * dash_length;
  2939. y += uy * dash_length;
  2940. if ((dash_index & 0x1) == 0)
  2941. {
  2942. VG_LITE_ERROR_HANDLER(_end_stroke_sub_path(
  2943. stroke_conversion,
  2944. x, y,
  2945. dx, dy
  2946. ));
  2947. drawing = 0;
  2948. }
  2949. VG_LITE_ERROR_HANDLER(_get_next_dash_length(stroke_conversion, &dash_index, &dash_length));
  2950. first_length = delta_length;
  2951. }
  2952. else if (delta_length <= -FLOAT_EPSILON)
  2953. {
  2954. dash_length = -delta_length;
  2955. break;
  2956. }
  2957. else
  2958. {
  2959. if ((dash_index & 0x1) == 0)
  2960. {
  2961. VG_LITE_ERROR_HANDLER(_end_stroke_sub_path(
  2962. stroke_conversion,
  2963. next_point->x, next_point->y,
  2964. dx, dy
  2965. ));
  2966. drawing = 0;
  2967. }
  2968. VG_LITE_ERROR_HANDLER(_get_next_dash_length(stroke_conversion, &dash_index, &dash_length));
  2969. first_length = 0;
  2970. break;
  2971. }
  2972. }
  2973. while (1);
  2974. }
  2975. else
  2976. {
  2977. VG_LITE_ERROR_HANDLER(_start_new_stroke_sub_path(
  2978. stroke_conversion,
  2979. point->x, point->y,
  2980. dx, dy, add_end_cap,
  2981. &stroke_sub_path
  2982. ));
  2983. drawing = 1;
  2984. add_end_cap = 1;
  2985. }
  2986. /* Process the rest of lines. */
  2987. prev_length = first_length;
  2988. for (point = next_point, next_point = point->next; next_point;
  2989. point = next_point, next_point = point->next)
  2990. {
  2991. if (!dashing || ((dash_index & 0x1) == 0 && drawing))
  2992. {
  2993. /* Add points for end of line for line join process with next line. */
  2994. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
  2995. point->x + dx, point->y + dy));
  2996. VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion,
  2997. point->x - dx, point->y - dy));
  2998. }
  2999. length = point->length;
  3000. ux = point->tangentX;
  3001. uy = point->tangentY;
  3002. dx = uy * half_width;
  3003. dy = -ux * half_width;
  3004. if (need_to_handle_swing)
  3005. {
  3006. accu_length += point->prev->length;
  3007. stroke_conversion->swing_length = accu_length;
  3008. if (accu_length < half_width)
  3009. {
  3010. swing_handling = SWING_OUT;
  3011. }
  3012. else if (total_length - accu_length < half_width)
  3013. {
  3014. swing_handling = SWING_IN;
  3015. }
  3016. else
  3017. {
  3018. swing_handling = SWING_NO;
  3019. }
  3020. }
  3021. if (!dashing)
  3022. {
  3023. /* Handle line joint style. */
  3024. VG_LITE_ERROR_HANDLER(_process_line_joint(
  3025. stroke_conversion, point,
  3026. length, prev_length, swing_handling,
  3027. point->x + dx, point->y + dy,
  3028. point->x - dx, point->y - dy
  3029. ));
  3030. }
  3031. else
  3032. {
  3033. vg_lite_float_t delta_length;
  3034. /* Draw dashes. */
  3035. x = point->x;
  3036. y = point->y;
  3037. if ((dash_index & 0x1) == 0)
  3038. {
  3039. if (drawing)
  3040. {
  3041. /* Handle line joint style. */
  3042. VG_LITE_ERROR_HANDLER(_process_line_joint(
  3043. stroke_conversion, point,
  3044. dash_length, prev_length, swing_handling,
  3045. x + dx, y + dy,
  3046. x - dx, y - dy
  3047. ));
  3048. }
  3049. else
  3050. {
  3051. /* Start a new sub path. */
  3052. VG_LITE_ERROR_HANDLER(_start_new_stroke_sub_path(
  3053. stroke_conversion,
  3054. x, y,
  3055. dx, dy, add_end_cap,
  3056. &stroke_sub_path
  3057. ));
  3058. drawing = 1;
  3059. add_end_cap = 1;
  3060. }
  3061. }
  3062. do
  3063. {
  3064. delta_length = length - dash_length;
  3065. if (delta_length >= FLOAT_EPSILON)
  3066. {
  3067. /* Move (x, y) forward along the line by dash_length. */
  3068. x += ux * dash_length;
  3069. y += uy * dash_length;
  3070. if ((dash_index & 0x1) == 0)
  3071. {
  3072. VG_LITE_ERROR_HANDLER(_end_stroke_sub_path(
  3073. stroke_conversion,
  3074. x, y, dx, dy
  3075. ));
  3076. drawing = 0;
  3077. }
  3078. VG_LITE_ERROR_HANDLER(_get_next_dash_length(stroke_conversion, &dash_index, &dash_length));
  3079. length = delta_length;
  3080. }
  3081. else if (delta_length <= -FLOAT_EPSILON)
  3082. {
  3083. dash_length = -delta_length;
  3084. break;
  3085. }
  3086. else
  3087. {
  3088. if ((dash_index & 0x1) == 0)
  3089. {
  3090. VG_LITE_ERROR_HANDLER(_end_stroke_sub_path(
  3091. stroke_conversion,
  3092. next_point->x, next_point->y,
  3093. dx, dy
  3094. ));
  3095. drawing = 0;
  3096. }
  3097. VG_LITE_ERROR_HANDLER(_get_next_dash_length(stroke_conversion, &dash_index, &dash_length));
  3098. length = 0;
  3099. break;
  3100. }
  3101. if ((dash_index & 0x1) == 0)
  3102. {
  3103. VG_LITE_ERROR_HANDLER(_start_new_stroke_sub_path(
  3104. stroke_conversion,
  3105. x, y,
  3106. dx, dy, add_end_cap,
  3107. &stroke_sub_path
  3108. ));
  3109. drawing = 1;
  3110. add_end_cap = 1;
  3111. }
  3112. }
  3113. while (1);
  3114. }
  3115. prev_length = length;
  3116. }
  3117. if (need_to_handle_swing)
  3118. {
  3119. accu_length += point->prev->length;
  3120. stroke_conversion->swing_length = accu_length;
  3121. if (accu_length < half_width)
  3122. {
  3123. swing_handling = SWING_OUT;
  3124. }
  3125. else if (total_length - accu_length < half_width)
  3126. {
  3127. swing_handling = SWING_IN;
  3128. }
  3129. else
  3130. {
  3131. swing_handling = SWING_NO;
  3132. }
  3133. }
  3134. if (stroke_conversion->swing_handling != SWING_NO)
  3135. {
  3136. /* Draw the swing area (pie area). */
  3137. VG_LITE_ERROR_HANDLER(_draw_swing_pie_area(stroke_conversion, stroke_conversion->path_end, VGL_FALSE));
  3138. }
  3139. if (stroke_conversion->closed)
  3140. {
  3141. if (! dashing || drawing)
  3142. {
  3143. /* Add points for end of line. */
  3144. VG_LITE_ERROR_HANDLER(_add_point_to_right_stroke_point_list_tail(stroke_conversion,
  3145. point->x + dx, point->y + dy));
  3146. VG_LITE_ERROR_HANDLER(_add_point_to_left_point_list_head(stroke_conversion,
  3147. point->x - dx, point->y - dy));
  3148. if (! dashing)
  3149. {
  3150. if (stroke_sub_path)
  3151. {
  3152. /* Handle line joint style for the first/last point in closed path. */
  3153. VG_LITE_ERROR_HANDLER(_close_stroke_sub_path(
  3154. stroke_conversion, point,
  3155. first_length, prev_length, swing_handling,
  3156. stroke_sub_path->point_list, stroke_sub_path->end_point
  3157. ));
  3158. }
  3159. }
  3160. else
  3161. {
  3162. /* Handle line joint style for the first/last point in closed path. */
  3163. if (first_right_point && last_left_point) {
  3164. VG_LITE_ERROR_HANDLER(_close_stroke_sub_path(
  3165. stroke_conversion, point,
  3166. first_length, prev_length, swing_handling,
  3167. first_right_point, last_left_point
  3168. ));
  3169. }else {
  3170. error = VG_LITE_INVALID_ARGUMENT;
  3171. goto ErrorHandler;
  3172. }
  3173. }
  3174. }
  3175. else if (stroke_conversion->cap_style != VG_LITE_CAP_BUTT)
  3176. {
  3177. /* No closing join need. Add end cap for the starting point. */
  3178. if (stroke_conversion->cap_style == VG_LITE_CAP_SQUARE)
  3179. {
  3180. if (first_right_point && last_left_point) {
  3181. first_right_point->x += first_dy;
  3182. first_right_point->y -= first_dx;
  3183. last_left_point->x += first_dy;
  3184. last_left_point->y -= first_dx;
  3185. }else {
  3186. error = VG_LITE_INVALID_ARGUMENT;
  3187. goto ErrorHandler;
  3188. }
  3189. }
  3190. else
  3191. {
  3192. vg_lite_sub_path_ptr last_stroke = stroke_conversion->last_stroke;
  3193. vg_lite_path_point_ptr start_point = last_stroke->point_list;
  3194. vg_lite_path_point_ptr extra_point;
  3195. /* Add curve. */
  3196. /* Add extra point to the beginning with end point's coordinates. */
  3197. extra_point = (vg_lite_path_point_ptr)vg_lite_os_malloc(sizeof(*extra_point));
  3198. if (!extra_point)
  3199. return VG_LITE_OUT_OF_RESOURCES;
  3200. memset(extra_point, 0, sizeof(*extra_point));
  3201. extra_point->x = last_stroke->end_point->x;
  3202. extra_point->y = last_stroke->end_point->y;
  3203. extra_point->next = start_point;
  3204. start_point->prev = extra_point;
  3205. start_point->curve_type = CURVE_ARC_SCCW;
  3206. start_point->tangentX = stroke_conversion->path_points->x;
  3207. start_point->tangentY = stroke_conversion->path_points->y;
  3208. last_stroke->point_list = extra_point;
  3209. }
  3210. }
  3211. }
  3212. else if (! dashing ||
  3213. (((dash_index & 0x1) == 0) && (dash_length < stroke_conversion->dash_pattern[dash_index])))
  3214. {
  3215. /* Add end cap if the subPath is not closed. */
  3216. VG_LITE_ERROR_HANDLER(_end_stroke_sub_path(
  3217. stroke_conversion,
  3218. point->x, point->y,
  3219. dx, dy
  3220. ));
  3221. drawing = 0;
  3222. }
  3223. if (!dash_phase_reset) {
  3224. /* Update dash index and length for next subpath. */
  3225. if (dashing) {
  3226. if (((dash_index & 0x1) == 1) &&
  3227. (stroke_conversion->dash_pattern[dash_index] - dash_length < FLOAT_EPSILON)) {
  3228. stroke_conversion->dash_index = dash_index - 1;
  3229. stroke_conversion->dash_length = 0;
  3230. }
  3231. else {
  3232. stroke_conversion->dash_index = dash_index;
  3233. stroke_conversion->dash_length = dash_length;
  3234. }
  3235. }
  3236. }
  3237. ErrorHandler:
  3238. return error;
  3239. }
  3240. static vg_lite_error_t _copy_stroke_path(
  3241. vg_lite_stroke_t * stroke_conversion,
  3242. vg_lite_path_t *path
  3243. )
  3244. {
  3245. vg_lite_error_t error = VG_LITE_SUCCESS;
  3246. vg_lite_path_point_ptr point,prev_point,tmp_point;
  3247. vg_lite_float_t totalsize = 0,real_size = 0;
  3248. float *pfloat;
  3249. char *cpath;
  3250. #if (CHIPID==0x355 || CHIPID==0x255)
  3251. char last_opcode = 0;
  3252. #endif
  3253. void *temp_stroke_data = NULL;
  3254. uint32_t temp_stroke_size;
  3255. vg_lite_sub_path_ptr sub_path;
  3256. vg_lite_float_t half_width;
  3257. #if (CHIPID==0x355)
  3258. vg_lite_buffer_t buffer = { 0 };
  3259. uint32_t bytes;
  3260. #endif
  3261. if (!stroke_conversion || !path)
  3262. return VG_LITE_INVALID_ARGUMENT;
  3263. half_width = stroke_conversion->half_width;
  3264. sub_path = stroke_conversion->stroke_paths;
  3265. if (!stroke_conversion || !path || !sub_path)
  3266. return VG_LITE_SUCCESS;
  3267. while (sub_path)
  3268. {
  3269. tmp_point = prev_point = point = sub_path->point_list;
  3270. totalsize += _commandSize_float[VLC_OP_LINE] * sub_path->point_count + _commandSize_float[VLC_OP_CLOSE];
  3271. for(;tmp_point;tmp_point = tmp_point->next)
  3272. {
  3273. if (tmp_point->curve_type == CURVE_ARC_SCCW || tmp_point->curve_type == CURVE_ARC_SCCW_HALF) {
  3274. totalsize += 4 * _commandSize_float[VLC_OP_QUAD];
  3275. }
  3276. }
  3277. temp_stroke_data = path->stroke_path;
  3278. temp_stroke_size = path->stroke_size;
  3279. path->stroke_size += (int32_t)totalsize;
  3280. #if (CHIPID==0x355)
  3281. if (sub_path->next == NULL) {
  3282. bytes = (8 + path->stroke_size + 7 + 8) & ~7;
  3283. buffer.width = bytes;
  3284. buffer.height = 1;
  3285. buffer.stride = 0;
  3286. buffer.format = VG_LITE_A8;
  3287. VG_LITE_RETURN_ERROR(vg_lite_allocate(&buffer));
  3288. memset(buffer.memory, 0, buffer.stride);
  3289. ((uint32_t*)buffer.memory)[0] = VG_LITE_DATA((path->stroke_size + 7) / 8);
  3290. ((uint32_t*)buffer.memory)[1] = 0;
  3291. if (temp_stroke_data) {
  3292. memcpy((char *)buffer.memory + 8, temp_stroke_data, temp_stroke_size);
  3293. vg_lite_os_free(temp_stroke_data);
  3294. temp_stroke_data = NULL;
  3295. }
  3296. path->stroke_path = 0;
  3297. pfloat = (vg_lite_float_t*)((char*)buffer.memory + 8 + temp_stroke_size);
  3298. }
  3299. else
  3300. #endif
  3301. {
  3302. path->stroke_path = (void*)vg_lite_os_malloc(path->stroke_size);
  3303. if (!path->stroke_path) {
  3304. error = VG_LITE_OUT_OF_RESOURCES;
  3305. goto ErrorHandler;
  3306. }
  3307. memset(path->stroke_path, 0, path->stroke_size);
  3308. if (temp_stroke_data) {
  3309. memcpy(path->stroke_path, temp_stroke_data, temp_stroke_size);
  3310. vg_lite_os_free(temp_stroke_data);
  3311. temp_stroke_data = NULL;
  3312. }
  3313. pfloat = (vg_lite_float_t*)((char*)path->stroke_path + temp_stroke_size);
  3314. }
  3315. #if (CHIPID==0x355 || CHIPID==0x255)
  3316. if (last_opcode == VLC_OP_CLOSE) {
  3317. cpath = (char*)(pfloat - 1) + 1;
  3318. *cpath++ = VLC_OP_MOVE;
  3319. cpath = (char*)pfloat;
  3320. }
  3321. else
  3322. #endif
  3323. {
  3324. cpath = (char*)pfloat;
  3325. *cpath = VLC_OP_MOVE;
  3326. pfloat++;
  3327. }
  3328. *pfloat++ = point->x;
  3329. *pfloat++ = point->y;
  3330. real_size += _commandSize_float[VLC_OP_MOVE];
  3331. #if (CHIPID==0x355 || CHIPID==0x255)
  3332. if (last_opcode == VLC_OP_CLOSE)
  3333. real_size -= 4;
  3334. #endif
  3335. for (point = point->next; point; prev_point = point, point = point->next)
  3336. {
  3337. if (point->curve_type == CURVE_LINE)
  3338. {
  3339. if (point->x == prev_point->x && point->y == prev_point->y)
  3340. {
  3341. path->stroke_size -= _commandSize_float[VLC_OP_LINE];
  3342. /* Skip zero-length lines. */
  3343. continue;
  3344. }
  3345. /* Add new command. */
  3346. cpath = (char *)pfloat;
  3347. *cpath = VLC_OP_LINE;
  3348. pfloat++;
  3349. /* Set the coordinates. */
  3350. *pfloat++ = point->x;
  3351. *pfloat++ = point->y;
  3352. real_size += _commandSize_float[VLC_OP_LINE];
  3353. }
  3354. else if (point->curve_type == CURVE_QUAD_CONTROL)
  3355. {
  3356. /* Add new command. */
  3357. cpath = (char *)pfloat;
  3358. *cpath = VLC_OP_QUAD;
  3359. pfloat++;
  3360. /* Set the coordinates. */
  3361. prev_point = point, point = point->next;
  3362. *pfloat++ = prev_point->x;
  3363. *pfloat++ = prev_point->y;
  3364. *pfloat++ = point->x;
  3365. *pfloat++ = point->y;
  3366. real_size += _commandSize_float[VLC_OP_QUAD];
  3367. }
  3368. else
  3369. {
  3370. vg_lite_path_point_ptr point_list, p, nextP;
  3371. vg_lite_path_point_ptr p2;
  3372. if (point->curve_type == CURVE_ARC_SCCW)
  3373. {
  3374. /* Convert an arc to Bezier curves. */
  3375. VG_LITE_ERROR_HANDLER(_convert_circle_arc(stroke_conversion, half_width,
  3376. point->tangentX, point->tangentY,
  3377. prev_point->x, prev_point->y,
  3378. point->x, point->y,
  3379. 0, &point_list));
  3380. }
  3381. else
  3382. {
  3383. /* Convert a half circle to Bezier curves. */
  3384. VG_LITE_ERROR_HANDLER(_convert_circle_arc(stroke_conversion, half_width,
  3385. point->tangentX, point->tangentY,
  3386. prev_point->x, prev_point->y,
  3387. point->x, point->y,
  3388. 1, &point_list));
  3389. }
  3390. if (point_list)
  3391. {
  3392. for (p = point_list; p; p = nextP)
  3393. {
  3394. /* Add new command. */
  3395. cpath = (char *)pfloat;
  3396. *cpath = VLC_OP_QUAD;
  3397. pfloat++;
  3398. /* Set the coordinates. */
  3399. p2 = p->next;
  3400. nextP = p2->next;
  3401. *pfloat++ = p->x;
  3402. *pfloat++ = p->y;
  3403. *pfloat++ = p2->x;
  3404. *pfloat++ = p2->y;
  3405. real_size += _commandSize_float[VLC_OP_QUAD];
  3406. vg_lite_os_free(p);
  3407. vg_lite_os_free(p2);
  3408. }
  3409. }
  3410. else
  3411. {
  3412. /* Handle special case of huge scaling. */
  3413. /* Add new command. */
  3414. cpath = (char *)pfloat;
  3415. *cpath = VLC_OP_LINE;
  3416. pfloat++;
  3417. /* Set the coordinates. */
  3418. *pfloat++ = point->x;
  3419. *pfloat++ = point->y;
  3420. real_size += _commandSize_float[VLC_OP_LINE];
  3421. }
  3422. }
  3423. }
  3424. /* Create a CLOSE_PATH command at the end. */
  3425. cpath = (char *)pfloat;
  3426. if (sub_path->next)
  3427. *cpath = VLC_OP_CLOSE;
  3428. else
  3429. *cpath = VLC_OP_END;
  3430. real_size += _commandSize_float[VLC_OP_CLOSE];
  3431. path->stroke_size = temp_stroke_size + (int32_t)real_size;
  3432. totalsize = 0;
  3433. real_size = 0;
  3434. sub_path = sub_path->next;
  3435. #if (CHIPID==0x355 || CHIPID==0x255)
  3436. last_opcode = *cpath;
  3437. #endif
  3438. }
  3439. #if (CHIPID==0x355)
  3440. /* Initialize command buffer postfix. */
  3441. ((uint32_t*)buffer.memory)[(bytes >> 2) - 2] = VG_LITE_RETURN();
  3442. ((uint32_t*)buffer.memory)[(bytes >> 2) - 1] = 0;
  3443. /* Mark stroke as uploaded. */
  3444. path->stroke->uploaded.handle = buffer.handle;
  3445. path->stroke->uploaded.address = buffer.address;
  3446. path->stroke->uploaded.memory = buffer.memory;
  3447. path->stroke->uploaded.bytes = bytes;
  3448. VLM_PATH_STROKE_ENABLE_UPLOAD(*path);
  3449. #endif
  3450. ErrorHandler:
  3451. if (temp_stroke_data) {
  3452. vg_lite_os_free(temp_stroke_data);
  3453. temp_stroke_data = NULL;
  3454. }
  3455. return error;
  3456. }
  3457. static vg_lite_error_t _initialize_stroke_dash_parameters(
  3458. vg_lite_stroke_t * stroke_conversion
  3459. )
  3460. {
  3461. vg_lite_error_t error = VG_LITE_SUCCESS;
  3462. uint32_t count;
  3463. uint32_t i;
  3464. vg_lite_float_t *pattern_src;
  3465. vg_lite_float_t *pattern,*temp_pattern;
  3466. vg_lite_float_t length;
  3467. if (!stroke_conversion)
  3468. return VG_LITE_INVALID_ARGUMENT;
  3469. count = stroke_conversion->pattern_count;
  3470. if (count == 0 || !stroke_conversion->dash_pattern)
  3471. return error;
  3472. length = stroke_conversion->dash_phase;
  3473. /* The last pattern is ignored if the number is odd. */
  3474. if (count & 0x1) count--;
  3475. pattern = (vg_lite_float_t *)vg_lite_os_malloc(count * sizeof(vg_lite_float_t));
  3476. if (!pattern)
  3477. return VG_LITE_OUT_OF_RESOURCES;
  3478. temp_pattern = pattern;
  3479. stroke_conversion->pattern_length = 0.0f;
  3480. pattern_src = stroke_conversion->dash_pattern;
  3481. for (i = 0; i < count; i++, pattern++, pattern_src++)
  3482. {
  3483. if (*pattern_src < 0.0f)
  3484. {
  3485. *pattern = 0.0f;
  3486. }
  3487. else
  3488. {
  3489. *pattern = *pattern_src;
  3490. }
  3491. stroke_conversion->pattern_length += *pattern;
  3492. }
  3493. if (stroke_conversion->pattern_length < FLOAT_EPSILON)
  3494. {
  3495. stroke_conversion->pattern_count = 0;
  3496. vg_lite_os_free(temp_pattern);
  3497. temp_pattern = NULL;
  3498. return error;
  3499. }
  3500. while (length < 0.0f)
  3501. {
  3502. length += stroke_conversion->pattern_length;
  3503. }
  3504. while (length >= stroke_conversion->pattern_length)
  3505. {
  3506. length -= stroke_conversion->pattern_length;
  3507. }
  3508. pattern = stroke_conversion->dash_pattern;
  3509. for (i = 0; i < stroke_conversion->pattern_count; i++, pattern++)
  3510. {
  3511. if (length <= *pattern) break;
  3512. length -= *pattern;
  3513. }
  3514. stroke_conversion->dash_index = i;
  3515. stroke_conversion->dash_length = *pattern - length;
  3516. vg_lite_os_free(temp_pattern);
  3517. temp_pattern = NULL;
  3518. return error;
  3519. }
  3520. vg_lite_error_t vg_lite_update_stroke(
  3521. vg_lite_path_t *path
  3522. )
  3523. {
  3524. vg_lite_error_t error = VG_LITE_SUCCESS;
  3525. vg_lite_stroke_t * stroke_conversion;
  3526. vg_lite_path_list_ptr cur_list;
  3527. #if gcFEATURE_VG_TRACE_API
  3528. VGLITE_LOG("vg_lite_update_stroke %p\n", path);
  3529. #endif
  3530. if (!path)
  3531. return VG_LITE_INVALID_ARGUMENT;
  3532. if (!path->path_length)
  3533. return VG_LITE_SUCCESS;
  3534. if (!path->path)
  3535. return VG_LITE_INVALID_ARGUMENT;
  3536. if (!path->stroke)
  3537. return VG_LITE_INVALID_ARGUMENT;
  3538. stroke_conversion = path->stroke;
  3539. cur_list = stroke_conversion->cur_list;
  3540. #if (CHIPID==0x355)
  3541. if (path->stroke && path->stroke->uploaded.handle != NULL) {
  3542. vg_lite_kernel_free_t free_cmd;
  3543. free_cmd.memory_handle = path->stroke->uploaded.handle;
  3544. error = vg_lite_kernel(VG_LITE_FREE, &free_cmd);
  3545. if (error != VG_LITE_SUCCESS)
  3546. return error;
  3547. path->stroke->uploaded.address = 0;
  3548. path->stroke->uploaded.bytes = 0;
  3549. path->stroke->uploaded.handle = NULL;
  3550. path->stroke->uploaded.memory = NULL;
  3551. }
  3552. #endif
  3553. /* Free the existing stroke path. */
  3554. if (path->stroke_path)
  3555. {
  3556. vg_lite_os_free(path->stroke_path);
  3557. /* Reset the stroke. */
  3558. path->stroke_path = NULL;
  3559. }
  3560. if (stroke_conversion->line_width >= FLOAT_FAT_LINE_WIDTH
  3561. && stroke_conversion->line_width >= 1.0f)
  3562. {
  3563. stroke_conversion->fattened = 1;
  3564. }
  3565. stroke_conversion->add_end = path->add_end;
  3566. VG_LITE_RETURN_ERROR(_initialize_stroke_dash_parameters(stroke_conversion));
  3567. VG_LITE_RETURN_ERROR(_flatten_path(stroke_conversion, path));
  3568. for (cur_list = stroke_conversion->path_list_divide; cur_list; cur_list = cur_list->next)
  3569. {
  3570. stroke_conversion->path_end = cur_list->path_end;
  3571. stroke_conversion->path_points = cur_list->path_points;
  3572. stroke_conversion->point_count = cur_list->point_count;
  3573. stroke_conversion->closed = cur_list->closed;
  3574. VG_LITE_RETURN_ERROR(_create_stroke_path(stroke_conversion));
  3575. }
  3576. if (stroke_conversion->path_list_divide)
  3577. {
  3578. stroke_conversion->path_end = stroke_conversion->path_list_divide->path_end;
  3579. stroke_conversion->path_points = stroke_conversion->path_list_divide->path_points;
  3580. stroke_conversion->point_count = stroke_conversion->path_list_divide->point_count;
  3581. }
  3582. VG_LITE_RETURN_ERROR(_copy_stroke_path(stroke_conversion, path));
  3583. /* add VLC_OP_END if stroke_path is empty. */
  3584. if (path->stroke_size == 0) {
  3585. path->stroke_path = vg_lite_os_malloc(_commandSize_float[VLC_OP_END]);
  3586. if (!path->stroke_path)
  3587. return VG_LITE_OUT_OF_RESOURCES;
  3588. *(uint8_t*)path->stroke_path = VLC_OP_END;
  3589. path->stroke_size = _commandSize_float[VLC_OP_END];
  3590. }
  3591. return error;
  3592. }
  3593. vg_lite_error_t vg_lite_set_stroke(
  3594. vg_lite_path_t *path,
  3595. vg_lite_cap_style_t cap_style,
  3596. vg_lite_join_style_t join_style,
  3597. vg_lite_float_t line_width,
  3598. vg_lite_float_t miter_limit,
  3599. vg_lite_float_t *dash_pattern,
  3600. vg_lite_uint32_t pattern_count,
  3601. vg_lite_float_t dash_phase,
  3602. vg_lite_color_t stroke_color
  3603. )
  3604. {
  3605. #if gcFEATURE_VG_TRACE_API
  3606. 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);
  3607. #endif
  3608. if (!path || line_width <= 0)
  3609. return VG_LITE_INVALID_ARGUMENT;
  3610. if (miter_limit < 1.0f)
  3611. miter_limit = 1.0f;
  3612. if (!path->stroke) {
  3613. path->stroke = (vg_lite_stroke_t *)vg_lite_os_malloc(sizeof(vg_lite_stroke_t));
  3614. if (!path->stroke)
  3615. return VG_LITE_OUT_OF_RESOURCES;
  3616. memset(path->stroke, 0, sizeof(vg_lite_stroke_t));
  3617. }
  3618. else {
  3619. if (path->stroke) {
  3620. if (path->stroke->path_list_divide) {
  3621. vg_lite_path_list_ptr cur_list;
  3622. while (path->stroke->path_list_divide) {
  3623. cur_list = path->stroke->path_list_divide->next;
  3624. if (path->stroke->path_list_divide->path_points) {
  3625. vg_lite_path_point_ptr temp_point;
  3626. while (path->stroke->path_list_divide->path_points) {
  3627. temp_point = path->stroke->path_list_divide->path_points->next;
  3628. vg_lite_os_free(path->stroke->path_list_divide->path_points);
  3629. path->stroke->path_list_divide->path_points = temp_point;
  3630. }
  3631. temp_point = NULL;
  3632. }
  3633. vg_lite_os_free(path->stroke->path_list_divide);
  3634. path->stroke->path_list_divide = cur_list;
  3635. }
  3636. cur_list = NULL;
  3637. }
  3638. if (path->stroke->stroke_paths) {
  3639. vg_lite_sub_path_ptr temp_sub_path;
  3640. while (path->stroke->stroke_paths) {
  3641. temp_sub_path = path->stroke->stroke_paths->next;
  3642. if (path->stroke->stroke_paths->point_list) {
  3643. vg_lite_path_point_ptr temp_point;
  3644. while (path->stroke->stroke_paths->point_list) {
  3645. temp_point = path->stroke->stroke_paths->point_list->next;
  3646. vg_lite_os_free(path->stroke->stroke_paths->point_list);
  3647. path->stroke->stroke_paths->point_list = temp_point;
  3648. }
  3649. temp_point = NULL;
  3650. }
  3651. vg_lite_os_free(path->stroke->stroke_paths);
  3652. path->stroke->stroke_paths = temp_sub_path;
  3653. }
  3654. temp_sub_path = NULL;
  3655. }
  3656. if (path->stroke->dash_pattern)
  3657. vg_lite_os_free(path->stroke->dash_pattern);
  3658. path->stroke_valid = 0;
  3659. }
  3660. memset(path->stroke, 0, sizeof(vg_lite_stroke_t));
  3661. path->stroke_size = 0;
  3662. }
  3663. /* Clamp dash pattern and phase. */
  3664. pattern_count &= 0xFFFFFFFE;
  3665. float* dash_pattern_copy = NULL;
  3666. if (pattern_count > 0) {
  3667. dash_pattern_copy = vg_lite_os_malloc(pattern_count * sizeof(float));
  3668. if (!dash_pattern_copy)
  3669. return VG_LITE_OUT_OF_RESOURCES;
  3670. }
  3671. for (uint32_t i = 0; i < pattern_count; ++i)
  3672. dash_pattern_copy[i] = (dash_pattern[i] > 0.f) ? dash_pattern[i] : 0.f;
  3673. if (dash_phase < 0.f) {
  3674. float dash_total_length = 0.f;
  3675. for (uint32_t i = 0; i < pattern_count; ++i)
  3676. dash_total_length += dash_pattern_copy[i];
  3677. if (dash_total_length > 0.f)
  3678. dash_phase += (int)(-dash_phase / dash_total_length + 1) * dash_total_length;
  3679. else
  3680. dash_phase = 0.f;
  3681. }
  3682. path->stroke->cap_style = cap_style;
  3683. path->stroke->join_style = join_style;
  3684. path->stroke->line_width = line_width;
  3685. path->stroke->miter_limit = miter_limit;
  3686. path->stroke->half_width = line_width / 2.0f;
  3687. path->stroke->miter_square = path->stroke->miter_limit * path->stroke->miter_limit;
  3688. path->stroke->dash_pattern = dash_pattern_copy;
  3689. path->stroke->pattern_count = pattern_count;
  3690. path->stroke->dash_phase = dash_phase;
  3691. path->stroke_color = stroke_color;
  3692. return VG_LITE_SUCCESS;
  3693. }
  3694. #else /* gcFEATURE_VG_STROKE_PATH */
  3695. vg_lite_error_t vg_lite_update_stroke(
  3696. vg_lite_path_t *path
  3697. )
  3698. {
  3699. return VG_LITE_NOT_SUPPORT;
  3700. }
  3701. vg_lite_error_t vg_lite_set_stroke(
  3702. vg_lite_path_t* path,
  3703. vg_lite_cap_style_t cap_style,
  3704. vg_lite_join_style_t join_style,
  3705. vg_lite_float_t line_width,
  3706. vg_lite_float_t miter_limit,
  3707. vg_lite_float_t* dash_pattern,
  3708. vg_lite_uint32_t pattern_count,
  3709. vg_lite_float_t dash_phase,
  3710. vg_lite_color_t stroke_color
  3711. )
  3712. {
  3713. return VG_LITE_NOT_SUPPORT;
  3714. }
  3715. #endif /* gcFEATURE_VG_STROKE_PATH */
  3716. #if gcFEATURE_VG_ARC_PATH
  3717. static vg_lite_float_t _angle(
  3718. vg_lite_float_t Ux,
  3719. vg_lite_float_t Uy,
  3720. vg_lite_float_t Vx,
  3721. vg_lite_float_t Vy
  3722. )
  3723. {
  3724. vg_lite_float_t dot, length, angle, cosVal;
  3725. int32_t sign;
  3726. dot = Ux * Vx + Uy * Vy;
  3727. length = SQRTF(Ux * Ux + Uy * Uy) * SQRTF(Vx * Vx + Vy * Vy);
  3728. sign = (Ux * Vy - Uy * Vx < 0) ? -1 : 1;
  3729. cosVal = dot / length;
  3730. cosVal = CLAMP(cosVal, -1.0f, 1.0f);
  3731. angle = sign * ACOSF(cosVal);
  3732. return angle;
  3733. }
  3734. void compute_quadpathbounds(vg_lite_path_t* path, float currentX, float currentY, float controlX, float controlY, float lastX, float lastY)
  3735. {
  3736. int j = 0;
  3737. float newPointX = 0;
  3738. float newPointY = 0;
  3739. for (j = 1; j <= 256; j++) {
  3740. float t = (float)j / 256;
  3741. float u = 1.0f - t;
  3742. float term1 = u * u;
  3743. float term2 = t * u * 2.0f;
  3744. float term3 = t * t;
  3745. newPointX = currentX * term1 + controlX * term2 + lastX * term3;
  3746. newPointY = currentY * term1 + controlY * term2 + lastY * term3;
  3747. path->bounding_box[0] = MIN(path->bounding_box[0], newPointX);
  3748. path->bounding_box[1] = MIN(path->bounding_box[1], newPointY);
  3749. path->bounding_box[2] = MAX(path->bounding_box[2], newPointX);
  3750. path->bounding_box[3] = MAX(path->bounding_box[3], newPointY);
  3751. }
  3752. }
  3753. vg_lite_error_t _convert_hline(
  3754. vg_lite_float_t EndX,
  3755. vg_lite_float_t EndY,
  3756. uint8_t Relative,
  3757. vg_lite_control_coord_t* coords,
  3758. void** path_data,
  3759. uint32_t* offset,
  3760. uint32_t last_size
  3761. )
  3762. {
  3763. vg_lite_float_t endX, endY;
  3764. uint8_t segmentCommand;
  3765. int32_t segs;
  3766. uint32_t bufferSize;
  3767. char* pchar, * linePath;
  3768. vg_lite_float_t* pfloat;
  3769. /*******************************************************************
  3770. ** Converting.
  3771. */
  3772. if (path_data == NULL || *path_data == NULL || offset == NULL || coords == NULL)
  3773. return VG_LITE_INVALID_ARGUMENT;
  3774. segs = 1;
  3775. if (Relative)
  3776. {
  3777. endX = EndX + coords->lastX;
  3778. endY = EndY + coords->lastY;
  3779. }
  3780. else
  3781. {
  3782. endX = EndX;
  3783. endY = EndY;
  3784. }
  3785. /* Determine the segment command. */
  3786. segmentCommand = Relative
  3787. ? VLC_OP_LINE_REL
  3788. : VLC_OP_LINE;
  3789. /* Determine the size of the buffer required. */
  3790. bufferSize = (1 + 2) * SIZEOF(vg_lite_float_t) * segs;
  3791. linePath = (char*)vg_lite_os_malloc(*offset + bufferSize + last_size);
  3792. if (linePath == NULL)
  3793. return VG_LITE_OUT_OF_RESOURCES;
  3794. #if(CHIPID == 0x355)
  3795. memset(linePath, 0, *offset + bufferSize + last_size);
  3796. #endif
  3797. memcpy(linePath, (char*)*path_data, *offset);
  3798. vg_lite_os_free(*path_data);
  3799. *path_data = linePath;
  3800. pchar = linePath + *offset;
  3801. pfloat = (vg_lite_float_t*)pchar;
  3802. while (segs-- > 0)
  3803. {
  3804. /* Adjust relative coordinates. */
  3805. pchar = (char*)pfloat;
  3806. *pchar = segmentCommand;
  3807. pfloat++;
  3808. if (Relative) {
  3809. *pfloat++ = EndX;
  3810. *pfloat++ = 0;
  3811. }
  3812. else {
  3813. *pfloat++ = EndX;
  3814. *pfloat++ = EndY;
  3815. }
  3816. *offset += (1 + 2) * SIZEOF(vg_lite_float_t);
  3817. }
  3818. /* Update the control coordinates. */
  3819. coords->lastX = endX;
  3820. coords->lastY = endY;
  3821. coords->controlX = endX;
  3822. coords->controlY = endY;
  3823. return VG_LITE_SUCCESS;
  3824. }
  3825. vg_lite_error_t _convert_vline(
  3826. vg_lite_float_t EndX,
  3827. vg_lite_float_t EndY,
  3828. uint8_t Relative,
  3829. vg_lite_control_coord_t* coords,
  3830. void** path_data,
  3831. uint32_t* offset,
  3832. uint32_t last_size
  3833. )
  3834. {
  3835. vg_lite_float_t endX, endY;
  3836. uint8_t segmentCommand;
  3837. int32_t segs;
  3838. uint32_t bufferSize;
  3839. char* pchar, * linePath;
  3840. vg_lite_float_t* pfloat;
  3841. /*******************************************************************
  3842. ** Converting.
  3843. */
  3844. if (path_data == NULL || *path_data == NULL || offset == NULL || coords == NULL)
  3845. return VG_LITE_INVALID_ARGUMENT;
  3846. segs = 1;
  3847. if (Relative)
  3848. {
  3849. endX = EndX + coords->lastX;
  3850. endY = EndY + coords->lastY;
  3851. }
  3852. else
  3853. {
  3854. endX = EndX;
  3855. endY = EndY;
  3856. }
  3857. /* Determine the segment command. */
  3858. segmentCommand = Relative
  3859. ? VLC_OP_LINE_REL
  3860. : VLC_OP_LINE;
  3861. /* Determine the size of the buffer required. */
  3862. bufferSize = (1 + 2) * SIZEOF(vg_lite_float_t) * segs;
  3863. linePath = (char*)vg_lite_os_malloc(*offset + bufferSize + last_size);
  3864. if (linePath == NULL)
  3865. return VG_LITE_OUT_OF_RESOURCES;
  3866. #if(CHIPID == 0x355)
  3867. memset(linePath, 0, *offset + bufferSize + last_size);
  3868. #endif
  3869. memcpy(linePath, (char*)*path_data, *offset);
  3870. vg_lite_os_free(*path_data);
  3871. *path_data = linePath;
  3872. pchar = linePath + *offset;
  3873. pfloat = (vg_lite_float_t*)pchar;
  3874. while (segs-- > 0)
  3875. {
  3876. /* Adjust relative coordinates. */
  3877. pchar = (char*)pfloat;
  3878. *pchar = segmentCommand;
  3879. pfloat++;
  3880. if (Relative) {
  3881. *pfloat++ = 0;
  3882. *pfloat++ = EndY;
  3883. }
  3884. else {
  3885. *pfloat++ = EndX;
  3886. *pfloat++ = EndY;
  3887. }
  3888. *offset += (1 + 2) * SIZEOF(vg_lite_float_t);
  3889. }
  3890. /* Update the control coordinates. */
  3891. coords->lastX = endX;
  3892. coords->lastY = endY;
  3893. coords->controlX = endX;
  3894. coords->controlY = endY;
  3895. return VG_LITE_SUCCESS;
  3896. }
  3897. vg_lite_error_t _convert_scubic(
  3898. vg_lite_float_t EndX,
  3899. vg_lite_float_t EndY,
  3900. vg_lite_float_t ControlX,
  3901. vg_lite_float_t ControlY,
  3902. uint8_t Relative,
  3903. vg_lite_control_coord_t* coords,
  3904. void** path_data,
  3905. uint32_t* offset,
  3906. uint32_t last_size
  3907. )
  3908. {
  3909. vg_lite_float_t endX, endY;
  3910. uint8_t segmentCommand;
  3911. int32_t segs;
  3912. uint32_t bufferSize;
  3913. char* pchar, * cubicPath;
  3914. vg_lite_float_t* pfloat;
  3915. vg_lite_float_t controlX;
  3916. vg_lite_float_t controlY;
  3917. /*******************************************************************
  3918. ** Converting.
  3919. */
  3920. if (path_data == NULL || *path_data == NULL || offset == NULL || coords == NULL)
  3921. return VG_LITE_INVALID_ARGUMENT;
  3922. segs = 1;
  3923. if (Relative)
  3924. {
  3925. endX = EndX + coords->lastX;
  3926. endY = EndY + coords->lastY;
  3927. controlX = coords->lastX + ControlX;
  3928. controlY = coords->lastY + ControlY;
  3929. }
  3930. else
  3931. {
  3932. endX = EndX;
  3933. endY = EndY;
  3934. controlX = ControlX;
  3935. controlY = ControlY;
  3936. }
  3937. /* Determine the segment command. */
  3938. segmentCommand = Relative
  3939. ? VLC_OP_CUBIC_REL
  3940. : VLC_OP_CUBIC;
  3941. /* Determine the size of the buffer required. */
  3942. bufferSize = (1 + 6) * SIZEOF(vg_lite_float_t) * segs;
  3943. cubicPath = (char*)vg_lite_os_malloc(*offset + bufferSize + last_size);
  3944. if (cubicPath == NULL)
  3945. return VG_LITE_OUT_OF_RESOURCES;
  3946. #if(CHIPID == 0x355)
  3947. memset(cubicPath, 0, *offset + bufferSize + last_size);
  3948. #endif
  3949. memcpy(cubicPath, (char*)*path_data, *offset);
  3950. vg_lite_os_free(*path_data);
  3951. *path_data = cubicPath;
  3952. pchar = cubicPath + *offset;
  3953. pfloat = (vg_lite_float_t*)pchar;
  3954. while (segs-- > 0)
  3955. {
  3956. /* Adjust relative coordinates. */
  3957. pchar = (char*)pfloat;
  3958. *pchar = segmentCommand;
  3959. pfloat++;
  3960. if (Relative) {
  3961. /* Calculate the first control point and convert to relative coordinates. */
  3962. *pfloat++ = (2 * coords->lastX - coords->controlX) - coords->lastX;
  3963. *pfloat++ = (2 * coords->lastY - coords->controlY) - coords->lastY;
  3964. *pfloat++ = ControlX;
  3965. *pfloat++ = ControlY;
  3966. *pfloat++ = EndX;
  3967. *pfloat++ = EndY;
  3968. *offset += (1 + 6) * SIZEOF(vg_lite_float_t);
  3969. }
  3970. else {
  3971. *pfloat++ = 2 * coords->lastX - coords->controlX;
  3972. *pfloat++ = 2 * coords->lastY - coords->controlY;
  3973. *pfloat++ = ControlX;
  3974. *pfloat++ = ControlY;
  3975. *pfloat++ = EndX;
  3976. *pfloat++ = EndY;
  3977. *offset += (1 + 6) * SIZEOF(vg_lite_float_t);
  3978. }
  3979. }
  3980. /* Update the control coordinates. */
  3981. coords->lastX = endX;
  3982. coords->lastY = endY;
  3983. coords->controlX = controlX;
  3984. coords->controlY = controlY;
  3985. return VG_LITE_SUCCESS;
  3986. }
  3987. vg_lite_error_t _convert_squad(
  3988. vg_lite_float_t EndX,
  3989. vg_lite_float_t EndY,
  3990. uint8_t Relative,
  3991. vg_lite_control_coord_t* coords,
  3992. void** path_data,
  3993. uint32_t* offset,
  3994. uint32_t last_size
  3995. )
  3996. {
  3997. vg_lite_float_t endX, endY;
  3998. uint8_t segmentCommand;
  3999. int32_t segs;
  4000. uint32_t bufferSize;
  4001. char* pchar, * quadPath;
  4002. vg_lite_float_t* pfloat;
  4003. vg_lite_float_t ControlX1;
  4004. vg_lite_float_t ControlY1;
  4005. vg_lite_float_t controlX;
  4006. vg_lite_float_t controlY;
  4007. /*******************************************************************
  4008. ** Converting.
  4009. */
  4010. if (path_data == NULL || *path_data == NULL || offset == NULL || coords == NULL)
  4011. return VG_LITE_INVALID_ARGUMENT;
  4012. segs = 1;
  4013. if (Relative)
  4014. {
  4015. endX = EndX + coords->lastX;
  4016. endY = EndY + coords->lastY;
  4017. }
  4018. else
  4019. {
  4020. endX = EndX;
  4021. endY = EndY;
  4022. }
  4023. /* Determine the segment command. */
  4024. segmentCommand = Relative
  4025. ? VLC_OP_QUAD_REL
  4026. : VLC_OP_QUAD;
  4027. /* Determine the size of the buffer required. */
  4028. bufferSize = (1 + 4) * SIZEOF(vg_lite_float_t) * segs;
  4029. quadPath = (char*)vg_lite_os_malloc(*offset + bufferSize + last_size);
  4030. if (quadPath == NULL)
  4031. return VG_LITE_OUT_OF_RESOURCES;
  4032. #if(CHIPID == 0x355)
  4033. memset(quadPath, 0, *offset + bufferSize + last_size);
  4034. #endif
  4035. memcpy(quadPath, (char*)*path_data, *offset);
  4036. vg_lite_os_free(*path_data);
  4037. *path_data = quadPath;
  4038. pchar = quadPath + *offset;
  4039. pfloat = (vg_lite_float_t*)pchar;
  4040. while (segs-- > 0)
  4041. {
  4042. /* Adjust relative coordinates. */
  4043. pchar = (char*)pfloat;
  4044. *pchar = segmentCommand;
  4045. pfloat++;
  4046. if (Relative) {
  4047. ControlX1 = *pfloat++ = (2 * coords->lastX - coords->controlX) - coords->lastX;
  4048. ControlY1 = *pfloat++ = (2 * coords->lastY - coords->controlY) - coords->lastY;
  4049. controlX = ControlX1 + coords->lastX;
  4050. controlY = ControlY1 + coords->lastY;
  4051. *pfloat++ = EndX;
  4052. *pfloat++ = EndY;
  4053. *offset += (1 + 4) * SIZEOF(vg_lite_float_t);
  4054. }
  4055. else {
  4056. controlX = *pfloat++ = 2 * coords->lastX - coords->controlX;
  4057. controlY = *pfloat++ = 2 * coords->lastY - coords->controlY;
  4058. *pfloat++ = EndX;
  4059. *pfloat++ = EndY;
  4060. *offset += (1 + 4) * SIZEOF(vg_lite_float_t);
  4061. }
  4062. }
  4063. /* Update the control coordinates. */
  4064. coords->startX = coords->lastX;
  4065. coords->startY = coords->lastY;
  4066. coords->lastX = endX;
  4067. coords->lastY = endY;
  4068. coords->controlX = controlX;
  4069. coords->controlY = controlY;
  4070. return VG_LITE_SUCCESS;
  4071. }
  4072. /*!
  4073. @discussion
  4074. Convert arc to multi-segment bezier curve.
  4075. @param HorRadius
  4076. Major axis radius.
  4077. @param VerRadius
  4078. minor axis radius.
  4079. @param RotAngle
  4080. Rotation angle.
  4081. @param EndX
  4082. End coordinate x.
  4083. @param EndX
  4084. End coordinate y.
  4085. @param CounterClockwise
  4086. If this is 0,anticlockwise rotation,if this is 1,clockwise rotation.
  4087. @param Large
  4088. 1 means big arc,0 means little arc.
  4089. @param Relative
  4090. 1 means absolute coordinates,0 means relative coordinates.
  4091. @param coords
  4092. Including the start point coordinates of the path,the control point of the last segment of the path,
  4093. and the end point of the last segment of the path.
  4094. @param path_data
  4095. Path data usr for internal conversion.
  4096. @param offset
  4097. The offset of path_data.
  4098. @param last_size
  4099. The remain unconverted size of the original path data.
  4100. @result
  4101. Error code. VG_LITE_INVALID_ARGUMENTS to indicate the parameters are wrong.
  4102. */
  4103. vg_lite_error_t _convert_arc(
  4104. vg_lite_float_t HorRadius,
  4105. vg_lite_float_t VerRadius,
  4106. vg_lite_float_t RotAngle,
  4107. vg_lite_float_t EndX,
  4108. vg_lite_float_t EndY,
  4109. uint8_t CounterClockwise,
  4110. uint8_t Large,
  4111. uint8_t Relative,
  4112. vg_lite_control_coord_t* coords,
  4113. void ** path_data,
  4114. uint32_t *offset,
  4115. uint32_t last_size
  4116. )
  4117. {
  4118. vg_lite_float_t endX, endY;
  4119. uint8_t segmentCommand;
  4120. vg_lite_float_t phi, cosPhi, sinPhi;
  4121. vg_lite_float_t dxHalf, dyHalf;
  4122. vg_lite_float_t x1Prime, y1Prime;
  4123. vg_lite_float_t rx, ry;
  4124. vg_lite_float_t x1PrimeSquare, y1PrimeSquare;
  4125. vg_lite_float_t lambda;
  4126. vg_lite_float_t rxSquare, rySquare;
  4127. int32_t sign;
  4128. vg_lite_float_t sq, signedSq;
  4129. vg_lite_float_t cxPrime, cyPrime;
  4130. vg_lite_float_t theta1, thetaSpan;
  4131. int32_t segs;
  4132. vg_lite_float_t theta, ax, ay, x, y;
  4133. vg_lite_float_t controlX, controlY, anchorX, anchorY;
  4134. vg_lite_float_t lastX, lastY;
  4135. uint32_t bufferSize;
  4136. char *pchar, *arcPath;
  4137. vg_lite_float_t *pfloat;
  4138. /*******************************************************************
  4139. ** Converting.
  4140. */
  4141. if (path_data == NULL || *path_data == NULL || offset == NULL || coords == NULL)
  4142. return VG_LITE_INVALID_ARGUMENT;
  4143. if (Relative)
  4144. {
  4145. endX = EndX + coords->lastX;
  4146. endY = EndY + coords->lastY;
  4147. }
  4148. else
  4149. {
  4150. endX = EndX;
  4151. endY = EndY;
  4152. }
  4153. phi = RotAngle / 180.0f * PI;
  4154. cosPhi = COSF(phi);
  4155. sinPhi = SINF(phi);
  4156. if (Relative)
  4157. {
  4158. dxHalf = - EndX / 2.0f;
  4159. dyHalf = - EndY / 2.0f;
  4160. }
  4161. else
  4162. {
  4163. dxHalf = (coords->lastX - endX) / 2.0f;
  4164. dyHalf = (coords->lastY - endY) / 2.0f;
  4165. }
  4166. x1Prime = cosPhi * dxHalf + sinPhi * dyHalf;
  4167. y1Prime = -sinPhi * dxHalf + cosPhi * dyHalf;
  4168. rx = FABSF(HorRadius);
  4169. ry = FABSF(VerRadius);
  4170. x1PrimeSquare = x1Prime * x1Prime;
  4171. y1PrimeSquare = y1Prime * y1Prime;
  4172. lambda = x1PrimeSquare / (rx * rx) + y1PrimeSquare / (ry * ry);
  4173. if (lambda > 1.0f)
  4174. {
  4175. rx *= SQRTF(lambda);
  4176. ry *= SQRTF(lambda);
  4177. }
  4178. rxSquare = rx * rx;
  4179. rySquare = ry * ry;
  4180. sign = (Large == CounterClockwise) ? -1 : 1;
  4181. sq = ( rxSquare * rySquare
  4182. - rxSquare * y1PrimeSquare
  4183. - rySquare * x1PrimeSquare
  4184. )
  4185. /
  4186. ( rxSquare * y1PrimeSquare
  4187. + rySquare * x1PrimeSquare
  4188. );
  4189. signedSq = sign * ((sq < 0) ? 0 : SQRTF(sq));
  4190. cxPrime = signedSq * (rx * y1Prime / ry);
  4191. cyPrime = signedSq * -(ry * x1Prime / rx);
  4192. theta1 = _angle(1, 0, (x1Prime - cxPrime) / rx, (y1Prime - cyPrime) / ry);
  4193. theta1 = FMODF(theta1, 2 * PI);
  4194. thetaSpan = _angle(( x1Prime - cxPrime) / rx, ( y1Prime - cyPrime) / ry,
  4195. (-x1Prime - cxPrime) / rx, (-y1Prime - cyPrime) / ry);
  4196. if (!CounterClockwise && (thetaSpan > 0))
  4197. {
  4198. thetaSpan -= 2 * PI;
  4199. }
  4200. else if (CounterClockwise && (thetaSpan < 0))
  4201. {
  4202. thetaSpan += 2 * PI;
  4203. }
  4204. thetaSpan = FMODF(thetaSpan, 2 * PI);
  4205. /*******************************************************************
  4206. ** Drawing.
  4207. */
  4208. segs = (int32_t) (CEILF(FABSF(thetaSpan) / (45.0f / 180.0f * PI)));
  4209. theta = thetaSpan / segs;
  4210. ax = coords->lastX - COSF(theta1) * rx;
  4211. ay = coords->lastY - SINF(theta1) * ry;
  4212. if (FABSF(HorRadius) != 0 &&
  4213. FABSF(VerRadius) != 0 &&
  4214. (endX != coords->lastX || endY != coords->lastY)) {
  4215. /* Determine the segment command. */
  4216. segmentCommand = Relative
  4217. ? VLC_OP_QUAD_REL
  4218. : VLC_OP_QUAD;
  4219. /* Determine the size of the buffer required. */
  4220. bufferSize = (1 + 2 * 2) * SIZEOF(vg_lite_float_t) * segs;
  4221. arcPath = (char*)vg_lite_os_malloc(*offset + bufferSize + last_size);
  4222. if (arcPath == NULL)
  4223. return VG_LITE_OUT_OF_RESOURCES;
  4224. #if(CHIPID == 0x355)
  4225. memset(arcPath, 0, *offset + bufferSize + last_size);
  4226. #endif
  4227. memcpy(arcPath, (char*)*path_data, *offset);
  4228. vg_lite_os_free(*path_data);
  4229. *path_data = arcPath;
  4230. pchar = arcPath + *offset;
  4231. pfloat = (vg_lite_float_t*)pchar;
  4232. /* Set initial last point. */
  4233. lastX = coords->lastX;
  4234. lastY = coords->lastY;
  4235. while (segs-- > 0)
  4236. {
  4237. theta1 += theta;
  4238. controlX = ax + COSF(theta1 - (theta / 2.0f)) * rx / COSF(theta / 2.0f);
  4239. controlY = ay + SINF(theta1 - (theta / 2.0f)) * ry / COSF(theta / 2.0f);
  4240. anchorX = ax + COSF(theta1) * rx;
  4241. anchorY = ay + SINF(theta1) * ry;
  4242. if (RotAngle != 0)
  4243. {
  4244. x = coords->lastX + cosPhi * (controlX - coords->lastX) - sinPhi * (controlY - coords->lastY);
  4245. y = coords->lastY + sinPhi * (controlX - coords->lastX) + cosPhi * (controlY - coords->lastY);
  4246. controlX = x;
  4247. controlY = y;
  4248. x = coords->lastX + cosPhi * (anchorX - coords->lastX) - sinPhi * (anchorY - coords->lastY);
  4249. y = coords->lastY + sinPhi * (anchorX - coords->lastX) + cosPhi * (anchorY - coords->lastY);
  4250. anchorX = x;
  4251. anchorY = y;
  4252. }
  4253. if (segs == 0)
  4254. {
  4255. /* Use end point directly to avoid accumulated errors. */
  4256. anchorX = endX;
  4257. anchorY = endY;
  4258. }
  4259. /* Adjust relative coordinates. */
  4260. if (Relative)
  4261. {
  4262. vg_lite_float_t nextLastX = anchorX;
  4263. vg_lite_float_t nextLastY = anchorY;
  4264. controlX -= lastX;
  4265. controlY -= lastY;
  4266. anchorX -= lastX;
  4267. anchorY -= lastY;
  4268. lastX = nextLastX;
  4269. lastY = nextLastY;
  4270. }
  4271. pchar = (char*)pfloat;
  4272. *pchar = segmentCommand;
  4273. pfloat++;
  4274. *pfloat++ = controlX;
  4275. *pfloat++ = controlY;
  4276. *pfloat++ = anchorX;
  4277. *pfloat++ = anchorY;
  4278. *offset += (1 + 2 * 2) * SIZEOF(vg_lite_float_t);
  4279. }
  4280. }
  4281. else {
  4282. /* Determine the segment command. */
  4283. segmentCommand = Relative
  4284. ? VLC_OP_LINE_REL
  4285. : VLC_OP_LINE;
  4286. /* Determine the size of the buffer required. */
  4287. bufferSize = (1 + 2) * SIZEOF(vg_lite_float_t);
  4288. arcPath = (char*)vg_lite_os_malloc(*offset + bufferSize + last_size);
  4289. if (arcPath == NULL)
  4290. return VG_LITE_OUT_OF_RESOURCES;
  4291. memcpy(arcPath, (char*)*path_data, *offset);
  4292. vg_lite_os_free(*path_data);
  4293. *path_data = arcPath;
  4294. pchar = arcPath + *offset;
  4295. pfloat = (vg_lite_float_t*)pchar;
  4296. pchar = (char*)pfloat;
  4297. *pchar = segmentCommand;
  4298. pfloat++;
  4299. *pfloat++ = Relative ? EndX : endX;
  4300. *pfloat++ = Relative ? EndY : endY;
  4301. *offset += (1 + 2) * SIZEOF(vg_lite_float_t);
  4302. }
  4303. /* Update the control coordinates. */
  4304. coords->lastX = endX;
  4305. coords->lastY = endY;
  4306. coords->controlX = endX;
  4307. coords->controlY = endY;
  4308. return VG_LITE_SUCCESS;
  4309. }
  4310. vg_lite_error_t vg_lite_init_arc_path(vg_lite_path_t* path,
  4311. vg_lite_format_t data_format,
  4312. vg_lite_quality_t quality,
  4313. vg_lite_uint32_t path_length,
  4314. vg_lite_pointer path_data,
  4315. vg_lite_float_t min_x, vg_lite_float_t min_y,
  4316. vg_lite_float_t max_x, vg_lite_float_t max_y)
  4317. {
  4318. vg_lite_error_t error = VG_LITE_SUCCESS;
  4319. uint32_t i = 0, j, command = 0, offset = 0;
  4320. vg_lite_float_t moveToX, moveToY, lineToX, lineToY, controlX, controlY, quadToX, quadToY;
  4321. vg_lite_float_t controlX1, controlY1, controlX2, controlY2, cubicToX, cubicToY;
  4322. vg_lite_float_t horRadius, verRadius, rotAngle, endX, endY;
  4323. float* pfloat, * fpath;
  4324. char* cpath, * pathdata;
  4325. vg_lite_control_coord_t coords;
  4326. char add_end = path->add_end;
  4327. vg_lite_int32_t bytes;
  4328. vg_lite_pointer path_data_fp32 = path_data;
  4329. int8_t cmd, * path_data_s8_ptr;
  4330. int16_t* path_data_s16_ptr;
  4331. int32_t* path_data_s32_ptr;
  4332. float* path_data_fp32_ptr;
  4333. int32_t data_size, num = 0;
  4334. memset(&coords, 0, sizeof(vg_lite_control_coord_t));
  4335. coords.lastX = s_context.path_lastX;
  4336. coords.lastY = s_context.path_lastY;
  4337. #if gcFEATURE_VG_TRACE_API
  4338. 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);
  4339. #endif
  4340. if (path == NULL || path_data == NULL)
  4341. return VG_LITE_INVALID_ARGUMENT;
  4342. /* Path data cannot end with a CLOSE op. Replace CLOSE with END for path_data */
  4343. data_size = get_data_size(data_format);
  4344. num = path_length / data_size;
  4345. switch (data_format)
  4346. {
  4347. case VG_LITE_S8:
  4348. if (path_data && (*((char*)path_data + num - 1) == VLC_OP_CLOSE))
  4349. {
  4350. *(char*)((int*)path_data + num - 1) = VLC_OP_END;
  4351. }
  4352. break;
  4353. case VG_LITE_S16:
  4354. if (path_data && (*(char*)((short*)path_data + num - 1) == VLC_OP_CLOSE))
  4355. {
  4356. *(char*)((short*)path_data + num - 1) = VLC_OP_END;
  4357. }
  4358. break;
  4359. case VG_LITE_S32:
  4360. if (path_data && (*(char*)((int*)path_data + num - 1) == VLC_OP_CLOSE))
  4361. {
  4362. *(char*)((int*)path_data + num - 1) = VLC_OP_END;
  4363. }
  4364. break;
  4365. case VG_LITE_FP32:
  4366. if (path_data && (*(char*)((float*)path_data + num - 1) == VLC_OP_CLOSE))
  4367. {
  4368. *(char*)((float*)path_data + num - 1) = VLC_OP_END;
  4369. }
  4370. break;
  4371. default:
  4372. break;
  4373. }
  4374. /* Convert path format into float. */
  4375. switch (data_format)
  4376. {
  4377. case VG_LITE_S8:
  4378. /* src_s8, dst_fp32 */
  4379. bytes = path_length * 4;
  4380. path_data_fp32 = vg_lite_os_malloc(bytes);
  4381. if (path_data_fp32 == NULL)
  4382. return VG_LITE_OUT_OF_RESOURCES;
  4383. memset(path_data_fp32, 0, bytes);
  4384. path_data_fp32_ptr = path_data_fp32;
  4385. path_data_s8_ptr = (int8_t*)path_data;
  4386. i = 0;
  4387. while (i < path_length){
  4388. cmd = *(uint8_t*)path_data_s8_ptr;
  4389. *(uint8_t*)path_data_fp32_ptr = cmd;
  4390. path_data_s8_ptr++;
  4391. path_data_fp32_ptr++;
  4392. for (j = 0; j < _commandSize_float[cmd] / 4 - 1; j++) {
  4393. *path_data_fp32_ptr = (float)(*path_data_s8_ptr);
  4394. path_data_fp32_ptr++;
  4395. path_data_s8_ptr++;
  4396. }
  4397. i += _commandSize_float[cmd] / 4;
  4398. }
  4399. path_length *= 4;
  4400. break;
  4401. case VG_LITE_S16:
  4402. /* src_s16, dst_fp32 */
  4403. bytes = path_length * 2;
  4404. path_data_fp32 = vg_lite_os_malloc(bytes);
  4405. if (path_data_fp32 == NULL)
  4406. return VG_LITE_OUT_OF_RESOURCES;
  4407. memset(path_data_fp32, 0, bytes);
  4408. path_data_fp32_ptr = path_data_fp32;
  4409. path_data_s16_ptr = (int16_t*)path_data;
  4410. i = 0;
  4411. while (i < path_length) {
  4412. cmd = *(uint8_t*)path_data_s16_ptr;
  4413. *(uint8_t*)path_data_fp32_ptr = cmd;
  4414. path_data_s16_ptr++;
  4415. path_data_fp32_ptr++;
  4416. for (j = 0; j < _commandSize_float[cmd] / 4 - 1; j++) {
  4417. *path_data_fp32_ptr = (float)(*path_data_s16_ptr);
  4418. path_data_fp32_ptr++;
  4419. path_data_s16_ptr++;
  4420. }
  4421. i += _commandSize_float[cmd] / 2;
  4422. }
  4423. path_length *= 2;
  4424. break;
  4425. case VG_LITE_S32:
  4426. /* src_s32, dst_fp32 */
  4427. bytes = path_length;
  4428. path_data_fp32 = vg_lite_os_malloc(bytes);
  4429. if (path_data_fp32 == NULL)
  4430. return VG_LITE_OUT_OF_RESOURCES;
  4431. memset(path_data_fp32, 0, bytes);
  4432. path_data_fp32_ptr = path_data_fp32;
  4433. path_data_s32_ptr = (int32_t*)path_data;
  4434. i = 0;
  4435. while (i < path_length) {
  4436. cmd = *(uint8_t*)path_data_s32_ptr;
  4437. *(uint8_t*)path_data_fp32_ptr = cmd;
  4438. path_data_s32_ptr++;
  4439. path_data_fp32_ptr++;
  4440. for (j = 0; j < _commandSize_float[cmd] / 4 - 1; j++) {
  4441. *path_data_fp32_ptr = (float)(*path_data_s32_ptr);
  4442. path_data_fp32_ptr++;
  4443. path_data_s32_ptr++;
  4444. }
  4445. i += _commandSize_float[cmd];
  4446. }
  4447. break;
  4448. case VG_LITE_FP32: {
  4449. /* src_fp32, dst_fp32 */
  4450. bytes = path_length;
  4451. path_data_fp32 = vg_lite_os_malloc(bytes);
  4452. if (path_data_fp32 == NULL)
  4453. return VG_LITE_OUT_OF_RESOURCES;
  4454. #if(CHIPID == 0x355)
  4455. memset(path_data_fp32, 0, bytes);
  4456. #endif
  4457. memcpy(path_data_fp32, path_data, bytes);
  4458. break;
  4459. }
  4460. default:
  4461. break;
  4462. }
  4463. vg_lite_clear_path(path);
  4464. data_format = VG_LITE_FP32;
  4465. if (!path_length)
  4466. {
  4467. path->format = data_format;
  4468. path->quality = quality;
  4469. path->bounding_box[0] = min_x;
  4470. path->bounding_box[1] = min_y;
  4471. path->bounding_box[2] = max_x;
  4472. path->bounding_box[3] = max_y;
  4473. path->path_length = 0;
  4474. path->path = NULL;
  4475. path->pdata_internal = 1;
  4476. path->path_changed = 1;
  4477. path->uploaded.address = 0;
  4478. path->uploaded.bytes = 0;
  4479. path->uploaded.handle = NULL;
  4480. path->uploaded.memory = NULL;
  4481. return VG_LITE_SUCCESS;
  4482. }
  4483. path->add_end = add_end;
  4484. path->bounding_box[0] = min_x;
  4485. path->bounding_box[1] = min_y;
  4486. path->bounding_box[2] = max_x;
  4487. path->bounding_box[3] = max_y;
  4488. pathdata = (char*)vg_lite_os_malloc(path_length);
  4489. if (pathdata == NULL)
  4490. return VG_LITE_OUT_OF_RESOURCES;
  4491. #if(CHIPID == 0x355)
  4492. memset(pathdata, 0, path_length);
  4493. #endif
  4494. pfloat = (vg_lite_float_t*)path_data_fp32;
  4495. i = 0;
  4496. while (i < path_length)
  4497. {
  4498. cpath = (char*)pfloat;
  4499. command = (uint32_t)*cpath;
  4500. pfloat++;
  4501. switch (command)
  4502. {
  4503. case VLC_OP_END:
  4504. cpath = (char*)pathdata + offset;
  4505. fpath = (vg_lite_float_t*)cpath;
  4506. *cpath = VLC_OP_END;
  4507. offset += _commandSize_float[VLC_OP_END];
  4508. i += _commandSize_float[VLC_OP_END];
  4509. break;
  4510. case VLC_OP_CLOSE:
  4511. /* Update the control coordinates. */
  4512. coords.lastX = coords.startX;
  4513. coords.lastY = coords.startY;
  4514. coords.controlX = coords.startX;
  4515. coords.controlY = coords.startY;
  4516. cpath = (char*)pathdata + offset;
  4517. fpath = (vg_lite_float_t*)cpath;
  4518. *cpath = VLC_OP_CLOSE;
  4519. offset += _commandSize_float[VLC_OP_CLOSE];
  4520. i += _commandSize_float[VLC_OP_CLOSE];
  4521. break;
  4522. case VLC_OP_MOVE:
  4523. moveToX = *pfloat;
  4524. pfloat++;
  4525. moveToY = *pfloat;
  4526. pfloat++;
  4527. /* Update the control coordinates. */
  4528. coords.startX = moveToX;
  4529. coords.startY = moveToY;
  4530. coords.lastX = moveToX;
  4531. coords.lastY = moveToY;
  4532. coords.controlX = moveToX;
  4533. coords.controlY = moveToY;
  4534. cpath = (char*)pathdata + offset;
  4535. fpath = (vg_lite_float_t*)cpath;
  4536. *cpath = VLC_OP_MOVE;
  4537. fpath++;
  4538. *fpath = moveToX;
  4539. fpath++;
  4540. *fpath = moveToY;
  4541. fpath++;
  4542. offset += _commandSize_float[VLC_OP_MOVE];
  4543. i += _commandSize_float[VLC_OP_MOVE];
  4544. break;
  4545. case VLC_OP_MOVE_REL:
  4546. moveToX = *pfloat;
  4547. pfloat++;
  4548. moveToY = *pfloat;
  4549. pfloat++;
  4550. cpath = (char*)pathdata + offset;
  4551. fpath = (vg_lite_float_t*)cpath;
  4552. *cpath = VLC_OP_MOVE_REL;
  4553. fpath++;
  4554. *fpath = moveToX;
  4555. fpath++;
  4556. *fpath = moveToY;
  4557. fpath++;
  4558. offset += _commandSize_float[VLC_OP_MOVE_REL];
  4559. i += _commandSize_float[VLC_OP_MOVE_REL];
  4560. /* Determine the absolute coordinates. */
  4561. moveToX += coords.lastX;
  4562. moveToY += coords.lastY;
  4563. /* Update the control coordinates. */
  4564. coords.startX = moveToX;
  4565. coords.startY = moveToY;
  4566. coords.lastX = moveToX;
  4567. coords.lastY = moveToY;
  4568. coords.controlX = moveToX;
  4569. coords.controlY = moveToY;
  4570. break;
  4571. case VLC_OP_LINE:
  4572. lineToX = *pfloat;
  4573. pfloat++;
  4574. lineToY = *pfloat;
  4575. pfloat++;
  4576. /* Update the control coordinates. */
  4577. coords.lastX = lineToX;
  4578. coords.lastY = lineToY;
  4579. coords.controlX = lineToX;
  4580. coords.controlY = lineToY;
  4581. cpath = (char*)pathdata + offset;
  4582. fpath = (vg_lite_float_t*)cpath;
  4583. *cpath = VLC_OP_LINE;
  4584. fpath++;
  4585. *fpath = lineToX;
  4586. fpath++;
  4587. *fpath = lineToY;
  4588. fpath++;
  4589. offset += _commandSize_float[VLC_OP_LINE];
  4590. i += _commandSize_float[VLC_OP_LINE];
  4591. break;
  4592. case VLC_OP_LINE_REL:
  4593. lineToX = *pfloat;
  4594. pfloat++;
  4595. lineToY = *pfloat;
  4596. pfloat++;
  4597. cpath = (char*)pathdata + offset;
  4598. fpath = (vg_lite_float_t*)cpath;
  4599. *cpath = VLC_OP_LINE_REL;
  4600. fpath++;
  4601. *fpath = lineToX;
  4602. fpath++;
  4603. *fpath = lineToY;
  4604. fpath++;
  4605. offset += _commandSize_float[VLC_OP_LINE_REL];
  4606. i += _commandSize_float[VLC_OP_LINE_REL];
  4607. /* Determine the absolute coordinates. */
  4608. lineToX += coords.lastX;
  4609. lineToY += coords.lastY;
  4610. /* Update the control coordinates. */
  4611. coords.lastX = lineToX;
  4612. coords.lastY = lineToY;
  4613. coords.controlX = lineToX;
  4614. coords.controlY = lineToY;
  4615. break;
  4616. case VLC_OP_QUAD:
  4617. controlX = *pfloat;
  4618. pfloat++;
  4619. controlY = *pfloat;
  4620. pfloat++;
  4621. quadToX = *pfloat;
  4622. pfloat++;
  4623. quadToY = *pfloat;
  4624. pfloat++;
  4625. compute_quadpathbounds(path, coords.lastX, coords.lastY, controlX, controlY, quadToX, quadToY);
  4626. /* Update the control coordinates. */
  4627. coords.lastX = quadToX;
  4628. coords.lastY = quadToY;
  4629. coords.controlX = controlX;
  4630. coords.controlY = controlY;
  4631. cpath = (char*)pathdata + offset;
  4632. fpath = (vg_lite_float_t*)cpath;
  4633. *cpath = VLC_OP_QUAD;
  4634. fpath++;
  4635. *fpath = controlX;
  4636. fpath++;
  4637. *fpath = controlY;
  4638. fpath++;
  4639. *fpath = quadToX;
  4640. fpath++;
  4641. *fpath = quadToY;
  4642. fpath++;
  4643. offset += _commandSize_float[VLC_OP_QUAD];
  4644. i += _commandSize_float[VLC_OP_QUAD];
  4645. break;
  4646. case VLC_OP_SQUAD:
  4647. quadToX = *pfloat;
  4648. pfloat++;
  4649. quadToY = *pfloat;
  4650. pfloat++;
  4651. i += _commandSize_float[VLC_OP_SQUAD];
  4652. /* Update the control coordinates. */
  4653. VG_LITE_ERROR_HANDLER(_convert_squad(quadToX, quadToY, VGL_FALSE, &coords, (void*)&pathdata, &offset, path_length - i));
  4654. compute_quadpathbounds(path, coords.startX, coords.startY, coords.controlX, coords.controlY, quadToX, quadToY);
  4655. break;
  4656. case VLC_OP_SQUAD_REL:
  4657. quadToX = *pfloat;
  4658. pfloat++;
  4659. quadToY = *pfloat;
  4660. pfloat++;
  4661. i += _commandSize_float[VLC_OP_SQUAD_REL];
  4662. /* Update the control coordinates. */
  4663. VG_LITE_ERROR_HANDLER(_convert_squad(quadToX, quadToY, VGL_TRUE, &coords, (void*)&pathdata, &offset, path_length - i));
  4664. break;
  4665. case VLC_OP_QUAD_REL:
  4666. controlX = *pfloat;
  4667. pfloat++;
  4668. controlY = *pfloat;
  4669. pfloat++;
  4670. quadToX = *pfloat;
  4671. pfloat++;
  4672. quadToY = *pfloat;
  4673. pfloat++;
  4674. cpath = (char*)pathdata + offset;
  4675. fpath = (vg_lite_float_t*)cpath;
  4676. *cpath = VLC_OP_QUAD_REL;
  4677. fpath++;
  4678. *fpath = controlX;
  4679. fpath++;
  4680. *fpath = controlY;
  4681. fpath++;
  4682. *fpath = quadToX;
  4683. fpath++;
  4684. *fpath = quadToY;
  4685. fpath++;
  4686. offset += _commandSize_float[VLC_OP_QUAD_REL];
  4687. i += _commandSize_float[VLC_OP_QUAD_REL];
  4688. /* Determine the absolute coordinates. */
  4689. controlX += coords.lastX;
  4690. controlY += coords.lastY;
  4691. quadToX += coords.lastX;
  4692. quadToY += coords.lastY;
  4693. /* Update the control coordinates. */
  4694. coords.lastX = quadToX;
  4695. coords.lastY = quadToY;
  4696. coords.controlX = controlX;
  4697. coords.controlY = controlY;
  4698. break;
  4699. case VLC_OP_CUBIC:
  4700. controlX1 = *pfloat;
  4701. pfloat++;
  4702. controlY1 = *pfloat;
  4703. pfloat++;
  4704. controlX2 = *pfloat;
  4705. pfloat++;
  4706. controlY2 = *pfloat;
  4707. pfloat++;
  4708. cubicToX = *pfloat;
  4709. pfloat++;
  4710. cubicToY = *pfloat;
  4711. pfloat++;
  4712. /* Update the control coordinates. */
  4713. coords.lastX = cubicToX;
  4714. coords.lastY = cubicToY;
  4715. coords.controlX = controlX2;
  4716. coords.controlY = controlY2;
  4717. cpath = (char*)pathdata + offset;
  4718. fpath = (vg_lite_float_t*)cpath;
  4719. *cpath = VLC_OP_CUBIC;
  4720. fpath++;
  4721. *fpath = controlX1;
  4722. fpath++;
  4723. *fpath = controlY1;
  4724. fpath++;
  4725. *fpath = controlX2;
  4726. fpath++;
  4727. *fpath = controlY2;
  4728. fpath++;
  4729. *fpath = cubicToX;
  4730. fpath++;
  4731. *fpath = cubicToY;
  4732. fpath++;
  4733. offset += _commandSize_float[VLC_OP_CUBIC];
  4734. i += _commandSize_float[VLC_OP_CUBIC];
  4735. break;
  4736. case VLC_OP_CUBIC_REL:
  4737. controlX1 = *pfloat;
  4738. pfloat++;
  4739. controlY1 = *pfloat;
  4740. pfloat++;
  4741. controlX2 = *pfloat;
  4742. pfloat++;
  4743. controlY2 = *pfloat;
  4744. pfloat++;
  4745. cubicToX = *pfloat;
  4746. pfloat++;
  4747. cubicToY = *pfloat;
  4748. pfloat++;
  4749. cpath = (char*)pathdata + offset;
  4750. fpath = (vg_lite_float_t*)cpath;
  4751. *cpath = VLC_OP_CUBIC_REL;
  4752. fpath++;
  4753. *fpath = controlX1;
  4754. fpath++;
  4755. *fpath = controlY1;
  4756. fpath++;
  4757. *fpath = controlX2;
  4758. fpath++;
  4759. *fpath = controlY2;
  4760. fpath++;
  4761. *fpath = cubicToX;
  4762. fpath++;
  4763. *fpath = cubicToY;
  4764. fpath++;
  4765. offset += _commandSize_float[VLC_OP_CUBIC_REL];
  4766. i += _commandSize_float[VLC_OP_CUBIC_REL];
  4767. /* Determine the absolute coordinates. */
  4768. controlX2 += coords.lastX;
  4769. controlY2 += coords.lastY;
  4770. cubicToX += coords.lastX;
  4771. cubicToY += coords.lastY;
  4772. /* Update the control coordinates. */
  4773. coords.lastX = cubicToX;
  4774. coords.lastY = cubicToY;
  4775. coords.controlX = controlX2;
  4776. coords.controlY = controlY2;
  4777. break;
  4778. case VLC_OP_SCUBIC:
  4779. controlX1 = *pfloat;
  4780. pfloat++;
  4781. controlY1 = *pfloat;
  4782. pfloat++;
  4783. cubicToX = *pfloat;
  4784. pfloat++;
  4785. cubicToY = *pfloat;
  4786. pfloat++;
  4787. i += _commandSize_float[VLC_OP_SCUBIC];
  4788. /* Update the control coordinates. */
  4789. VG_LITE_ERROR_HANDLER(_convert_scubic(cubicToX, cubicToY, controlX1, controlY1, VGL_FALSE, &coords, (void*)&pathdata, &offset, path_length - i));
  4790. break;
  4791. case VLC_OP_SCUBIC_REL:
  4792. controlX1 = *pfloat;
  4793. pfloat++;
  4794. controlY1 = *pfloat;
  4795. pfloat++;
  4796. cubicToX = *pfloat;
  4797. pfloat++;
  4798. cubicToY = *pfloat;
  4799. pfloat++;
  4800. i += _commandSize_float[VLC_OP_SCUBIC_REL];
  4801. /* Update the control coordinates. */
  4802. VG_LITE_ERROR_HANDLER(_convert_scubic(cubicToX, cubicToY, controlX1, controlY1, VGL_TRUE, &coords, (void*)&pathdata, &offset, path_length - i));
  4803. break;
  4804. case VLC_OP_HLINE:
  4805. lineToX = *pfloat;
  4806. pfloat++;
  4807. lineToY = coords.lastY;
  4808. i += _commandSize_float[VLC_OP_HLINE];
  4809. /* Update the control coordinates. */
  4810. VG_LITE_ERROR_HANDLER(_convert_hline(lineToX, lineToY, VGL_FALSE, &coords, (void*)&pathdata, &offset, path_length - i));
  4811. break;
  4812. case VLC_OP_HLINE_REL:
  4813. lineToX = *pfloat;
  4814. pfloat++;
  4815. lineToY = coords.lastY;
  4816. i += _commandSize_float[VLC_OP_HLINE_REL];
  4817. /* Update the control coordinates. */
  4818. VG_LITE_ERROR_HANDLER(_convert_hline(lineToX, lineToY, VGL_TRUE, &coords, (void*)&pathdata, &offset, path_length - i));
  4819. break;
  4820. case VLC_OP_VLINE:
  4821. lineToX = coords.lastX;
  4822. lineToY = *pfloat;
  4823. pfloat++;
  4824. i += _commandSize_float[VLC_OP_VLINE];
  4825. /* Update the control coordinates. */
  4826. VG_LITE_ERROR_HANDLER(_convert_vline(lineToX, lineToY, VGL_FALSE, &coords, (void*)&pathdata, &offset, path_length - i));
  4827. break;
  4828. case VLC_OP_VLINE_REL:
  4829. lineToX = coords.lastX;
  4830. lineToY = *pfloat;
  4831. pfloat++;
  4832. i += _commandSize_float[VLC_OP_VLINE_REL];
  4833. /* Update the control coordinates. */
  4834. VG_LITE_ERROR_HANDLER(_convert_vline(lineToX, lineToY, VGL_TRUE, &coords, (void*)&pathdata, &offset, path_length - i));
  4835. break;
  4836. case VLC_OP_SCCWARC:
  4837. horRadius = *pfloat;
  4838. pfloat++;
  4839. verRadius = *pfloat;
  4840. pfloat++;
  4841. rotAngle = *pfloat;
  4842. pfloat++;
  4843. endX = *pfloat;
  4844. pfloat++;
  4845. endY = *pfloat;
  4846. pfloat++;
  4847. i += _commandSize_float[VLC_OP_SCCWARC];
  4848. VG_LITE_ERROR_HANDLER(_convert_arc(horRadius, verRadius, rotAngle, endX, endY, VGL_FALSE, VGL_FALSE, VGL_FALSE, &coords, (void*)&pathdata, &offset, path_length - i));
  4849. break;
  4850. case VLC_OP_SCCWARC_REL:
  4851. horRadius = *pfloat;
  4852. pfloat++;
  4853. verRadius = *pfloat;
  4854. pfloat++;
  4855. rotAngle = *pfloat;
  4856. pfloat++;
  4857. endX = *pfloat;
  4858. pfloat++;
  4859. endY = *pfloat;
  4860. pfloat++;
  4861. i += _commandSize_float[VLC_OP_SCCWARC_REL];
  4862. VG_LITE_ERROR_HANDLER(_convert_arc(horRadius, verRadius, rotAngle, endX, endY, VGL_FALSE, VGL_FALSE, VGL_TRUE, &coords, (void*)&pathdata, &offset, path_length - i));
  4863. break;
  4864. case VLC_OP_SCWARC:
  4865. horRadius = *pfloat;
  4866. pfloat++;
  4867. verRadius = *pfloat;
  4868. pfloat++;
  4869. rotAngle = *pfloat;
  4870. pfloat++;
  4871. endX = *pfloat;
  4872. pfloat++;
  4873. endY = *pfloat;
  4874. pfloat++;
  4875. i += _commandSize_float[VLC_OP_SCCWARC_REL];
  4876. VG_LITE_ERROR_HANDLER(_convert_arc(horRadius, verRadius, rotAngle, endX, endY, VGL_TRUE, VGL_FALSE, VGL_FALSE, &coords, (void*)&pathdata, &offset, path_length - i));
  4877. break;
  4878. case VLC_OP_SCWARC_REL:
  4879. horRadius = *pfloat;
  4880. pfloat++;
  4881. verRadius = *pfloat;
  4882. pfloat++;
  4883. rotAngle = *pfloat;
  4884. pfloat++;
  4885. endX = *pfloat;
  4886. pfloat++;
  4887. endY = *pfloat;
  4888. pfloat++;
  4889. i += _commandSize_float[VLC_OP_SCCWARC_REL];
  4890. VG_LITE_ERROR_HANDLER(_convert_arc(horRadius, verRadius, rotAngle, endX, endY, VGL_TRUE, VGL_FALSE, VGL_TRUE, &coords, (void*)&pathdata, &offset, path_length - i));
  4891. break;
  4892. case VLC_OP_LCCWARC:
  4893. horRadius = *pfloat;
  4894. pfloat++;
  4895. verRadius = *pfloat;
  4896. pfloat++;
  4897. rotAngle = *pfloat;
  4898. pfloat++;
  4899. endX = *pfloat;
  4900. pfloat++;
  4901. endY = *pfloat;
  4902. pfloat++;
  4903. i += _commandSize_float[VLC_OP_SCCWARC_REL];
  4904. VG_LITE_ERROR_HANDLER(_convert_arc(horRadius, verRadius, rotAngle, endX, endY, VGL_FALSE, VGL_TRUE, VGL_FALSE, &coords, (void*)&pathdata, &offset, path_length - i));
  4905. break;
  4906. case VLC_OP_LCCWARC_REL:
  4907. horRadius = *pfloat;
  4908. pfloat++;
  4909. verRadius = *pfloat;
  4910. pfloat++;
  4911. rotAngle = *pfloat;
  4912. pfloat++;
  4913. endX = *pfloat;
  4914. pfloat++;
  4915. endY = *pfloat;
  4916. pfloat++;
  4917. i += _commandSize_float[VLC_OP_SCCWARC_REL];
  4918. VG_LITE_ERROR_HANDLER(_convert_arc(horRadius, verRadius, rotAngle, endX, endY, VGL_FALSE, VGL_TRUE, VGL_TRUE, &coords, (void*)&pathdata, &offset, path_length - i));
  4919. break;
  4920. case VLC_OP_LCWARC:
  4921. horRadius = *pfloat;
  4922. pfloat++;
  4923. verRadius = *pfloat;
  4924. pfloat++;
  4925. rotAngle = *pfloat;
  4926. pfloat++;
  4927. endX = *pfloat;
  4928. pfloat++;
  4929. endY = *pfloat;
  4930. pfloat++;
  4931. i += _commandSize_float[VLC_OP_SCCWARC_REL];
  4932. VG_LITE_ERROR_HANDLER(_convert_arc(horRadius, verRadius, rotAngle, endX, endY, VGL_TRUE, VGL_TRUE, VGL_FALSE, &coords, (void*)&pathdata, &offset, path_length - i));
  4933. break;
  4934. case VLC_OP_LCWARC_REL:
  4935. horRadius = *pfloat;
  4936. pfloat++;
  4937. verRadius = *pfloat;
  4938. pfloat++;
  4939. rotAngle = *pfloat;
  4940. pfloat++;
  4941. endX = *pfloat;
  4942. pfloat++;
  4943. endY = *pfloat;
  4944. pfloat++;
  4945. i += _commandSize_float[VLC_OP_SCCWARC_REL];
  4946. VG_LITE_ERROR_HANDLER(_convert_arc(horRadius, verRadius, rotAngle, endX, endY, VGL_TRUE, VGL_TRUE, VGL_TRUE, &coords, (void*)&pathdata, &offset, path_length - i));
  4947. break;
  4948. default:
  4949. break;
  4950. }
  4951. }
  4952. if (path_data_fp32 != NULL)
  4953. vg_lite_os_free(path_data_fp32);
  4954. path->format = VG_LITE_FP32;
  4955. path->quality = quality;
  4956. path->path_length = offset;
  4957. path->path = pathdata;
  4958. path->pdata_internal = 1;
  4959. path->path_changed = 1;
  4960. path->uploaded.address = 0;
  4961. path->uploaded.bytes = 0;
  4962. path->uploaded.handle = NULL;
  4963. path->uploaded.memory = NULL;
  4964. s_context.path_lastX = coords.lastX;
  4965. s_context.path_lastY = coords.lastY;
  4966. return VG_LITE_SUCCESS;
  4967. ErrorHandler:
  4968. vg_lite_os_free(pathdata);
  4969. pathdata = NULL;
  4970. return error;
  4971. }
  4972. #else /* gcFEATURE_VG_ARC_PATH */
  4973. vg_lite_error_t vg_lite_init_arc_path(vg_lite_path_t* path,
  4974. vg_lite_format_t data_format,
  4975. vg_lite_quality_t quality,
  4976. vg_lite_uint32_t path_length,
  4977. vg_lite_pointer path_data,
  4978. vg_lite_float_t min_x, vg_lite_float_t min_y,
  4979. vg_lite_float_t max_x, vg_lite_float_t max_y)
  4980. {
  4981. return VG_LITE_NOT_SUPPORT;
  4982. }
  4983. #endif /* gcFEATURE_VG_ARC_PATH */