nsRuleNode.cpp 414 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /*
  6. * a node in the lexicographic tree of rules that match an element,
  7. * responsible for converting the rules' information into computed style
  8. */
  9. #include <algorithm>
  10. #include "mozilla/ArrayUtils.h"
  11. #include "mozilla/Assertions.h"
  12. #include "mozilla/DebugOnly.h"
  13. #include "mozilla/Function.h"
  14. #include "mozilla/dom/AnimationEffectReadOnlyBinding.h" // for PlaybackDirection
  15. #include "mozilla/Likely.h"
  16. #include "mozilla/LookAndFeel.h"
  17. #include "mozilla/OperatorNewExtensions.h"
  18. #include "mozilla/Unused.h"
  19. #include "mozilla/css/Declaration.h"
  20. #include "mozilla/TypeTraits.h"
  21. #include "nsAlgorithm.h" // for clamped()
  22. #include "nsRuleNode.h"
  23. #include "nscore.h"
  24. #include "nsIWidget.h"
  25. #include "nsIPresShell.h"
  26. #include "nsFontMetrics.h"
  27. #include "gfxFont.h"
  28. #include "nsCSSAnonBoxes.h"
  29. #include "nsCSSPseudoElements.h"
  30. #include "nsThemeConstants.h"
  31. #include "PLDHashTable.h"
  32. #include "nsStyleContext.h"
  33. #include "nsStyleSet.h"
  34. #include "nsStyleStruct.h"
  35. #include "nsSize.h"
  36. #include "nsRuleData.h"
  37. #include "nsIStyleRule.h"
  38. #include "nsBidiUtils.h"
  39. #include "nsStyleStructInlines.h"
  40. #include "nsCSSProps.h"
  41. #include "nsTArray.h"
  42. #include "nsContentUtils.h"
  43. #include "CSSCalc.h"
  44. #include "nsPrintfCString.h"
  45. #include "nsRenderingContext.h"
  46. #include "nsStyleUtil.h"
  47. #include "nsIDocument.h"
  48. #include "prtime.h"
  49. #include "CSSVariableResolver.h"
  50. #include "nsCSSParser.h"
  51. #include "CounterStyleManager.h"
  52. #include "nsCSSPropertyIDSet.h"
  53. #include "mozilla/RuleNodeCacheConditions.h"
  54. #include "nsDeviceContext.h"
  55. #include "nsQueryObject.h"
  56. #include "nsUnicodeProperties.h"
  57. #if defined(_MSC_VER) || defined(__MINGW32__)
  58. #include <malloc.h>
  59. #ifdef _MSC_VER
  60. #define alloca _alloca
  61. #endif
  62. #endif
  63. #ifdef XP_SOLARIS
  64. #include <alloca.h>
  65. #endif
  66. using std::max;
  67. using std::min;
  68. using namespace mozilla;
  69. using namespace mozilla::dom;
  70. namespace mozilla {
  71. enum UnsetAction
  72. {
  73. eUnsetInitial,
  74. eUnsetInherit
  75. };
  76. } // namespace mozilla
  77. void*
  78. nsConditionalResetStyleData::GetConditionalStyleData(nsStyleStructID aSID,
  79. nsStyleContext* aStyleContext) const
  80. {
  81. Entry* e = static_cast<Entry*>(mEntries[aSID]);
  82. MOZ_ASSERT(e, "if mConditionalBits bit is set, we must have at least one "
  83. "conditional style struct");
  84. do {
  85. if (e->mConditions.Matches(aStyleContext)) {
  86. void* data = e->mStyleStruct;
  87. // For reset structs with conditions, we cache the data on the
  88. // style context.
  89. // Tell the style context that it doesn't own the data
  90. aStyleContext->AddStyleBit(GetBitForSID(aSID));
  91. aStyleContext->SetStyle(aSID, data);
  92. return data;
  93. }
  94. e = e->mNext;
  95. } while (e);
  96. return nullptr;
  97. }
  98. // Creates and returns an imgRequestProxy based on the specified
  99. // value in aValue.
  100. static imgRequestProxy*
  101. GetImageRequest(nsPresContext* aPresContext, const nsCSSValue& aValue)
  102. {
  103. return aValue.GetImageValue(aPresContext->Document());
  104. }
  105. // Creates an imgRequestProxy based on the specified value in
  106. // aValue and calls aCallback with it. If the nsPresContext
  107. // is static (e.g. for printing), then a static request (i.e.
  108. // showing the first frame, without animation) will be created.
  109. // (The expectation is then that aCallback will set the resulting
  110. // imgRequestProxy in a style struct somewhere.)
  111. static void
  112. SetImageRequest(function<void(imgRequestProxy*)> aCallback,
  113. nsPresContext* aPresContext,
  114. const nsCSSValue& aValue)
  115. {
  116. RefPtr<imgRequestProxy> req =
  117. aValue.GetPossiblyStaticImageValue(aPresContext->Document(),
  118. aPresContext);
  119. aCallback(req);
  120. }
  121. static void
  122. SetStyleImageRequest(function<void(nsStyleImageRequest*)> aCallback,
  123. nsPresContext* aPresContext,
  124. const nsCSSValue& aValue,
  125. nsStyleImageRequest::Mode aModeFlags =
  126. nsStyleImageRequest::Mode::Track)
  127. {
  128. SetImageRequest([&](imgRequestProxy* aProxy) {
  129. RefPtr<nsStyleImageRequest> request;
  130. if (aProxy) {
  131. css::ImageValue* imageValue = aValue.GetImageStructValue();
  132. ImageTracker* imageTracker =
  133. (aModeFlags & nsStyleImageRequest::Mode::Track)
  134. ? aPresContext->Document()->ImageTracker()
  135. : nullptr;
  136. request =
  137. new nsStyleImageRequest(aModeFlags, aProxy, imageValue, imageTracker);
  138. }
  139. aCallback(request);
  140. }, aPresContext, aValue);
  141. }
  142. template<typename ReferenceBox>
  143. static void
  144. SetStyleShapeSourceToCSSValue(StyleShapeSource<ReferenceBox>* aShapeSource,
  145. const nsCSSValue* aValue,
  146. nsStyleContext* aStyleContext,
  147. nsPresContext* aPresContext,
  148. RuleNodeCacheConditions& aConditions);
  149. /* Helper function to convert a CSS <position> specified value into its
  150. * computed-style form. */
  151. static void
  152. ComputePositionValue(nsStyleContext* aStyleContext,
  153. const nsCSSValue& aValue,
  154. Position& aComputedValue,
  155. RuleNodeCacheConditions& aConditions);
  156. /*
  157. * For storage of an |nsRuleNode|'s children in a PLDHashTable.
  158. */
  159. struct ChildrenHashEntry : public PLDHashEntryHdr {
  160. // key is |mRuleNode->GetKey()|
  161. nsRuleNode *mRuleNode;
  162. };
  163. /* static */ PLDHashNumber
  164. nsRuleNode::ChildrenHashHashKey(const void *aKey)
  165. {
  166. const nsRuleNode::Key *key =
  167. static_cast<const nsRuleNode::Key*>(aKey);
  168. // Disagreement on importance and level for the same rule is extremely
  169. // rare, so hash just on the rule.
  170. return PLDHashTable::HashVoidPtrKeyStub(key->mRule);
  171. }
  172. /* static */ bool
  173. nsRuleNode::ChildrenHashMatchEntry(const PLDHashEntryHdr *aHdr,
  174. const void *aKey)
  175. {
  176. const ChildrenHashEntry *entry =
  177. static_cast<const ChildrenHashEntry*>(aHdr);
  178. const nsRuleNode::Key *key =
  179. static_cast<const nsRuleNode::Key*>(aKey);
  180. return entry->mRuleNode->GetKey() == *key;
  181. }
  182. /* static */ const PLDHashTableOps
  183. nsRuleNode::ChildrenHashOps = {
  184. // It's probably better to allocate the table itself using malloc and
  185. // free rather than the pres shell's arena because the table doesn't
  186. // grow very often and the pres shell's arena doesn't recycle very
  187. // large size allocations.
  188. ChildrenHashHashKey,
  189. ChildrenHashMatchEntry,
  190. PLDHashTable::MoveEntryStub,
  191. PLDHashTable::ClearEntryStub,
  192. nullptr
  193. };
  194. // EnsureBlockDisplay:
  195. // Never change display:none or display:contents *ever*, otherwise:
  196. // - if the display value (argument) is not a block-type
  197. // then we set it to a valid block display value
  198. // - For enforcing the floated/positioned element CSS2 rules
  199. // - We allow the behavior of "list-item" to be customized.
  200. // CSS21 says that position/float do not convert 'list-item' to 'block',
  201. // but it explicitly does not define whether 'list-item' should be
  202. // converted to block *on the root node*. To allow for flexibility
  203. // (so that we don't have to support a list-item root node), this method
  204. // lets the caller pick either behavior, using the 'aConvertListItem' arg.
  205. // Reference: http://www.w3.org/TR/CSS21/visuren.html#dis-pos-flo
  206. /* static */
  207. void
  208. nsRuleNode::EnsureBlockDisplay(StyleDisplay& display,
  209. bool aConvertListItem /* = false */)
  210. {
  211. // see if the display value is already a block
  212. switch (display) {
  213. case StyleDisplay::ListItem:
  214. if (aConvertListItem) {
  215. display = StyleDisplay::Block;
  216. break;
  217. } // else, fall through to share the 'break' for non-changing display vals
  218. MOZ_FALLTHROUGH;
  219. case StyleDisplay::None:
  220. case StyleDisplay::Contents:
  221. // never change display:none or display:contents *ever*
  222. case StyleDisplay::Table:
  223. case StyleDisplay::Block:
  224. case StyleDisplay::Flex:
  225. case StyleDisplay::WebkitBox:
  226. case StyleDisplay::Grid:
  227. case StyleDisplay::FlowRoot:
  228. // do not muck with these at all - already blocks
  229. // This is equivalent to nsStyleDisplay::IsBlockOutside. (XXX Maybe we
  230. // should just call that?)
  231. // This needs to match the check done in
  232. // nsCSSFrameConstructor::FindMathMLData for <math>.
  233. break;
  234. case StyleDisplay::InlineTable:
  235. // make inline tables into tables
  236. display = StyleDisplay::Table;
  237. break;
  238. case StyleDisplay::InlineFlex:
  239. // make inline flex containers into flex containers
  240. display = StyleDisplay::Flex;
  241. break;
  242. case StyleDisplay::WebkitInlineBox:
  243. // make -webkit-inline-box containers into -webkit-box containers
  244. display = StyleDisplay::WebkitBox;
  245. break;
  246. case StyleDisplay::InlineGrid:
  247. // make inline grid containers into grid containers
  248. display = StyleDisplay::Grid;
  249. break;
  250. default:
  251. // make it a block
  252. display = StyleDisplay::Block;
  253. }
  254. }
  255. // EnsureInlineDisplay:
  256. // - if the display value (argument) is not an inline type
  257. // then we set it to a valid inline display value
  258. /* static */
  259. void
  260. nsRuleNode::EnsureInlineDisplay(StyleDisplay& display)
  261. {
  262. // see if the display value is already inline
  263. switch (display) {
  264. case StyleDisplay::Block:
  265. case StyleDisplay::FlowRoot:
  266. display = StyleDisplay::InlineBlock;
  267. break;
  268. case StyleDisplay::Table:
  269. display = StyleDisplay::InlineTable;
  270. break;
  271. case StyleDisplay::Flex:
  272. display = StyleDisplay::InlineFlex;
  273. break;
  274. case StyleDisplay::WebkitBox:
  275. display = StyleDisplay::WebkitInlineBox;
  276. break;
  277. case StyleDisplay::Grid:
  278. display = StyleDisplay::InlineGrid;
  279. break;
  280. case StyleDisplay::Box:
  281. display = StyleDisplay::InlineBox;
  282. break;
  283. case StyleDisplay::Stack:
  284. display = StyleDisplay::InlineStack;
  285. break;
  286. default:
  287. break; // Do nothing
  288. }
  289. }
  290. static nscoord CalcLengthWith(const nsCSSValue& aValue,
  291. nscoord aFontSize,
  292. const nsStyleFont* aStyleFont,
  293. nsStyleContext* aStyleContext,
  294. nsPresContext* aPresContext,
  295. bool aUseProvidedRootEmSize,
  296. bool aUseUserFontSet,
  297. RuleNodeCacheConditions& aConditions);
  298. struct CalcLengthCalcOps : public css::BasicCoordCalcOps,
  299. public css::NumbersAlreadyNormalizedOps
  300. {
  301. // All of the parameters to CalcLengthWith except aValue.
  302. const nscoord mFontSize;
  303. const nsStyleFont* const mStyleFont;
  304. nsStyleContext* const mStyleContext;
  305. nsPresContext* const mPresContext;
  306. const bool mUseProvidedRootEmSize;
  307. const bool mUseUserFontSet;
  308. RuleNodeCacheConditions& mConditions;
  309. CalcLengthCalcOps(nscoord aFontSize, const nsStyleFont* aStyleFont,
  310. nsStyleContext* aStyleContext, nsPresContext* aPresContext,
  311. bool aUseProvidedRootEmSize, bool aUseUserFontSet,
  312. RuleNodeCacheConditions& aConditions)
  313. : mFontSize(aFontSize),
  314. mStyleFont(aStyleFont),
  315. mStyleContext(aStyleContext),
  316. mPresContext(aPresContext),
  317. mUseProvidedRootEmSize(aUseProvidedRootEmSize),
  318. mUseUserFontSet(aUseUserFontSet),
  319. mConditions(aConditions)
  320. {
  321. }
  322. result_type ComputeLeafValue(const nsCSSValue& aValue)
  323. {
  324. return CalcLengthWith(aValue, mFontSize, mStyleFont,
  325. mStyleContext, mPresContext, mUseProvidedRootEmSize,
  326. mUseUserFontSet, mConditions);
  327. }
  328. };
  329. static inline nscoord ScaleCoordRound(const nsCSSValue& aValue, float aFactor)
  330. {
  331. return NSToCoordRoundWithClamp(aValue.GetFloatValue() * aFactor);
  332. }
  333. static inline nscoord ScaleViewportCoordTrunc(const nsCSSValue& aValue,
  334. nscoord aViewportSize)
  335. {
  336. // For units (like percentages and viewport units) where authors might
  337. // repeatedly use a value and expect some multiple of the value to be
  338. // smaller than a container, we need to use floor rather than round.
  339. // We need to use division by 100.0 rather than multiplication by 0.1f
  340. // to avoid introducing error.
  341. return NSToCoordTruncClamped(aValue.GetFloatValue() *
  342. aViewportSize / 100.0f);
  343. }
  344. already_AddRefed<nsFontMetrics>
  345. GetMetricsFor(nsPresContext* aPresContext,
  346. nsStyleContext* aStyleContext,
  347. const nsStyleFont* aStyleFont,
  348. nscoord aFontSize, // overrides value from aStyleFont
  349. bool aUseUserFontSet)
  350. {
  351. nsFont font = aStyleFont->mFont;
  352. font.size = aFontSize;
  353. gfxFont::Orientation orientation = gfxFont::eHorizontal;
  354. if (aStyleContext) {
  355. WritingMode wm(aStyleContext);
  356. if (wm.IsVertical() && !wm.IsSideways()) {
  357. orientation = gfxFont::eVertical;
  358. }
  359. }
  360. nsFontMetrics::Params params;
  361. params.language = aStyleFont->mLanguage;
  362. params.explicitLanguage = aStyleFont->mExplicitLanguage;
  363. params.orientation = orientation;
  364. params.userFontSet =
  365. aUseUserFontSet ? aPresContext->GetUserFontSet() : nullptr;
  366. params.textPerf = aPresContext->GetTextPerfMetrics();
  367. return aPresContext->DeviceContext()->GetMetricsFor(font, params);
  368. }
  369. static nsSize CalcViewportUnitsScale(nsPresContext* aPresContext)
  370. {
  371. // The caller is making use of viewport units, so notify the pres context
  372. // that it will need to rebuild the rule tree if the size of the viewport
  373. // changes.
  374. aPresContext->SetUsesViewportUnits(true);
  375. // The default (when we have 'overflow: auto' on the root element, or
  376. // trivially for 'overflow: hidden' since we never have scrollbars in that
  377. // case) is to define the scale of the viewport units without considering
  378. // scrollbars.
  379. nsSize viewportSize(aPresContext->GetVisibleArea().Size());
  380. // Check for 'overflow: scroll' styles on the root scroll frame. If we find
  381. // any, the standard requires us to take scrollbars into account.
  382. nsIScrollableFrame* scrollFrame =
  383. aPresContext->PresShell()->GetRootScrollFrameAsScrollable();
  384. if (scrollFrame) {
  385. ScrollStyles styles(scrollFrame->GetScrollStyles());
  386. if (styles.mHorizontal == NS_STYLE_OVERFLOW_SCROLL ||
  387. styles.mVertical == NS_STYLE_OVERFLOW_SCROLL) {
  388. // Gather scrollbar size information.
  389. nsRenderingContext context(
  390. aPresContext->PresShell()->CreateReferenceRenderingContext());
  391. nsMargin sizes(scrollFrame->GetDesiredScrollbarSizes(aPresContext, &context));
  392. if (styles.mHorizontal == NS_STYLE_OVERFLOW_SCROLL) {
  393. // 'overflow-x: scroll' means we must consider the horizontal scrollbar,
  394. // which affects the scale of viewport height units.
  395. viewportSize.height -= sizes.TopBottom();
  396. }
  397. if (styles.mVertical == NS_STYLE_OVERFLOW_SCROLL) {
  398. // 'overflow-y: scroll' means we must consider the vertical scrollbar,
  399. // which affects the scale of viewport width units.
  400. viewportSize.width -= sizes.LeftRight();
  401. }
  402. }
  403. }
  404. return viewportSize;
  405. }
  406. // If |aStyleFont| is nullptr, aStyleContext->StyleFont() is used.
  407. //
  408. // In case that |aValue| is rem unit, if |aStyleContext| is null, callers must
  409. // specify a valid |aStyleFont| and |aUseProvidedRootEmSize| must be true so
  410. // that we can get the length from |aStyleFont|.
  411. static nscoord CalcLengthWith(const nsCSSValue& aValue,
  412. nscoord aFontSize,
  413. const nsStyleFont* aStyleFont,
  414. nsStyleContext* aStyleContext,
  415. nsPresContext* aPresContext,
  416. bool aUseProvidedRootEmSize,
  417. // aUseUserFontSet should always be true
  418. // except when called from
  419. // CalcLengthWithInitialFont.
  420. bool aUseUserFontSet,
  421. RuleNodeCacheConditions& aConditions)
  422. {
  423. NS_ASSERTION(aValue.IsLengthUnit() || aValue.IsCalcUnit(),
  424. "not a length or calc unit");
  425. NS_ASSERTION(aStyleFont || aStyleContext,
  426. "Must have style data");
  427. NS_ASSERTION(aStyleContext || aUseProvidedRootEmSize,
  428. "Must have style context or specify aUseProvidedRootEmSize");
  429. NS_ASSERTION(aPresContext, "Must have prescontext");
  430. if (aValue.IsFixedLengthUnit()) {
  431. return aValue.GetFixedLength(aPresContext);
  432. }
  433. if (aValue.IsPixelLengthUnit()) {
  434. return aValue.GetPixelLength();
  435. }
  436. if (aValue.IsCalcUnit()) {
  437. // For properties for which lengths are the *only* units accepted in
  438. // calc(), we can handle calc() here and just compute a final
  439. // result. We ensure that we don't get to this code for other
  440. // properties by not calling CalcLength in those cases: SetCoord
  441. // only calls CalcLength for a calc when it is appropriate to do so.
  442. CalcLengthCalcOps ops(aFontSize, aStyleFont,
  443. aStyleContext, aPresContext,
  444. aUseProvidedRootEmSize, aUseUserFontSet,
  445. aConditions);
  446. return css::ComputeCalc(aValue, ops);
  447. }
  448. switch (aValue.GetUnit()) {
  449. // nsPresContext::SetVisibleArea and
  450. // nsPresContext::MediaFeatureValuesChanged handle dynamic changes
  451. // of the basis for viewport units by rebuilding the rule tree and
  452. // style context tree. Not caching them in the rule tree wouldn't
  453. // be sufficient to handle these changes because we also need a way
  454. // to get rid of cached values in the style context tree without any
  455. // changes in specified style. We can either do this by not caching
  456. // in the rule tree and then throwing away the style context tree
  457. // for dynamic viewport size changes, or by allowing caching in the
  458. // rule tree and using the existing rebuild style data path that
  459. // throws away the style context and the rule tree.
  460. // Thus we do cache viewport units in the rule tree. This allows us
  461. // to benefit from the performance advantages of the rule tree
  462. // (e.g., faster dynamic changes on other things, like transforms)
  463. // and allows us not to need an additional code path, in exchange
  464. // for an increased cost to dynamic changes to the viewport size
  465. // when viewport units are in use.
  466. case eCSSUnit_ViewportWidth: {
  467. nscoord viewportWidth = CalcViewportUnitsScale(aPresContext).width;
  468. return ScaleViewportCoordTrunc(aValue, viewportWidth);
  469. }
  470. case eCSSUnit_ViewportHeight: {
  471. nscoord viewportHeight = CalcViewportUnitsScale(aPresContext).height;
  472. return ScaleViewportCoordTrunc(aValue, viewportHeight);
  473. }
  474. case eCSSUnit_ViewportMin: {
  475. nsSize vuScale(CalcViewportUnitsScale(aPresContext));
  476. nscoord viewportMin = min(vuScale.width, vuScale.height);
  477. return ScaleViewportCoordTrunc(aValue, viewportMin);
  478. }
  479. case eCSSUnit_ViewportMax: {
  480. nsSize vuScale(CalcViewportUnitsScale(aPresContext));
  481. nscoord viewportMax = max(vuScale.width, vuScale.height);
  482. return ScaleViewportCoordTrunc(aValue, viewportMax);
  483. }
  484. // While we could deal with 'rem' units correctly by simply not
  485. // caching any data that uses them in the rule tree, it's valuable
  486. // to store them in the rule tree (for faster dynamic changes of
  487. // other things). And since the font size of the root element
  488. // changes rarely, we instead handle dynamic changes to the root
  489. // element's font size by rebuilding all style data in
  490. // nsCSSFrameConstructor::RestyleElement.
  491. case eCSSUnit_RootEM: {
  492. aPresContext->SetUsesRootEMUnits(true);
  493. nscoord rootFontSize;
  494. // NOTE: Be very careful with |styleFont|, since we haven't added any
  495. // conditions to aConditions or set it to uncacheable yet, so we don't
  496. // want to introduce any dependencies on aStyleContext's data here.
  497. const nsStyleFont *styleFont =
  498. aStyleFont ? aStyleFont : aStyleContext->StyleFont();
  499. if (aUseProvidedRootEmSize) {
  500. // We should use the provided aFontSize as the reference length to
  501. // scale. This only happens when we are calculating font-size or
  502. // an equivalent (scriptminsize or CalcLengthWithInitialFont) on
  503. // the root element, in which case aFontSize is already the
  504. // value we want.
  505. if (aFontSize == -1) {
  506. // XXX Should this be styleFont->mSize instead to avoid taking
  507. // minfontsize prefs into account?
  508. aFontSize = styleFont->mFont.size;
  509. }
  510. rootFontSize = aFontSize;
  511. } else if (aStyleContext && !aStyleContext->GetParent()) {
  512. // This is the root element (XXX we don't really know this, but
  513. // nsRuleNode::SetFont makes the same assumption!), so we should
  514. // use StyleFont on this context to get the root element's
  515. // font size.
  516. rootFontSize = styleFont->mFont.size;
  517. } else {
  518. // This is not the root element or we are calculating something other
  519. // than font size, so rem is relative to the root element's font size.
  520. // Find the root style context by walking up the style context tree.
  521. nsStyleContext* rootStyle = aStyleContext;
  522. while (rootStyle->GetParent()) {
  523. rootStyle = rootStyle->GetParent();
  524. }
  525. const nsStyleFont *rootStyleFont = rootStyle->StyleFont();
  526. rootFontSize = rootStyleFont->mFont.size;
  527. }
  528. return ScaleCoordRound(aValue, float(rootFontSize));
  529. }
  530. default:
  531. // Fall through to the code for units that can't be stored in the
  532. // rule tree because they depend on font data.
  533. break;
  534. }
  535. // Common code for units that depend on the element's font data and
  536. // thus can't be stored in the rule tree:
  537. const nsStyleFont *styleFont =
  538. aStyleFont ? aStyleFont : aStyleContext->StyleFont();
  539. if (aFontSize == -1) {
  540. // XXX Should this be styleFont->mSize instead to avoid taking minfontsize
  541. // prefs into account?
  542. aFontSize = styleFont->mFont.size;
  543. }
  544. switch (aValue.GetUnit()) {
  545. case eCSSUnit_EM: {
  546. if (aValue.GetFloatValue() == 0.0f) {
  547. // Don't call SetFontSizeDependency for '0em'.
  548. return 0;
  549. }
  550. // CSS2.1 specifies that this unit scales to the computed font
  551. // size, not the em-width in the font metrics, despite the name.
  552. aConditions.SetFontSizeDependency(aFontSize);
  553. return ScaleCoordRound(aValue, float(aFontSize));
  554. }
  555. case eCSSUnit_XHeight: {
  556. aPresContext->SetUsesExChUnits(true);
  557. RefPtr<nsFontMetrics> fm =
  558. GetMetricsFor(aPresContext, aStyleContext, styleFont,
  559. aFontSize, aUseUserFontSet);
  560. aConditions.SetUncacheable();
  561. return ScaleCoordRound(aValue, float(fm->XHeight()));
  562. }
  563. case eCSSUnit_Char: {
  564. aPresContext->SetUsesExChUnits(true);
  565. RefPtr<nsFontMetrics> fm =
  566. GetMetricsFor(aPresContext, aStyleContext, styleFont,
  567. aFontSize, aUseUserFontSet);
  568. gfxFloat zeroWidth =
  569. fm->GetThebesFontGroup()->GetFirstValidFont()->
  570. GetMetrics(fm->Orientation()).zeroOrAveCharWidth;
  571. aConditions.SetUncacheable();
  572. return ScaleCoordRound(aValue, ceil(aPresContext->AppUnitsPerDevPixel() *
  573. zeroWidth));
  574. }
  575. default:
  576. NS_NOTREACHED("unexpected unit");
  577. break;
  578. }
  579. return 0;
  580. }
  581. /* static */ nscoord
  582. nsRuleNode::CalcLength(const nsCSSValue& aValue,
  583. nsStyleContext* aStyleContext,
  584. nsPresContext* aPresContext,
  585. RuleNodeCacheConditions& aConditions)
  586. {
  587. NS_ASSERTION(aStyleContext, "Must have style data");
  588. return CalcLengthWith(aValue, -1, nullptr,
  589. aStyleContext, aPresContext,
  590. false, true, aConditions);
  591. }
  592. /* Inline helper function to redirect requests to CalcLength. */
  593. static inline nscoord CalcLength(const nsCSSValue& aValue,
  594. nsStyleContext* aStyleContext,
  595. nsPresContext* aPresContext,
  596. RuleNodeCacheConditions& aConditions)
  597. {
  598. return nsRuleNode::CalcLength(aValue, aStyleContext,
  599. aPresContext, aConditions);
  600. }
  601. /* static */ nscoord
  602. nsRuleNode::CalcLengthWithInitialFont(nsPresContext* aPresContext,
  603. const nsCSSValue& aValue)
  604. {
  605. nsStyleFont defaultFont(aPresContext); // FIXME: best language?
  606. RuleNodeCacheConditions conditions;
  607. return CalcLengthWith(aValue, -1, &defaultFont,
  608. nullptr, aPresContext,
  609. true, false, conditions);
  610. }
  611. struct LengthPercentPairCalcOps : public css::NumbersAlreadyNormalizedOps
  612. {
  613. typedef nsRuleNode::ComputedCalc result_type;
  614. LengthPercentPairCalcOps(nsStyleContext* aContext,
  615. nsPresContext* aPresContext,
  616. RuleNodeCacheConditions& aConditions)
  617. : mContext(aContext),
  618. mPresContext(aPresContext),
  619. mConditions(aConditions),
  620. mHasPercent(false) {}
  621. nsStyleContext* mContext;
  622. nsPresContext* mPresContext;
  623. RuleNodeCacheConditions& mConditions;
  624. bool mHasPercent;
  625. result_type ComputeLeafValue(const nsCSSValue& aValue)
  626. {
  627. if (aValue.GetUnit() == eCSSUnit_Percent) {
  628. mHasPercent = true;
  629. return result_type(0, aValue.GetPercentValue());
  630. }
  631. return result_type(CalcLength(aValue, mContext, mPresContext,
  632. mConditions),
  633. 0.0f);
  634. }
  635. result_type
  636. MergeAdditive(nsCSSUnit aCalcFunction,
  637. result_type aValue1, result_type aValue2)
  638. {
  639. if (aCalcFunction == eCSSUnit_Calc_Plus) {
  640. return result_type(NSCoordSaturatingAdd(aValue1.mLength,
  641. aValue2.mLength),
  642. aValue1.mPercent + aValue2.mPercent);
  643. }
  644. MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Minus,
  645. "min() and max() are not allowed in calc() on transform");
  646. return result_type(NSCoordSaturatingSubtract(aValue1.mLength,
  647. aValue2.mLength, 0),
  648. aValue1.mPercent - aValue2.mPercent);
  649. }
  650. result_type
  651. MergeMultiplicativeL(nsCSSUnit aCalcFunction,
  652. float aValue1, result_type aValue2)
  653. {
  654. MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Times_L,
  655. "unexpected unit");
  656. return result_type(NSCoordSaturatingMultiply(aValue2.mLength, aValue1),
  657. aValue1 * aValue2.mPercent);
  658. }
  659. result_type
  660. MergeMultiplicativeR(nsCSSUnit aCalcFunction,
  661. result_type aValue1, float aValue2)
  662. {
  663. MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Times_R ||
  664. aCalcFunction == eCSSUnit_Calc_Divided,
  665. "unexpected unit");
  666. if (aCalcFunction == eCSSUnit_Calc_Divided) {
  667. aValue2 = 1.0f / aValue2;
  668. }
  669. return result_type(NSCoordSaturatingMultiply(aValue1.mLength, aValue2),
  670. aValue1.mPercent * aValue2);
  671. }
  672. };
  673. static void
  674. SpecifiedCalcToComputedCalc(const nsCSSValue& aValue, nsStyleCoord& aCoord,
  675. nsStyleContext* aStyleContext,
  676. RuleNodeCacheConditions& aConditions)
  677. {
  678. LengthPercentPairCalcOps ops(aStyleContext, aStyleContext->PresContext(),
  679. aConditions);
  680. nsRuleNode::ComputedCalc vals = ComputeCalc(aValue, ops);
  681. nsStyleCoord::Calc* calcObj = new nsStyleCoord::Calc;
  682. calcObj->mLength = vals.mLength;
  683. calcObj->mPercent = vals.mPercent;
  684. calcObj->mHasPercent = ops.mHasPercent;
  685. aCoord.SetCalcValue(calcObj);
  686. }
  687. /* static */ nsRuleNode::ComputedCalc
  688. nsRuleNode::SpecifiedCalcToComputedCalc(const nsCSSValue& aValue,
  689. nsStyleContext* aStyleContext,
  690. nsPresContext* aPresContext,
  691. RuleNodeCacheConditions& aConditions)
  692. {
  693. LengthPercentPairCalcOps ops(aStyleContext, aPresContext,
  694. aConditions);
  695. return ComputeCalc(aValue, ops);
  696. }
  697. // This is our public API for handling calc() expressions that involve
  698. // percentages.
  699. /* static */ nscoord
  700. nsRuleNode::ComputeComputedCalc(const nsStyleCoord& aValue,
  701. nscoord aPercentageBasis)
  702. {
  703. nsStyleCoord::Calc* calc = aValue.GetCalcValue();
  704. return calc->mLength +
  705. NSToCoordFloorClamped(aPercentageBasis * calc->mPercent);
  706. }
  707. /* static */ nscoord
  708. nsRuleNode::ComputeCoordPercentCalc(const nsStyleCoord& aCoord,
  709. nscoord aPercentageBasis)
  710. {
  711. switch (aCoord.GetUnit()) {
  712. case eStyleUnit_Coord:
  713. return aCoord.GetCoordValue();
  714. case eStyleUnit_Percent:
  715. return NSToCoordFloorClamped(aPercentageBasis * aCoord.GetPercentValue());
  716. case eStyleUnit_Calc:
  717. return ComputeComputedCalc(aCoord, aPercentageBasis);
  718. default:
  719. MOZ_ASSERT(false, "unexpected unit");
  720. return 0;
  721. }
  722. }
  723. /* Given an enumerated value that represents a box position, converts it to
  724. * a float representing the percentage of the box it corresponds to. For
  725. * example, "center" becomes 0.5f.
  726. *
  727. * @param aEnumValue The enumerated value.
  728. * @return The float percent it corresponds to.
  729. */
  730. static float
  731. GetFloatFromBoxPosition(int32_t aEnumValue)
  732. {
  733. switch (aEnumValue) {
  734. case NS_STYLE_IMAGELAYER_POSITION_LEFT:
  735. case NS_STYLE_IMAGELAYER_POSITION_TOP:
  736. return 0.0f;
  737. case NS_STYLE_IMAGELAYER_POSITION_RIGHT:
  738. case NS_STYLE_IMAGELAYER_POSITION_BOTTOM:
  739. return 1.0f;
  740. default:
  741. MOZ_FALLTHROUGH_ASSERT("unexpected box position value");
  742. case NS_STYLE_IMAGELAYER_POSITION_CENTER:
  743. return 0.5f;
  744. }
  745. }
  746. #define SETCOORD_NORMAL 0x01 // N
  747. #define SETCOORD_AUTO 0x02 // A
  748. #define SETCOORD_INHERIT 0x04 // H
  749. #define SETCOORD_PERCENT 0x08 // P
  750. #define SETCOORD_FACTOR 0x10 // F
  751. #define SETCOORD_LENGTH 0x20 // L
  752. #define SETCOORD_INTEGER 0x40 // I
  753. #define SETCOORD_ENUMERATED 0x80 // E
  754. #define SETCOORD_NONE 0x100 // O
  755. #define SETCOORD_INITIAL_ZERO 0x200
  756. #define SETCOORD_INITIAL_AUTO 0x400
  757. #define SETCOORD_INITIAL_NONE 0x800
  758. #define SETCOORD_INITIAL_NORMAL 0x1000
  759. #define SETCOORD_INITIAL_HALF 0x2000
  760. #define SETCOORD_INITIAL_HUNDRED_PCT 0x00004000
  761. #define SETCOORD_INITIAL_FACTOR_ONE 0x00008000
  762. #define SETCOORD_INITIAL_FACTOR_ZERO 0x00010000
  763. #define SETCOORD_CALC_LENGTH_ONLY 0x00020000
  764. #define SETCOORD_CALC_CLAMP_NONNEGATIVE 0x00040000 // modifier for CALC_LENGTH_ONLY
  765. #define SETCOORD_STORE_CALC 0x00080000
  766. #define SETCOORD_BOX_POSITION 0x00100000 // exclusive with _ENUMERATED
  767. #define SETCOORD_ANGLE 0x00200000
  768. #define SETCOORD_UNSET_INHERIT 0x00400000
  769. #define SETCOORD_UNSET_INITIAL 0x00800000
  770. #define SETCOORD_LP (SETCOORD_LENGTH | SETCOORD_PERCENT)
  771. #define SETCOORD_LH (SETCOORD_LENGTH | SETCOORD_INHERIT)
  772. #define SETCOORD_AH (SETCOORD_AUTO | SETCOORD_INHERIT)
  773. #define SETCOORD_LAH (SETCOORD_AUTO | SETCOORD_LENGTH | SETCOORD_INHERIT)
  774. #define SETCOORD_LPH (SETCOORD_LP | SETCOORD_INHERIT)
  775. #define SETCOORD_LPAH (SETCOORD_LP | SETCOORD_AH)
  776. #define SETCOORD_LPE (SETCOORD_LP | SETCOORD_ENUMERATED)
  777. #define SETCOORD_LPEH (SETCOORD_LPE | SETCOORD_INHERIT)
  778. #define SETCOORD_LPAEH (SETCOORD_LPAH | SETCOORD_ENUMERATED)
  779. #define SETCOORD_LPO (SETCOORD_LP | SETCOORD_NONE)
  780. #define SETCOORD_LPOH (SETCOORD_LPH | SETCOORD_NONE)
  781. #define SETCOORD_LPOEH (SETCOORD_LPOH | SETCOORD_ENUMERATED)
  782. #define SETCOORD_LE (SETCOORD_LENGTH | SETCOORD_ENUMERATED)
  783. #define SETCOORD_LEH (SETCOORD_LE | SETCOORD_INHERIT)
  784. #define SETCOORD_IA (SETCOORD_INTEGER | SETCOORD_AUTO)
  785. #define SETCOORD_LAE (SETCOORD_LENGTH | SETCOORD_AUTO | SETCOORD_ENUMERATED)
  786. // changes aCoord iff it returns true
  787. static bool SetCoord(const nsCSSValue& aValue, nsStyleCoord& aCoord,
  788. const nsStyleCoord& aParentCoord,
  789. int32_t aMask, nsStyleContext* aStyleContext,
  790. nsPresContext* aPresContext,
  791. RuleNodeCacheConditions& aConditions)
  792. {
  793. bool result = true;
  794. if (aValue.GetUnit() == eCSSUnit_Null) {
  795. result = false;
  796. } else if ((((aMask & SETCOORD_LENGTH) != 0) &&
  797. aValue.IsLengthUnit()) ||
  798. (((aMask & SETCOORD_CALC_LENGTH_ONLY) != 0) &&
  799. aValue.IsCalcUnit())) {
  800. nscoord len = CalcLength(aValue, aStyleContext, aPresContext,
  801. aConditions);
  802. if ((aMask & SETCOORD_CALC_CLAMP_NONNEGATIVE) && len < 0) {
  803. NS_ASSERTION(aValue.IsCalcUnit(),
  804. "parser should have ensured no nonnegative lengths");
  805. len = 0;
  806. }
  807. aCoord.SetCoordValue(len);
  808. } else if (((aMask & SETCOORD_PERCENT) != 0) &&
  809. (aValue.GetUnit() == eCSSUnit_Percent)) {
  810. aCoord.SetPercentValue(aValue.GetPercentValue());
  811. } else if (((aMask & SETCOORD_INTEGER) != 0) &&
  812. (aValue.GetUnit() == eCSSUnit_Integer)) {
  813. aCoord.SetIntValue(aValue.GetIntValue(), eStyleUnit_Integer);
  814. } else if (((aMask & SETCOORD_ENUMERATED) != 0) &&
  815. (aValue.GetUnit() == eCSSUnit_Enumerated)) {
  816. aCoord.SetIntValue(aValue.GetIntValue(), eStyleUnit_Enumerated);
  817. } else if (((aMask & SETCOORD_BOX_POSITION) != 0) &&
  818. (aValue.GetUnit() == eCSSUnit_Enumerated)) {
  819. aCoord.SetPercentValue(GetFloatFromBoxPosition(aValue.GetIntValue()));
  820. } else if (((aMask & SETCOORD_AUTO) != 0) &&
  821. (aValue.GetUnit() == eCSSUnit_Auto)) {
  822. aCoord.SetAutoValue();
  823. } else if ((((aMask & SETCOORD_INHERIT) != 0) &&
  824. aValue.GetUnit() == eCSSUnit_Inherit) ||
  825. (((aMask & SETCOORD_UNSET_INHERIT) != 0) &&
  826. aValue.GetUnit() == eCSSUnit_Unset)) {
  827. aCoord = aParentCoord; // just inherit value from parent
  828. aConditions.SetUncacheable();
  829. } else if (((aMask & SETCOORD_NORMAL) != 0) &&
  830. (aValue.GetUnit() == eCSSUnit_Normal)) {
  831. aCoord.SetNormalValue();
  832. } else if (((aMask & SETCOORD_NONE) != 0) &&
  833. (aValue.GetUnit() == eCSSUnit_None)) {
  834. aCoord.SetNoneValue();
  835. } else if (((aMask & SETCOORD_FACTOR) != 0) &&
  836. (aValue.GetUnit() == eCSSUnit_Number)) {
  837. aCoord.SetFactorValue(aValue.GetFloatValue());
  838. } else if (((aMask & SETCOORD_STORE_CALC) != 0) &&
  839. (aValue.IsCalcUnit())) {
  840. SpecifiedCalcToComputedCalc(aValue, aCoord, aStyleContext,
  841. aConditions);
  842. } else if (aValue.GetUnit() == eCSSUnit_Initial ||
  843. (aValue.GetUnit() == eCSSUnit_Unset &&
  844. ((aMask & SETCOORD_UNSET_INITIAL) != 0))) {
  845. if ((aMask & SETCOORD_INITIAL_AUTO) != 0) {
  846. aCoord.SetAutoValue();
  847. } else if ((aMask & SETCOORD_INITIAL_ZERO) != 0) {
  848. aCoord.SetCoordValue(0);
  849. } else if ((aMask & SETCOORD_INITIAL_FACTOR_ZERO) != 0) {
  850. aCoord.SetFactorValue(0.0f);
  851. } else if ((aMask & SETCOORD_INITIAL_NONE) != 0) {
  852. aCoord.SetNoneValue();
  853. } else if ((aMask & SETCOORD_INITIAL_NORMAL) != 0) {
  854. aCoord.SetNormalValue();
  855. } else if ((aMask & SETCOORD_INITIAL_HALF) != 0) {
  856. aCoord.SetPercentValue(0.5f);
  857. } else if ((aMask & SETCOORD_INITIAL_HUNDRED_PCT) != 0) {
  858. aCoord.SetPercentValue(1.0f);
  859. } else if ((aMask & SETCOORD_INITIAL_FACTOR_ONE) != 0) {
  860. aCoord.SetFactorValue(1.0f);
  861. } else {
  862. result = false; // didn't set anything
  863. }
  864. } else if ((aMask & SETCOORD_ANGLE) != 0 &&
  865. (aValue.IsAngularUnit())) {
  866. nsStyleUnit unit;
  867. switch (aValue.GetUnit()) {
  868. case eCSSUnit_Degree: unit = eStyleUnit_Degree; break;
  869. case eCSSUnit_Grad: unit = eStyleUnit_Grad; break;
  870. case eCSSUnit_Radian: unit = eStyleUnit_Radian; break;
  871. case eCSSUnit_Turn: unit = eStyleUnit_Turn; break;
  872. default: NS_NOTREACHED("unrecognized angular unit");
  873. unit = eStyleUnit_Degree;
  874. }
  875. aCoord.SetAngleValue(aValue.GetAngleValue(), unit);
  876. }
  877. else {
  878. result = false; // didn't set anything
  879. }
  880. return result;
  881. }
  882. // This inline function offers a shortcut for SetCoord() by refusing to accept
  883. // SETCOORD_LENGTH, SETCOORD_INHERIT and SETCOORD_UNSET_* masks.
  884. static inline bool SetAbsCoord(const nsCSSValue& aValue,
  885. nsStyleCoord& aCoord,
  886. int32_t aMask)
  887. {
  888. MOZ_ASSERT((aMask & (SETCOORD_LH | SETCOORD_UNSET_INHERIT |
  889. SETCOORD_UNSET_INITIAL)) == 0,
  890. "does not handle SETCOORD_LENGTH, SETCOORD_INHERIT and "
  891. "SETCOORD_UNSET_*");
  892. // The values of the following variables will never be used; so it does not
  893. // matter what to set.
  894. const nsStyleCoord dummyParentCoord;
  895. nsStyleContext* dummyStyleContext = nullptr;
  896. nsPresContext* dummyPresContext = nullptr;
  897. RuleNodeCacheConditions dummyCacheKey;
  898. bool rv = SetCoord(aValue, aCoord, dummyParentCoord, aMask,
  899. dummyStyleContext, dummyPresContext,
  900. dummyCacheKey);
  901. MOZ_ASSERT(dummyCacheKey.CacheableWithoutDependencies(),
  902. "SetCoord() should not modify dummyCacheKey.");
  903. return rv;
  904. }
  905. /* Given a specified value that might be a pair value, call SetCoord twice,
  906. * either using each member of the pair, or using the unpaired value twice.
  907. */
  908. static bool
  909. SetPairCoords(const nsCSSValue& aValue,
  910. nsStyleCoord& aCoordX, nsStyleCoord& aCoordY,
  911. const nsStyleCoord& aParentX, const nsStyleCoord& aParentY,
  912. int32_t aMask, nsStyleContext* aStyleContext,
  913. nsPresContext* aPresContext, RuleNodeCacheConditions& aConditions)
  914. {
  915. const nsCSSValue& valX =
  916. aValue.GetUnit() == eCSSUnit_Pair ? aValue.GetPairValue().mXValue : aValue;
  917. const nsCSSValue& valY =
  918. aValue.GetUnit() == eCSSUnit_Pair ? aValue.GetPairValue().mYValue : aValue;
  919. bool cX = SetCoord(valX, aCoordX, aParentX, aMask, aStyleContext,
  920. aPresContext, aConditions);
  921. mozilla::DebugOnly<bool> cY = SetCoord(valY, aCoordY, aParentY, aMask,
  922. aStyleContext, aPresContext, aConditions);
  923. MOZ_ASSERT(cX == cY, "changed one but not the other");
  924. return cX;
  925. }
  926. static bool SetColor(const nsCSSValue& aValue, const nscolor aParentColor,
  927. nsPresContext* aPresContext, nsStyleContext *aContext,
  928. nscolor& aResult, RuleNodeCacheConditions& aConditions)
  929. {
  930. bool result = false;
  931. nsCSSUnit unit = aValue.GetUnit();
  932. if (aValue.IsNumericColorUnit()) {
  933. aResult = aValue.GetColorValue();
  934. result = true;
  935. } else if (eCSSUnit_Ident == unit) {
  936. nsAutoString value;
  937. aValue.GetStringValue(value);
  938. nscolor rgba;
  939. if (NS_ColorNameToRGB(value, &rgba)) {
  940. aResult = rgba;
  941. result = true;
  942. }
  943. } else if (eCSSUnit_EnumColor == unit) {
  944. int32_t intValue = aValue.GetIntValue();
  945. if (0 <= intValue) {
  946. LookAndFeel::ColorID colorID = (LookAndFeel::ColorID) intValue;
  947. bool useStandinsForNativeColors = aPresContext &&
  948. !aPresContext->IsChrome();
  949. if (NS_SUCCEEDED(LookAndFeel::GetColor(colorID,
  950. useStandinsForNativeColors, &aResult))) {
  951. result = true;
  952. }
  953. }
  954. else {
  955. aResult = NS_RGB(0, 0, 0);
  956. result = false;
  957. switch (intValue) {
  958. case NS_COLOR_MOZ_HYPERLINKTEXT:
  959. if (aPresContext) {
  960. aResult = aPresContext->DefaultLinkColor();
  961. result = true;
  962. }
  963. break;
  964. case NS_COLOR_MOZ_VISITEDHYPERLINKTEXT:
  965. if (aPresContext) {
  966. aResult = aPresContext->DefaultVisitedLinkColor();
  967. result = true;
  968. }
  969. break;
  970. case NS_COLOR_MOZ_ACTIVEHYPERLINKTEXT:
  971. if (aPresContext) {
  972. aResult = aPresContext->DefaultActiveLinkColor();
  973. result = true;
  974. }
  975. break;
  976. case NS_COLOR_CURRENTCOLOR:
  977. // The data computed from this can't be shared in the rule tree
  978. // because they could be used on a node with a different color
  979. aConditions.SetUncacheable();
  980. if (aContext) {
  981. aResult = aContext->StyleColor()->mColor;
  982. result = true;
  983. }
  984. break;
  985. case NS_COLOR_MOZ_DEFAULT_COLOR:
  986. if (aPresContext) {
  987. aResult = aPresContext->DefaultColor();
  988. result = true;
  989. }
  990. break;
  991. case NS_COLOR_MOZ_DEFAULT_BACKGROUND_COLOR:
  992. if (aPresContext) {
  993. aResult = aPresContext->DefaultBackgroundColor();
  994. result = true;
  995. }
  996. break;
  997. default:
  998. NS_NOTREACHED("Should never have an unknown negative colorID.");
  999. break;
  1000. }
  1001. }
  1002. } else if (eCSSUnit_Inherit == unit) {
  1003. aResult = aParentColor;
  1004. result = true;
  1005. aConditions.SetUncacheable();
  1006. } else if (eCSSUnit_Enumerated == unit &&
  1007. aValue.GetIntValue() == NS_STYLE_COLOR_INHERIT_FROM_BODY) {
  1008. NS_ASSERTION(aPresContext->CompatibilityMode() == eCompatibility_NavQuirks,
  1009. "Should only get this value in quirks mode");
  1010. // We just grab the color from the prescontext, and rely on the fact that
  1011. // if the body color ever changes all its descendants will get new style
  1012. // contexts (but NOT necessarily new rulenodes).
  1013. aResult = aPresContext->BodyTextColor();
  1014. result = true;
  1015. aConditions.SetUncacheable();
  1016. }
  1017. return result;
  1018. }
  1019. template<UnsetAction UnsetTo>
  1020. static void
  1021. SetComplexColor(const nsCSSValue& aValue,
  1022. const StyleComplexColor& aParentColor,
  1023. const StyleComplexColor& aInitialColor,
  1024. nsPresContext* aPresContext,
  1025. StyleComplexColor& aResult,
  1026. RuleNodeCacheConditions& aConditions)
  1027. {
  1028. nsCSSUnit unit = aValue.GetUnit();
  1029. if (unit == eCSSUnit_Null) {
  1030. return;
  1031. }
  1032. if (unit == eCSSUnit_Initial ||
  1033. (UnsetTo == eUnsetInitial && unit == eCSSUnit_Unset)) {
  1034. aResult = aInitialColor;
  1035. } else if (unit == eCSSUnit_Inherit ||
  1036. (UnsetTo == eUnsetInherit && unit == eCSSUnit_Unset)) {
  1037. aConditions.SetUncacheable();
  1038. aResult = aParentColor;
  1039. } else if (unit == eCSSUnit_EnumColor &&
  1040. aValue.GetIntValue() == NS_COLOR_CURRENTCOLOR) {
  1041. aResult = StyleComplexColor::CurrentColor();
  1042. } else if (unit == eCSSUnit_ComplexColor) {
  1043. aResult = aValue.GetStyleComplexColorValue();
  1044. } else if (unit == eCSSUnit_Auto) {
  1045. aResult = StyleComplexColor::Auto();
  1046. } else {
  1047. nscolor resultColor;
  1048. if (!SetColor(aValue, aParentColor.mColor, aPresContext,
  1049. nullptr, resultColor, aConditions)) {
  1050. MOZ_ASSERT_UNREACHABLE("Unknown color value");
  1051. return;
  1052. }
  1053. aResult = StyleComplexColor::FromColor(resultColor);
  1054. }
  1055. }
  1056. static void SetGradientCoord(const nsCSSValue& aValue, nsPresContext* aPresContext,
  1057. nsStyleContext* aContext, nsStyleCoord& aResult,
  1058. RuleNodeCacheConditions& aConditions)
  1059. {
  1060. // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
  1061. if (!SetCoord(aValue, aResult, nsStyleCoord(),
  1062. SETCOORD_LPO | SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC,
  1063. aContext, aPresContext, aConditions)) {
  1064. NS_NOTREACHED("unexpected unit for gradient anchor point");
  1065. aResult.SetNoneValue();
  1066. }
  1067. }
  1068. static void SetGradient(const nsCSSValue& aValue, nsPresContext* aPresContext,
  1069. nsStyleContext* aContext, nsStyleGradient& aResult,
  1070. RuleNodeCacheConditions& aConditions)
  1071. {
  1072. MOZ_ASSERT(aValue.GetUnit() == eCSSUnit_Gradient,
  1073. "The given data is not a gradient");
  1074. const nsCSSValueGradient* gradient = aValue.GetGradientValue();
  1075. if (gradient->mIsExplicitSize) {
  1076. SetCoord(gradient->GetRadiusX(), aResult.mRadiusX, nsStyleCoord(),
  1077. SETCOORD_LP | SETCOORD_STORE_CALC,
  1078. aContext, aPresContext, aConditions);
  1079. if (gradient->GetRadiusY().GetUnit() != eCSSUnit_None) {
  1080. SetCoord(gradient->GetRadiusY(), aResult.mRadiusY, nsStyleCoord(),
  1081. SETCOORD_LP | SETCOORD_STORE_CALC,
  1082. aContext, aPresContext, aConditions);
  1083. aResult.mShape = NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL;
  1084. } else {
  1085. aResult.mRadiusY = aResult.mRadiusX;
  1086. aResult.mShape = NS_STYLE_GRADIENT_SHAPE_CIRCULAR;
  1087. }
  1088. aResult.mSize = NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE;
  1089. } else if (gradient->mIsRadial) {
  1090. if (gradient->GetRadialShape().GetUnit() == eCSSUnit_Enumerated) {
  1091. aResult.mShape = gradient->GetRadialShape().GetIntValue();
  1092. } else {
  1093. NS_ASSERTION(gradient->GetRadialShape().GetUnit() == eCSSUnit_None,
  1094. "bad unit for radial shape");
  1095. aResult.mShape = NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL;
  1096. }
  1097. if (gradient->GetRadialSize().GetUnit() == eCSSUnit_Enumerated) {
  1098. aResult.mSize = gradient->GetRadialSize().GetIntValue();
  1099. } else {
  1100. NS_ASSERTION(gradient->GetRadialSize().GetUnit() == eCSSUnit_None,
  1101. "bad unit for radial shape");
  1102. aResult.mSize = NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER;
  1103. }
  1104. } else {
  1105. NS_ASSERTION(gradient->GetRadialShape().GetUnit() == eCSSUnit_None,
  1106. "bad unit for linear shape");
  1107. NS_ASSERTION(gradient->GetRadialSize().GetUnit() == eCSSUnit_None,
  1108. "bad unit for linear size");
  1109. aResult.mShape = NS_STYLE_GRADIENT_SHAPE_LINEAR;
  1110. aResult.mSize = NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER;
  1111. }
  1112. aResult.mLegacySyntax = gradient->mIsLegacySyntax;
  1113. // bg-position
  1114. SetGradientCoord(gradient->mBgPos.mXValue, aPresContext, aContext,
  1115. aResult.mBgPosX, aConditions);
  1116. SetGradientCoord(gradient->mBgPos.mYValue, aPresContext, aContext,
  1117. aResult.mBgPosY, aConditions);
  1118. aResult.mRepeating = gradient->mIsRepeating;
  1119. // angle
  1120. const nsStyleCoord dummyParentCoord;
  1121. if (!SetCoord(gradient->mAngle, aResult.mAngle, dummyParentCoord, SETCOORD_ANGLE,
  1122. aContext, aPresContext, aConditions)) {
  1123. NS_ASSERTION(gradient->mAngle.GetUnit() == eCSSUnit_None,
  1124. "bad unit for gradient angle");
  1125. aResult.mAngle.SetNoneValue();
  1126. }
  1127. // stops
  1128. for (uint32_t i = 0; i < gradient->mStops.Length(); i++) {
  1129. nsStyleGradientStop stop;
  1130. const nsCSSValueGradientStop &valueStop = gradient->mStops[i];
  1131. if (!SetCoord(valueStop.mLocation, stop.mLocation,
  1132. nsStyleCoord(), SETCOORD_LPO | SETCOORD_STORE_CALC,
  1133. aContext, aPresContext, aConditions)) {
  1134. NS_NOTREACHED("unexpected unit for gradient stop location");
  1135. }
  1136. stop.mIsInterpolationHint = valueStop.mIsInterpolationHint;
  1137. // inherit is not a valid color for stops, so we pass in a dummy
  1138. // parent color
  1139. NS_ASSERTION(valueStop.mColor.GetUnit() != eCSSUnit_Inherit,
  1140. "inherit is not a valid color for gradient stops");
  1141. if (!valueStop.mIsInterpolationHint) {
  1142. SetColor(valueStop.mColor, NS_RGB(0, 0, 0), aPresContext,
  1143. aContext, stop.mColor, aConditions);
  1144. } else {
  1145. // Always initialize to the same color so we don't need to worry
  1146. // about comparisons.
  1147. stop.mColor = NS_RGB(0, 0, 0);
  1148. }
  1149. aResult.mStops.AppendElement(stop);
  1150. }
  1151. }
  1152. // -moz-image-rect(<uri>, <top>, <right>, <bottom>, <left>)
  1153. static void SetStyleImageToImageRect(nsStyleContext* aStyleContext,
  1154. const nsCSSValue& aValue,
  1155. nsStyleImage& aResult)
  1156. {
  1157. MOZ_ASSERT(aValue.GetUnit() == eCSSUnit_Function &&
  1158. aValue.EqualsFunction(eCSSKeyword__moz_image_rect),
  1159. "the value is not valid -moz-image-rect()");
  1160. nsCSSValue::Array* arr = aValue.GetArrayValue();
  1161. MOZ_ASSERT(arr && arr->Count() == 6, "invalid number of arguments");
  1162. // <uri>
  1163. if (arr->Item(1).GetUnit() == eCSSUnit_Image) {
  1164. SetStyleImageRequest([&](nsStyleImageRequest* req) {
  1165. aResult.SetImageRequest(do_AddRef(req));
  1166. }, aStyleContext->PresContext(), arr->Item(1));
  1167. } else {
  1168. NS_WARNING("nsCSSValue::Image::Image() failed?");
  1169. }
  1170. // <top>, <right>, <bottom>, <left>
  1171. nsStyleSides cropRect;
  1172. NS_FOR_CSS_SIDES(side) {
  1173. nsStyleCoord coord;
  1174. const nsCSSValue& val = arr->Item(2 + side);
  1175. #ifdef DEBUG
  1176. bool unitOk =
  1177. #endif
  1178. SetAbsCoord(val, coord, SETCOORD_FACTOR | SETCOORD_PERCENT);
  1179. MOZ_ASSERT(unitOk, "Incorrect data structure created by CSS parser");
  1180. cropRect.Set(side, coord);
  1181. }
  1182. aResult.SetCropRect(MakeUnique<nsStyleSides>(cropRect));
  1183. }
  1184. static void SetStyleImage(nsStyleContext* aStyleContext,
  1185. const nsCSSValue& aValue,
  1186. nsStyleImage& aResult,
  1187. RuleNodeCacheConditions& aConditions)
  1188. {
  1189. if (aValue.GetUnit() == eCSSUnit_Null) {
  1190. return;
  1191. }
  1192. aResult.SetNull();
  1193. switch (aValue.GetUnit()) {
  1194. case eCSSUnit_Image:
  1195. SetStyleImageRequest([&](nsStyleImageRequest* req) {
  1196. aResult.SetImageRequest(do_AddRef(req));
  1197. }, aStyleContext->PresContext(), aValue);
  1198. break;
  1199. case eCSSUnit_Function:
  1200. if (aValue.EqualsFunction(eCSSKeyword__moz_image_rect)) {
  1201. SetStyleImageToImageRect(aStyleContext, aValue, aResult);
  1202. } else {
  1203. NS_NOTREACHED("-moz-image-rect() is the only expected function");
  1204. }
  1205. break;
  1206. case eCSSUnit_Gradient:
  1207. {
  1208. nsStyleGradient* gradient = new nsStyleGradient();
  1209. SetGradient(aValue, aStyleContext->PresContext(), aStyleContext,
  1210. *gradient, aConditions);
  1211. aResult.SetGradientData(gradient);
  1212. break;
  1213. }
  1214. case eCSSUnit_Element:
  1215. aResult.SetElementId(aValue.GetStringBufferValue());
  1216. break;
  1217. case eCSSUnit_Initial:
  1218. case eCSSUnit_Unset:
  1219. case eCSSUnit_None:
  1220. break;
  1221. case eCSSUnit_URL:
  1222. {
  1223. #ifdef DEBUG
  1224. // eCSSUnit_URL is expected only if
  1225. // 1. we have eCSSUnit_URL values for if-visited style contexts, which
  1226. // we can safely treat like 'none'.
  1227. // 2. aValue is a local-ref URL, e.g. url(#foo).
  1228. // 3. aValue is a not a local-ref URL, but it refers to an element in
  1229. // the current document. For example, the url of the current document
  1230. // is "http://foo.html" and aValue is url(http://foo.html#foo).
  1231. //
  1232. // We skip image download in TryToStartImageLoadOnValue under #2 and #3,
  1233. // and that's part of reasons we get eCSSUnit_URL instead of
  1234. // eCSSUnit_Image here.
  1235. // Check #2.
  1236. bool isLocalRef = aValue.GetURLStructValue()->IsLocalRef();
  1237. // Check #3.
  1238. bool isEqualExceptRef = false;
  1239. if (!isLocalRef) {
  1240. nsIDocument* currentDoc = aStyleContext->PresContext()->Document();
  1241. nsIURI* docURI = currentDoc->GetDocumentURI();
  1242. nsIURI* imageURI = aValue.GetURLValue();
  1243. imageURI->EqualsExceptRef(docURI, &isEqualExceptRef);
  1244. }
  1245. MOZ_ASSERT(aStyleContext->IsStyleIfVisited() || isEqualExceptRef ||
  1246. isLocalRef,
  1247. "unexpected unit; maybe nsCSSValue::Image::Image() failed?");
  1248. #endif
  1249. break;
  1250. }
  1251. default:
  1252. MOZ_ASSERT_UNREACHABLE("Unexpected Unit type.");
  1253. break;
  1254. }
  1255. }
  1256. struct SetEnumValueHelper
  1257. {
  1258. template<typename FieldT>
  1259. static void SetIntegerValue(FieldT&, const nsCSSValue&)
  1260. {
  1261. // FIXME Is it possible to turn this assertion into a compilation error?
  1262. MOZ_ASSERT_UNREACHABLE("inappropriate unit");
  1263. }
  1264. #define DEFINE_ENUM_CLASS_SETTER(type_, min_, max_) \
  1265. static void SetEnumeratedValue(type_& aField, const nsCSSValue& aValue) \
  1266. { \
  1267. auto value = aValue.GetIntValue(); \
  1268. MOZ_ASSERT(value >= static_cast<decltype(value)>(type_::min_) && \
  1269. value <= static_cast<decltype(value)>(type_::max_), \
  1270. "inappropriate value"); \
  1271. aField = static_cast<type_>(value); \
  1272. }
  1273. DEFINE_ENUM_CLASS_SETTER(StyleBoxAlign, Stretch, End)
  1274. DEFINE_ENUM_CLASS_SETTER(StyleBoxDecorationBreak, Slice, Clone)
  1275. DEFINE_ENUM_CLASS_SETTER(StyleBoxDirection, Normal, Reverse)
  1276. DEFINE_ENUM_CLASS_SETTER(StyleBoxOrient, Horizontal, Vertical)
  1277. DEFINE_ENUM_CLASS_SETTER(StyleBoxPack, Start, Justify)
  1278. DEFINE_ENUM_CLASS_SETTER(StyleBoxSizing, Content, Border)
  1279. DEFINE_ENUM_CLASS_SETTER(StyleClear, None, Both)
  1280. DEFINE_ENUM_CLASS_SETTER(StyleFillRule, Nonzero, Evenodd)
  1281. DEFINE_ENUM_CLASS_SETTER(StyleFloat, None, InlineEnd)
  1282. DEFINE_ENUM_CLASS_SETTER(StyleFloatEdge, ContentBox, MarginBox)
  1283. DEFINE_ENUM_CLASS_SETTER(StyleScrollbarWidth, Auto, None)
  1284. DEFINE_ENUM_CLASS_SETTER(StyleTextJustify, None, InterCharacter)
  1285. DEFINE_ENUM_CLASS_SETTER(StyleUserFocus, None, SelectMenu)
  1286. DEFINE_ENUM_CLASS_SETTER(StyleUserSelect, None, MozText)
  1287. DEFINE_ENUM_CLASS_SETTER(StyleUserInput, None, Auto)
  1288. DEFINE_ENUM_CLASS_SETTER(StyleUserModify, ReadOnly, WriteOnly)
  1289. DEFINE_ENUM_CLASS_SETTER(StyleWindowDragging, Default, NoDrag)
  1290. DEFINE_ENUM_CLASS_SETTER(StyleOrient, Inline, Vertical)
  1291. #ifdef MOZ_XUL
  1292. DEFINE_ENUM_CLASS_SETTER(StyleDisplay, None, Popup)
  1293. #else
  1294. DEFINE_ENUM_CLASS_SETTER(StyleDisplay, None, InlineBox)
  1295. #endif
  1296. #undef DEF_SET_ENUMERATED_VALUE
  1297. };
  1298. template<typename FieldT>
  1299. struct SetIntegerValueHelper
  1300. {
  1301. static void SetIntegerValue(FieldT& aField, const nsCSSValue& aValue)
  1302. {
  1303. aField = aValue.GetIntValue();
  1304. }
  1305. static void SetEnumeratedValue(FieldT& aField, const nsCSSValue& aValue)
  1306. {
  1307. aField = aValue.GetIntValue();
  1308. }
  1309. };
  1310. template<typename FieldT>
  1311. struct SetValueHelper : Conditional<IsEnum<FieldT>::value,
  1312. SetEnumValueHelper,
  1313. SetIntegerValueHelper<FieldT>>::Type
  1314. {
  1315. template<typename ValueT>
  1316. static void SetValue(FieldT& aField, const ValueT& aValue)
  1317. {
  1318. aField = aValue;
  1319. }
  1320. static void SetValue(FieldT&, unused_t)
  1321. {
  1322. // FIXME Is it possible to turn this assertion into a compilation error?
  1323. MOZ_ASSERT_UNREACHABLE("inappropriate unit");
  1324. }
  1325. };
  1326. // flags for SetValue - align values with SETCOORD_* constants
  1327. // where possible
  1328. #define SETVAL_INTEGER 0x40 // I
  1329. #define SETVAL_ENUMERATED 0x80 // E
  1330. #define SETVAL_UNSET_INHERIT 0x00400000
  1331. #define SETVAL_UNSET_INITIAL 0x00800000
  1332. // no caller cares whether aField was changed or not
  1333. template<typename FieldT, typename InitialT,
  1334. typename AutoT, typename NoneT, typename NormalT, typename SysFontT>
  1335. static void
  1336. SetValue(const nsCSSValue& aValue, FieldT& aField,
  1337. RuleNodeCacheConditions& aConditions, uint32_t aMask,
  1338. FieldT aParentValue,
  1339. InitialT aInitialValue,
  1340. AutoT aAutoValue,
  1341. NoneT aNoneValue,
  1342. NormalT aNormalValue,
  1343. SysFontT aSystemFontValue)
  1344. {
  1345. typedef SetValueHelper<FieldT> Helper;
  1346. switch (aValue.GetUnit()) {
  1347. case eCSSUnit_Null:
  1348. return;
  1349. // every caller of SetValue provides inherit and initial
  1350. // alternatives, so we don't require them to say so in the mask
  1351. case eCSSUnit_Inherit:
  1352. aConditions.SetUncacheable();
  1353. aField = aParentValue;
  1354. return;
  1355. case eCSSUnit_Initial:
  1356. Helper::SetValue(aField, aInitialValue);
  1357. return;
  1358. // every caller provides one or other of these alternatives,
  1359. // but they have to say which
  1360. case eCSSUnit_Enumerated:
  1361. if (aMask & SETVAL_ENUMERATED) {
  1362. Helper::SetEnumeratedValue(aField, aValue);
  1363. return;
  1364. }
  1365. break;
  1366. case eCSSUnit_Integer:
  1367. if (aMask & SETVAL_INTEGER) {
  1368. Helper::SetIntegerValue(aField, aValue);
  1369. return;
  1370. }
  1371. break;
  1372. // remaining possibilities in descending order of frequency of use
  1373. case eCSSUnit_Auto:
  1374. Helper::SetValue(aField, aAutoValue);
  1375. return;
  1376. case eCSSUnit_None:
  1377. Helper::SetValue(aField, aNoneValue);
  1378. return;
  1379. case eCSSUnit_Normal:
  1380. Helper::SetValue(aField, aNormalValue);
  1381. return;
  1382. case eCSSUnit_System_Font:
  1383. Helper::SetValue(aField, aSystemFontValue);
  1384. return;
  1385. case eCSSUnit_Unset:
  1386. if (aMask & SETVAL_UNSET_INHERIT) {
  1387. aConditions.SetUncacheable();
  1388. aField = aParentValue;
  1389. return;
  1390. }
  1391. if (aMask & SETVAL_UNSET_INITIAL) {
  1392. Helper::SetValue(aField, aInitialValue);
  1393. return;
  1394. }
  1395. break;
  1396. default:
  1397. break;
  1398. }
  1399. NS_NOTREACHED("SetValue: inappropriate unit");
  1400. }
  1401. template <typename FieldT, typename T1>
  1402. static void
  1403. SetValue(const nsCSSValue& aValue, FieldT& aField,
  1404. RuleNodeCacheConditions& aConditions, uint32_t aMask,
  1405. FieldT aParentValue, T1 aInitialValue)
  1406. {
  1407. SetValue(aValue, aField, aConditions, aMask, aParentValue,
  1408. aInitialValue, Unused, Unused, Unused, Unused);
  1409. }
  1410. // flags for SetFactor
  1411. #define SETFCT_POSITIVE 0x01 // assert value is >= 0.0f
  1412. #define SETFCT_OPACITY 0x02 // clamp value to [0.0f .. 1.0f]
  1413. #define SETFCT_NONE 0x04 // allow _None (uses aInitialValue).
  1414. #define SETFCT_UNSET_INHERIT 0x00400000
  1415. #define SETFCT_UNSET_INITIAL 0x00800000
  1416. static void
  1417. SetFactor(const nsCSSValue& aValue, float& aField, RuleNodeCacheConditions& aConditions,
  1418. float aParentValue, float aInitialValue, uint32_t aFlags = 0)
  1419. {
  1420. switch (aValue.GetUnit()) {
  1421. case eCSSUnit_Null:
  1422. return;
  1423. case eCSSUnit_Number:
  1424. aField = aValue.GetFloatValue();
  1425. if (aFlags & SETFCT_POSITIVE) {
  1426. NS_ASSERTION(aField >= 0.0f, "negative value for positive-only property");
  1427. if (aField < 0.0f) {
  1428. aField = 0.0f;
  1429. }
  1430. }
  1431. if (aFlags & SETFCT_OPACITY) {
  1432. if (aField < 0.0f) {
  1433. aField = 0.0f;
  1434. }
  1435. if (aField > 1.0f) {
  1436. aField = 1.0f;
  1437. }
  1438. }
  1439. return;
  1440. case eCSSUnit_Inherit:
  1441. aConditions.SetUncacheable();
  1442. aField = aParentValue;
  1443. return;
  1444. case eCSSUnit_Initial:
  1445. aField = aInitialValue;
  1446. return;
  1447. case eCSSUnit_None:
  1448. if (aFlags & SETFCT_NONE) {
  1449. aField = aInitialValue;
  1450. return;
  1451. }
  1452. break;
  1453. case eCSSUnit_Unset:
  1454. if (aFlags & SETFCT_UNSET_INHERIT) {
  1455. aConditions.SetUncacheable();
  1456. aField = aParentValue;
  1457. return;
  1458. }
  1459. if (aFlags & SETFCT_UNSET_INITIAL) {
  1460. aField = aInitialValue;
  1461. return;
  1462. }
  1463. break;
  1464. default:
  1465. break;
  1466. }
  1467. NS_NOTREACHED("SetFactor: inappropriate unit");
  1468. }
  1469. void*
  1470. nsRuleNode::operator new(size_t sz, nsPresContext* aPresContext)
  1471. {
  1472. // Check the recycle list first.
  1473. return aPresContext->PresShell()->AllocateByObjectID(eArenaObjectID_nsRuleNode, sz);
  1474. }
  1475. // Overridden to prevent the global delete from being called, since the memory
  1476. // came out of an nsIArena instead of the global delete operator's heap.
  1477. void
  1478. nsRuleNode::Destroy()
  1479. {
  1480. // Destroy ourselves.
  1481. this->~nsRuleNode();
  1482. // Don't let the memory be freed, since it will be recycled
  1483. // instead. Don't call the global operator delete.
  1484. mPresContext->PresShell()->FreeByObjectID(eArenaObjectID_nsRuleNode, this);
  1485. }
  1486. already_AddRefed<nsRuleNode>
  1487. nsRuleNode::CreateRootNode(nsPresContext* aPresContext)
  1488. {
  1489. return do_AddRef(new (aPresContext)
  1490. nsRuleNode(aPresContext, nullptr, nullptr, SheetType::Unknown, false));
  1491. }
  1492. nsRuleNode::nsRuleNode(nsPresContext* aContext, nsRuleNode* aParent,
  1493. nsIStyleRule* aRule, SheetType aLevel,
  1494. bool aIsImportant)
  1495. : mPresContext(aContext),
  1496. mParent(aParent),
  1497. mRule(aRule),
  1498. mNextSibling(nullptr),
  1499. mDependentBits((uint32_t(aLevel) << NS_RULE_NODE_LEVEL_SHIFT) |
  1500. (aIsImportant ? NS_RULE_NODE_IS_IMPORTANT : 0)),
  1501. mNoneBits(aParent ? aParent->mNoneBits & NS_RULE_NODE_HAS_ANIMATION_DATA :
  1502. 0),
  1503. mRefCnt(0)
  1504. {
  1505. MOZ_ASSERT(aContext);
  1506. MOZ_ASSERT(IsRoot() == !aRule,
  1507. "non-root rule nodes must have a rule");
  1508. mChildren.asVoid = nullptr;
  1509. MOZ_COUNT_CTOR(nsRuleNode);
  1510. NS_ASSERTION(IsRoot() || GetLevel() == aLevel, "not enough bits");
  1511. NS_ASSERTION(IsRoot() || IsImportantRule() == aIsImportant, "yikes");
  1512. MOZ_ASSERT(aContext->StyleSet()->IsGecko(),
  1513. "ServoStyleSets should not have rule nodes");
  1514. aContext->StyleSet()->AsGecko()->RuleNodeUnused(this, /* aMayGC = */ false);
  1515. // nsStyleSet::GetContext depends on there being only one animation
  1516. // rule.
  1517. MOZ_ASSERT(IsRoot() || GetLevel() != SheetType::Animation ||
  1518. mParent->IsRoot() ||
  1519. mParent->GetLevel() != SheetType::Animation,
  1520. "must be only one rule at animation level");
  1521. }
  1522. nsRuleNode::~nsRuleNode()
  1523. {
  1524. MOZ_ASSERT(!HaveChildren());
  1525. MOZ_COUNT_DTOR(nsRuleNode);
  1526. if (mParent) {
  1527. mParent->RemoveChild(this);
  1528. }
  1529. if (mStyleData.mResetData || mStyleData.mInheritedData)
  1530. mStyleData.Destroy(mDependentBits, mPresContext);
  1531. }
  1532. nsRuleNode*
  1533. nsRuleNode::Transition(nsIStyleRule* aRule, SheetType aLevel,
  1534. bool aIsImportantRule)
  1535. {
  1536. #ifdef DEBUG
  1537. {
  1538. RefPtr<css::Declaration> declaration(do_QueryObject(aRule));
  1539. MOZ_ASSERT(!declaration || !declaration->IsMutable(),
  1540. "caller must call Declaration::SetImmutable first");
  1541. }
  1542. #endif
  1543. nsRuleNode* next = nullptr;
  1544. nsRuleNode::Key key(aRule, aLevel, aIsImportantRule);
  1545. if (HaveChildren() && !ChildrenAreHashed()) {
  1546. int32_t numKids = 0;
  1547. nsRuleNode* curr = ChildrenList();
  1548. while (curr && curr->GetKey() != key) {
  1549. curr = curr->mNextSibling;
  1550. ++numKids;
  1551. }
  1552. if (curr) {
  1553. next = curr;
  1554. } else if (numKids >= kMaxChildrenInList) {
  1555. ConvertChildrenToHash(numKids);
  1556. }
  1557. }
  1558. if (ChildrenAreHashed()) {
  1559. auto entry =
  1560. static_cast<ChildrenHashEntry*>(ChildrenHash()->Add(&key, fallible));
  1561. if (!entry) {
  1562. NS_WARNING("out of memory");
  1563. return this;
  1564. }
  1565. if (entry->mRuleNode) {
  1566. next = entry->mRuleNode;
  1567. } else {
  1568. next = entry->mRuleNode = new (mPresContext)
  1569. nsRuleNode(mPresContext, this, aRule, aLevel, aIsImportantRule);
  1570. }
  1571. } else if (!next) {
  1572. // Create the new entry in our list.
  1573. next = new (mPresContext)
  1574. nsRuleNode(mPresContext, this, aRule, aLevel, aIsImportantRule);
  1575. next->mNextSibling = ChildrenList();
  1576. SetChildrenList(next);
  1577. }
  1578. return next;
  1579. }
  1580. nsRuleNode*
  1581. nsRuleNode::RuleTree()
  1582. {
  1583. nsRuleNode* n = this;
  1584. while (n->mParent) {
  1585. n = n->mParent;
  1586. }
  1587. return n;
  1588. }
  1589. void nsRuleNode::SetUsedDirectly()
  1590. {
  1591. mDependentBits |= NS_RULE_NODE_USED_DIRECTLY;
  1592. // Maintain the invariant that any rule node that is used directly has
  1593. // all structs that live in the rule tree cached (which
  1594. // nsRuleNode::GetStyleData depends on for speed).
  1595. if (mDependentBits & NS_STYLE_INHERIT_MASK) {
  1596. for (nsStyleStructID sid = nsStyleStructID(0); sid < nsStyleStructID_Length;
  1597. sid = nsStyleStructID(sid + 1)) {
  1598. uint32_t bit = nsCachedStyleData::GetBitForSID(sid);
  1599. if (mDependentBits & bit) {
  1600. nsRuleNode *source = mParent;
  1601. while ((source->mDependentBits & bit) && !source->IsUsedDirectly()) {
  1602. source = source->mParent;
  1603. }
  1604. void *data = source->mStyleData.GetStyleData(sid);
  1605. NS_ASSERTION(data, "unexpected null struct");
  1606. mStyleData.SetStyleData(sid, mPresContext, data);
  1607. }
  1608. }
  1609. }
  1610. }
  1611. void
  1612. nsRuleNode::ConvertChildrenToHash(int32_t aNumKids)
  1613. {
  1614. NS_ASSERTION(!ChildrenAreHashed() && HaveChildren(),
  1615. "must have a non-empty list of children");
  1616. PLDHashTable *hash = new PLDHashTable(&ChildrenHashOps,
  1617. sizeof(ChildrenHashEntry),
  1618. aNumKids);
  1619. for (nsRuleNode* curr = ChildrenList(); curr; curr = curr->mNextSibling) {
  1620. Key key = curr->GetKey();
  1621. // This will never fail because of the initial size we gave the table.
  1622. auto entry =
  1623. static_cast<ChildrenHashEntry*>(hash->Add(&key));
  1624. NS_ASSERTION(!entry->mRuleNode, "duplicate entries in list");
  1625. entry->mRuleNode = curr;
  1626. }
  1627. SetChildrenHash(hash);
  1628. }
  1629. void
  1630. nsRuleNode::RemoveChild(nsRuleNode* aNode)
  1631. {
  1632. MOZ_ASSERT(HaveChildren());
  1633. if (ChildrenAreHashed()) {
  1634. PLDHashTable* children = ChildrenHash();
  1635. Key key = aNode->GetKey();
  1636. MOZ_ASSERT(children->Search(&key));
  1637. children->Remove(&key);
  1638. if (children->EntryCount() == 0) {
  1639. delete children;
  1640. mChildren.asVoid = nullptr;
  1641. }
  1642. } else {
  1643. // This linear traversal is unfortunate, but we do the same thing when
  1644. // adding nodes. The traversal is bounded by kMaxChildrenInList.
  1645. nsRuleNode** curr = &mChildren.asList;
  1646. while (*curr != aNode) {
  1647. curr = &((*curr)->mNextSibling);
  1648. MOZ_ASSERT(*curr);
  1649. }
  1650. *curr = (*curr)->mNextSibling;
  1651. // If there was one element in the list, this sets mChildren.asList
  1652. // to 0, and HaveChildren() will return false.
  1653. }
  1654. }
  1655. inline void
  1656. nsRuleNode::PropagateNoneBit(uint32_t aBit, nsRuleNode* aHighestNode)
  1657. {
  1658. nsRuleNode* curr = this;
  1659. for (;;) {
  1660. NS_ASSERTION(!(curr->mNoneBits & aBit), "propagating too far");
  1661. curr->mNoneBits |= aBit;
  1662. if (curr == aHighestNode)
  1663. break;
  1664. curr = curr->mParent;
  1665. }
  1666. }
  1667. inline void
  1668. nsRuleNode::PropagateDependentBit(nsStyleStructID aSID, nsRuleNode* aHighestNode,
  1669. void* aStruct)
  1670. {
  1671. NS_ASSERTION(aStruct, "expected struct");
  1672. uint32_t bit = nsCachedStyleData::GetBitForSID(aSID);
  1673. for (nsRuleNode* curr = this; curr != aHighestNode; curr = curr->mParent) {
  1674. if (curr->mDependentBits & bit) {
  1675. #ifdef DEBUG
  1676. while (curr != aHighestNode) {
  1677. NS_ASSERTION(curr->mDependentBits & bit, "bit not set");
  1678. curr = curr->mParent;
  1679. }
  1680. #endif
  1681. break;
  1682. }
  1683. curr->mDependentBits |= bit;
  1684. if (curr->IsUsedDirectly()) {
  1685. curr->mStyleData.SetStyleData(aSID, mPresContext, aStruct);
  1686. }
  1687. }
  1688. }
  1689. /* static */ void
  1690. nsRuleNode::PropagateGrandancestorBit(nsStyleContext* aContext,
  1691. nsStyleContext* aContextInheritedFrom)
  1692. {
  1693. MOZ_ASSERT(aContext);
  1694. MOZ_ASSERT(aContextInheritedFrom &&
  1695. aContextInheritedFrom != aContext,
  1696. "aContextInheritedFrom must be an ancestor of aContext");
  1697. for (nsStyleContext* context = aContext->GetParent();
  1698. context != aContextInheritedFrom;
  1699. context = context->GetParent()) {
  1700. if (!context) {
  1701. MOZ_ASSERT(false, "aContextInheritedFrom must be an ancestor of "
  1702. "aContext's parent");
  1703. break;
  1704. }
  1705. context->AddStyleBit(NS_STYLE_CHILD_USES_GRANDANCESTOR_STYLE);
  1706. }
  1707. }
  1708. /*
  1709. * The following "Check" functions are used for determining what type of
  1710. * sharing can be used for the data on this rule node. MORE HERE...
  1711. */
  1712. /*
  1713. * a callback function that that can revise the result of
  1714. * CheckSpecifiedProperties before finishing; aResult is the current
  1715. * result, and it returns the revised one.
  1716. */
  1717. typedef nsRuleNode::RuleDetail
  1718. (* CheckCallbackFn)(const nsRuleData* aRuleData,
  1719. nsRuleNode::RuleDetail aResult);
  1720. /**
  1721. * @param aValue the value being examined
  1722. * @param aSpecifiedCount to be incremented by one if the value is specified
  1723. * @param aInheritedCount to be incremented by one if the value is set to inherit
  1724. * @param aUnsetCount to be incremented by one if the value is set to unset
  1725. */
  1726. inline void
  1727. ExamineCSSValue(const nsCSSValue& aValue,
  1728. uint32_t& aSpecifiedCount,
  1729. uint32_t& aInheritedCount,
  1730. uint32_t& aUnsetCount)
  1731. {
  1732. if (aValue.GetUnit() != eCSSUnit_Null) {
  1733. ++aSpecifiedCount;
  1734. if (aValue.GetUnit() == eCSSUnit_Inherit) {
  1735. ++aInheritedCount;
  1736. } else if (aValue.GetUnit() == eCSSUnit_Unset) {
  1737. ++aUnsetCount;
  1738. }
  1739. }
  1740. }
  1741. static nsRuleNode::RuleDetail
  1742. CheckFontCallback(const nsRuleData* aRuleData,
  1743. nsRuleNode::RuleDetail aResult)
  1744. {
  1745. // em, ex, percent, 'larger', and 'smaller' values on font-size depend
  1746. // on the parent context's font-size
  1747. // Likewise, 'lighter' and 'bolder' values of 'font-weight', and 'wider'
  1748. // and 'narrower' values of 'font-stretch' depend on the parent.
  1749. const nsCSSValue& size = *aRuleData->ValueForFontSize();
  1750. const nsCSSValue& weight = *aRuleData->ValueForFontWeight();
  1751. if ((size.IsRelativeLengthUnit() && size.GetUnit() != eCSSUnit_RootEM) ||
  1752. size.GetUnit() == eCSSUnit_Percent ||
  1753. (size.GetUnit() == eCSSUnit_Enumerated &&
  1754. (size.GetIntValue() == NS_STYLE_FONT_SIZE_SMALLER ||
  1755. size.GetIntValue() == NS_STYLE_FONT_SIZE_LARGER)) ||
  1756. aRuleData->ValueForScriptLevel()->GetUnit() == eCSSUnit_Integer ||
  1757. (weight.GetUnit() == eCSSUnit_Enumerated &&
  1758. (weight.GetIntValue() == NS_STYLE_FONT_WEIGHT_BOLDER ||
  1759. weight.GetIntValue() == NS_STYLE_FONT_WEIGHT_LIGHTER))) {
  1760. NS_ASSERTION(aResult == nsRuleNode::eRulePartialReset ||
  1761. aResult == nsRuleNode::eRuleFullReset ||
  1762. aResult == nsRuleNode::eRulePartialMixed ||
  1763. aResult == nsRuleNode::eRuleFullMixed,
  1764. "we know we already have a reset-counted property");
  1765. // Promote reset to mixed since we have something that depends on
  1766. // the parent. But never promote to inherited since that could
  1767. // cause inheritance of the exact value.
  1768. if (aResult == nsRuleNode::eRulePartialReset) {
  1769. aResult = nsRuleNode::eRulePartialMixed;
  1770. } else if (aResult == nsRuleNode::eRuleFullReset) {
  1771. aResult = nsRuleNode::eRuleFullMixed;
  1772. }
  1773. }
  1774. return aResult;
  1775. }
  1776. static nsRuleNode::RuleDetail
  1777. CheckColorCallback(const nsRuleData* aRuleData,
  1778. nsRuleNode::RuleDetail aResult)
  1779. {
  1780. // currentColor values for color require inheritance
  1781. const nsCSSValue* colorValue = aRuleData->ValueForColor();
  1782. if (colorValue->GetUnit() == eCSSUnit_EnumColor &&
  1783. colorValue->GetIntValue() == NS_COLOR_CURRENTCOLOR) {
  1784. NS_ASSERTION(aResult == nsRuleNode::eRuleFullReset,
  1785. "we should already be counted as full-reset");
  1786. aResult = nsRuleNode::eRuleFullInherited;
  1787. }
  1788. return aResult;
  1789. }
  1790. static nsRuleNode::RuleDetail
  1791. CheckTextCallback(const nsRuleData* aRuleData,
  1792. nsRuleNode::RuleDetail aResult)
  1793. {
  1794. const nsCSSValue* textAlignValue = aRuleData->ValueForTextAlign();
  1795. if (textAlignValue->GetUnit() == eCSSUnit_Enumerated &&
  1796. (textAlignValue->GetIntValue() ==
  1797. NS_STYLE_TEXT_ALIGN_MOZ_CENTER_OR_INHERIT ||
  1798. textAlignValue->GetIntValue() == NS_STYLE_TEXT_ALIGN_MATCH_PARENT)) {
  1799. // Promote reset to mixed since we have something that depends on
  1800. // the parent.
  1801. if (aResult == nsRuleNode::eRulePartialReset) {
  1802. aResult = nsRuleNode::eRulePartialMixed;
  1803. } else if (aResult == nsRuleNode::eRuleFullReset) {
  1804. aResult = nsRuleNode::eRuleFullMixed;
  1805. }
  1806. }
  1807. return aResult;
  1808. }
  1809. static nsRuleNode::RuleDetail
  1810. CheckVariablesCallback(const nsRuleData* aRuleData,
  1811. nsRuleNode::RuleDetail aResult)
  1812. {
  1813. // We don't actually have any properties on nsStyleVariables, so we do
  1814. // all of the RuleDetail calculation in here.
  1815. if (aRuleData->mVariables) {
  1816. return nsRuleNode::eRulePartialMixed;
  1817. }
  1818. return nsRuleNode::eRuleNone;
  1819. }
  1820. #define FLAG_DATA_FOR_PROPERTY(name_, id_, method_, flags_, pref_, \
  1821. parsevariant_, kwtable_, stylestructoffset_, \
  1822. animtype_) \
  1823. flags_,
  1824. // The order here must match the enums in *CheckCounter in nsCSSProps.cpp.
  1825. static const uint32_t gFontFlags[] = {
  1826. #define CSS_PROP_FONT FLAG_DATA_FOR_PROPERTY
  1827. #include "nsCSSPropList.h"
  1828. #undef CSS_PROP_FONT
  1829. };
  1830. static const uint32_t gDisplayFlags[] = {
  1831. #define CSS_PROP_DISPLAY FLAG_DATA_FOR_PROPERTY
  1832. #include "nsCSSPropList.h"
  1833. #undef CSS_PROP_DISPLAY
  1834. };
  1835. static const uint32_t gVisibilityFlags[] = {
  1836. #define CSS_PROP_VISIBILITY FLAG_DATA_FOR_PROPERTY
  1837. #include "nsCSSPropList.h"
  1838. #undef CSS_PROP_VISIBILITY
  1839. };
  1840. static const uint32_t gMarginFlags[] = {
  1841. #define CSS_PROP_MARGIN FLAG_DATA_FOR_PROPERTY
  1842. #include "nsCSSPropList.h"
  1843. #undef CSS_PROP_MARGIN
  1844. };
  1845. static const uint32_t gBorderFlags[] = {
  1846. #define CSS_PROP_BORDER FLAG_DATA_FOR_PROPERTY
  1847. #include "nsCSSPropList.h"
  1848. #undef CSS_PROP_BORDER
  1849. };
  1850. static const uint32_t gPaddingFlags[] = {
  1851. #define CSS_PROP_PADDING FLAG_DATA_FOR_PROPERTY
  1852. #include "nsCSSPropList.h"
  1853. #undef CSS_PROP_PADDING
  1854. };
  1855. static const uint32_t gOutlineFlags[] = {
  1856. #define CSS_PROP_OUTLINE FLAG_DATA_FOR_PROPERTY
  1857. #include "nsCSSPropList.h"
  1858. #undef CSS_PROP_OUTLINE
  1859. };
  1860. static const uint32_t gListFlags[] = {
  1861. #define CSS_PROP_LIST FLAG_DATA_FOR_PROPERTY
  1862. #include "nsCSSPropList.h"
  1863. #undef CSS_PROP_LIST
  1864. };
  1865. static const uint32_t gColorFlags[] = {
  1866. #define CSS_PROP_COLOR FLAG_DATA_FOR_PROPERTY
  1867. #include "nsCSSPropList.h"
  1868. #undef CSS_PROP_COLOR
  1869. };
  1870. static const uint32_t gBackgroundFlags[] = {
  1871. #define CSS_PROP_BACKGROUND FLAG_DATA_FOR_PROPERTY
  1872. #include "nsCSSPropList.h"
  1873. #undef CSS_PROP_BACKGROUND
  1874. };
  1875. static const uint32_t gPositionFlags[] = {
  1876. #define CSS_PROP_POSITION FLAG_DATA_FOR_PROPERTY
  1877. #include "nsCSSPropList.h"
  1878. #undef CSS_PROP_POSITION
  1879. };
  1880. static const uint32_t gTableFlags[] = {
  1881. #define CSS_PROP_TABLE FLAG_DATA_FOR_PROPERTY
  1882. #include "nsCSSPropList.h"
  1883. #undef CSS_PROP_TABLE
  1884. };
  1885. static const uint32_t gTableBorderFlags[] = {
  1886. #define CSS_PROP_TABLEBORDER FLAG_DATA_FOR_PROPERTY
  1887. #include "nsCSSPropList.h"
  1888. #undef CSS_PROP_TABLEBORDER
  1889. };
  1890. static const uint32_t gContentFlags[] = {
  1891. #define CSS_PROP_CONTENT FLAG_DATA_FOR_PROPERTY
  1892. #include "nsCSSPropList.h"
  1893. #undef CSS_PROP_CONTENT
  1894. };
  1895. static const uint32_t gTextFlags[] = {
  1896. #define CSS_PROP_TEXT FLAG_DATA_FOR_PROPERTY
  1897. #include "nsCSSPropList.h"
  1898. #undef CSS_PROP_TEXT
  1899. };
  1900. static const uint32_t gTextResetFlags[] = {
  1901. #define CSS_PROP_TEXTRESET FLAG_DATA_FOR_PROPERTY
  1902. #include "nsCSSPropList.h"
  1903. #undef CSS_PROP_TEXTRESET
  1904. };
  1905. static const uint32_t gUserInterfaceFlags[] = {
  1906. #define CSS_PROP_USERINTERFACE FLAG_DATA_FOR_PROPERTY
  1907. #include "nsCSSPropList.h"
  1908. #undef CSS_PROP_USERINTERFACE
  1909. };
  1910. static const uint32_t gUIResetFlags[] = {
  1911. #define CSS_PROP_UIRESET FLAG_DATA_FOR_PROPERTY
  1912. #include "nsCSSPropList.h"
  1913. #undef CSS_PROP_UIRESET
  1914. };
  1915. static const uint32_t gXULFlags[] = {
  1916. #define CSS_PROP_XUL FLAG_DATA_FOR_PROPERTY
  1917. #include "nsCSSPropList.h"
  1918. #undef CSS_PROP_XUL
  1919. };
  1920. static const uint32_t gSVGFlags[] = {
  1921. #define CSS_PROP_SVG FLAG_DATA_FOR_PROPERTY
  1922. #include "nsCSSPropList.h"
  1923. #undef CSS_PROP_SVG
  1924. };
  1925. static const uint32_t gSVGResetFlags[] = {
  1926. #define CSS_PROP_SVGRESET FLAG_DATA_FOR_PROPERTY
  1927. #include "nsCSSPropList.h"
  1928. #undef CSS_PROP_SVGRESET
  1929. };
  1930. static const uint32_t gColumnFlags[] = {
  1931. #define CSS_PROP_COLUMN FLAG_DATA_FOR_PROPERTY
  1932. #include "nsCSSPropList.h"
  1933. #undef CSS_PROP_COLUMN
  1934. };
  1935. // There are no properties in nsStyleVariables, but we can't have a
  1936. // zero length array.
  1937. static const uint32_t gVariablesFlags[] = {
  1938. 0,
  1939. #define CSS_PROP_VARIABLES FLAG_DATA_FOR_PROPERTY
  1940. #include "nsCSSPropList.h"
  1941. #undef CSS_PROP_VARIABLES
  1942. };
  1943. static_assert(sizeof(gVariablesFlags) == sizeof(uint32_t),
  1944. "if nsStyleVariables has properties now you can remove the dummy "
  1945. "gVariablesFlags entry");
  1946. static const uint32_t gEffectsFlags[] = {
  1947. #define CSS_PROP_EFFECTS FLAG_DATA_FOR_PROPERTY
  1948. #include "nsCSSPropList.h"
  1949. #undef CSS_PROP_EFFECTS
  1950. };
  1951. #undef FLAG_DATA_FOR_PROPERTY
  1952. static const uint32_t* gFlagsByStruct[] = {
  1953. #define STYLE_STRUCT(name, checkdata_cb) \
  1954. g##name##Flags,
  1955. #include "nsStyleStructList.h"
  1956. #undef STYLE_STRUCT
  1957. };
  1958. static const CheckCallbackFn gCheckCallbacks[] = {
  1959. #define STYLE_STRUCT(name, checkdata_cb) \
  1960. checkdata_cb,
  1961. #include "nsStyleStructList.h"
  1962. #undef STYLE_STRUCT
  1963. };
  1964. #ifdef DEBUG
  1965. static bool
  1966. AreAllMathMLPropertiesUndefined(const nsRuleData* aRuleData)
  1967. {
  1968. return
  1969. aRuleData->ValueForScriptLevel()->GetUnit() == eCSSUnit_Null &&
  1970. aRuleData->ValueForScriptSizeMultiplier()->GetUnit() == eCSSUnit_Null &&
  1971. aRuleData->ValueForScriptMinSize()->GetUnit() == eCSSUnit_Null &&
  1972. aRuleData->ValueForMathVariant()->GetUnit() == eCSSUnit_Null &&
  1973. aRuleData->ValueForMathDisplay()->GetUnit() == eCSSUnit_Null;
  1974. }
  1975. #endif
  1976. inline nsRuleNode::RuleDetail
  1977. nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID,
  1978. const nsRuleData* aRuleData)
  1979. {
  1980. // Build a count of the:
  1981. uint32_t total = 0, // total number of props in the struct
  1982. specified = 0, // number that were specified for this node
  1983. inherited = 0, // number that were 'inherit' (and not
  1984. // eCSSUnit_Inherit) for this node
  1985. unset = 0; // number that were 'unset'
  1986. // See comment in nsRuleData.h above mValueOffsets.
  1987. MOZ_ASSERT(aRuleData->mValueOffsets[aSID] == 0,
  1988. "we assume the value offset is zero instead of adding it");
  1989. for (nsCSSValue *values = aRuleData->mValueStorage,
  1990. *values_end = values + nsCSSProps::PropertyCountInStruct(aSID);
  1991. values != values_end; ++values) {
  1992. ++total;
  1993. ExamineCSSValue(*values, specified, inherited, unset);
  1994. }
  1995. if (!nsCachedStyleData::IsReset(aSID)) {
  1996. // For inherited properties, 'unset' means the same as 'inherit'.
  1997. inherited += unset;
  1998. unset = 0;
  1999. }
  2000. #if 0
  2001. printf("CheckSpecifiedProperties: SID=%d total=%d spec=%d inh=%d.\n",
  2002. aSID, total, specified, inherited);
  2003. #endif
  2004. NS_ASSERTION(aSID != eStyleStruct_Font ||
  2005. mPresContext->Document()->GetMathMLEnabled() ||
  2006. AreAllMathMLPropertiesUndefined(aRuleData),
  2007. "MathML style property was defined even though MathML is disabled");
  2008. /*
  2009. * Return the most specific information we can: prefer None or Full
  2010. * over Partial, and Reset or Inherited over Mixed, since we can
  2011. * optimize based on the edge cases and not the in-between cases.
  2012. */
  2013. nsRuleNode::RuleDetail result;
  2014. if (inherited == total) {
  2015. result = eRuleFullInherited;
  2016. } else if (specified == total
  2017. // MathML defines 5 properties in Font that will never be set when
  2018. // MathML is not in use. Therefore if all but five
  2019. // properties have been set, and MathML is not enabled, we can treat
  2020. // this as fully specified. Code in nsMathMLElementFactory will
  2021. // rebuild the rule tree and style data when MathML is first enabled
  2022. // (see nsMathMLElement::BindToTree).
  2023. || (aSID == eStyleStruct_Font && specified + 5 == total &&
  2024. !mPresContext->Document()->GetMathMLEnabled())
  2025. ) {
  2026. if (inherited == 0) {
  2027. result = eRuleFullReset;
  2028. } else {
  2029. result = eRuleFullMixed;
  2030. }
  2031. } else if (specified == 0) {
  2032. result = eRuleNone;
  2033. } else if (specified == inherited) {
  2034. result = eRulePartialInherited;
  2035. } else if (inherited == 0) {
  2036. result = eRulePartialReset;
  2037. } else {
  2038. result = eRulePartialMixed;
  2039. }
  2040. CheckCallbackFn cb = gCheckCallbacks[aSID];
  2041. if (cb) {
  2042. result = (*cb)(aRuleData, result);
  2043. }
  2044. return result;
  2045. }
  2046. // If we need to restrict which properties apply to the style context,
  2047. // return the bit to check in nsCSSProp's flags table. Otherwise,
  2048. // return 0.
  2049. inline uint32_t
  2050. GetPseudoRestriction(nsStyleContext *aContext)
  2051. {
  2052. // This needs to match nsStyleSet::WalkRestrictionRule.
  2053. uint32_t pseudoRestriction = 0;
  2054. nsIAtom *pseudoType = aContext->GetPseudo();
  2055. if (pseudoType) {
  2056. if (pseudoType == nsCSSPseudoElements::firstLetter) {
  2057. pseudoRestriction = CSS_PROPERTY_APPLIES_TO_FIRST_LETTER;
  2058. } else if (pseudoType == nsCSSPseudoElements::firstLine) {
  2059. pseudoRestriction = CSS_PROPERTY_APPLIES_TO_FIRST_LINE;
  2060. } else if (pseudoType == nsCSSPseudoElements::placeholder) {
  2061. pseudoRestriction = CSS_PROPERTY_APPLIES_TO_PLACEHOLDER;
  2062. }
  2063. }
  2064. return pseudoRestriction;
  2065. }
  2066. static void
  2067. UnsetPropertiesWithoutFlags(const nsStyleStructID aSID,
  2068. nsRuleData* aRuleData,
  2069. uint32_t aFlags)
  2070. {
  2071. NS_ASSERTION(aFlags != 0, "aFlags must be nonzero");
  2072. const uint32_t *flagData = gFlagsByStruct[aSID];
  2073. // See comment in nsRuleData.h above mValueOffsets.
  2074. MOZ_ASSERT(aRuleData->mValueOffsets[aSID] == 0,
  2075. "we assume the value offset is zero instead of adding it");
  2076. nsCSSValue *values = aRuleData->mValueStorage;
  2077. for (size_t i = 0, i_end = nsCSSProps::PropertyCountInStruct(aSID);
  2078. i != i_end; ++i) {
  2079. if ((flagData[i] & aFlags) != aFlags) {
  2080. values[i].Reset();
  2081. }
  2082. }
  2083. }
  2084. /**
  2085. * We allocate arrays of CSS values with alloca. (These arrays are a
  2086. * fixed size per style struct, but we don't want to waste the
  2087. * allocation and construction/destruction costs of the big structs when
  2088. * we're handling much smaller ones.) Since the lifetime of an alloca
  2089. * allocation is the life of the calling function, the caller must call
  2090. * alloca. However, to ensure that constructors and destructors are
  2091. * balanced, we do the constructor and destructor calling from this RAII
  2092. * class, AutoCSSValueArray.
  2093. */
  2094. struct AutoCSSValueArray {
  2095. /**
  2096. * aStorage must be the result of alloca(aCount * sizeof(nsCSSValue))
  2097. */
  2098. AutoCSSValueArray(void* aStorage, size_t aCount) {
  2099. MOZ_ASSERT(size_t(aStorage) % NS_ALIGNMENT_OF(nsCSSValue) == 0,
  2100. "bad alignment from alloca");
  2101. mCount = aCount;
  2102. // Don't use placement new[], since it might store extra data
  2103. // for the count (on Windows!).
  2104. mArray = static_cast<nsCSSValue*>(aStorage);
  2105. for (size_t i = 0; i < mCount; ++i) {
  2106. new (KnownNotNull, mArray + i) nsCSSValue();
  2107. }
  2108. }
  2109. ~AutoCSSValueArray() {
  2110. for (size_t i = 0; i < mCount; ++i) {
  2111. mArray[i].~nsCSSValue();
  2112. }
  2113. }
  2114. nsCSSValue* get() { return mArray; }
  2115. private:
  2116. nsCSSValue *mArray;
  2117. size_t mCount;
  2118. };
  2119. /* static */ bool
  2120. nsRuleNode::ResolveVariableReferences(const nsStyleStructID aSID,
  2121. nsRuleData* aRuleData,
  2122. nsStyleContext* aContext)
  2123. {
  2124. MOZ_ASSERT(aSID != eStyleStruct_Variables);
  2125. MOZ_ASSERT(aRuleData->mSIDs & nsCachedStyleData::GetBitForSID(aSID));
  2126. MOZ_ASSERT(aRuleData->mValueOffsets[aSID] == 0);
  2127. nsCSSParser parser;
  2128. bool anyTokenStreams = false;
  2129. // Look at each property in the nsRuleData for the given style struct.
  2130. size_t nprops = nsCSSProps::PropertyCountInStruct(aSID);
  2131. for (nsCSSValue* value = aRuleData->mValueStorage,
  2132. *values_end = aRuleData->mValueStorage + nprops;
  2133. value != values_end; value++) {
  2134. if (value->GetUnit() != eCSSUnit_TokenStream) {
  2135. continue;
  2136. }
  2137. const CSSVariableValues* variables =
  2138. &aContext->StyleVariables()->mVariables;
  2139. nsCSSValueTokenStream* tokenStream = value->GetTokenStreamValue();
  2140. MOZ_ASSERT(tokenStream->mLevel != SheetType::Count,
  2141. "Token stream should have a defined level");
  2142. AutoRestore<SheetType> saveLevel(aRuleData->mLevel);
  2143. aRuleData->mLevel = tokenStream->mLevel;
  2144. // Note that ParsePropertyWithVariableReferences relies on the fact
  2145. // that the nsCSSValue in aRuleData for the property we are re-parsing
  2146. // is still the token stream value. When
  2147. // ParsePropertyWithVariableReferences calls
  2148. // nsCSSExpandedDataBlock::MapRuleInfoInto, that function will add
  2149. // the ImageValue that is created into the token stream object's
  2150. // mImageValues table; see the comment above mImageValues for why.
  2151. // XXX Should pass in sheet here (see bug 952338).
  2152. parser.ParsePropertyWithVariableReferences(
  2153. tokenStream->mPropertyID, tokenStream->mShorthandPropertyID,
  2154. tokenStream->mTokenStream, variables, aRuleData,
  2155. tokenStream->mSheetURI, tokenStream->mBaseURI,
  2156. tokenStream->mSheetPrincipal, nullptr,
  2157. tokenStream->mLineNumber, tokenStream->mLineOffset);
  2158. aRuleData->mConditions.SetUncacheable();
  2159. anyTokenStreams = true;
  2160. }
  2161. return anyTokenStreams;
  2162. }
  2163. const void*
  2164. nsRuleNode::WalkRuleTree(const nsStyleStructID aSID,
  2165. nsStyleContext* aContext)
  2166. {
  2167. // use placement new[] on the result of alloca() to allocate a
  2168. // variable-sized stack array, including execution of constructors,
  2169. // and use an RAII class to run the destructors too.
  2170. size_t nprops = nsCSSProps::PropertyCountInStruct(aSID);
  2171. void* dataStorage = alloca(nprops * sizeof(nsCSSValue));
  2172. AutoCSSValueArray dataArray(dataStorage, nprops);
  2173. nsRuleData ruleData(nsCachedStyleData::GetBitForSID(aSID),
  2174. dataArray.get(), mPresContext, aContext);
  2175. ruleData.mValueOffsets[aSID] = 0;
  2176. // We start at the most specific rule in the tree.
  2177. void* startStruct = nullptr;
  2178. nsRuleNode* ruleNode = this;
  2179. nsRuleNode* highestNode = nullptr; // The highest node in the rule tree
  2180. // that has the same properties
  2181. // specified for struct |aSID| as
  2182. // |this| does.
  2183. nsRuleNode* rootNode = this; // After the loop below, this will be the
  2184. // highest node that we've walked without
  2185. // finding cached data on the rule tree.
  2186. // If we don't find any cached data, it
  2187. // will be the root. (XXX misnamed)
  2188. RuleDetail detail = eRuleNone;
  2189. uint32_t bit = nsCachedStyleData::GetBitForSID(aSID);
  2190. while (ruleNode) {
  2191. // See if this rule node has cached the fact that the remaining
  2192. // nodes along this path specify no data whatsoever.
  2193. if (ruleNode->mNoneBits & bit) {
  2194. break;
  2195. }
  2196. // If the dependent bit is set on a rule node for this struct, that
  2197. // means its rule won't have any information to add, so skip it.
  2198. // NOTE: If we exit the loop because of the !IsUsedDirectly() check,
  2199. // then we're guaranteed to break immediately afterwards due to a
  2200. // non-null startStruct.
  2201. while ((ruleNode->mDependentBits & bit) && !ruleNode->IsUsedDirectly()) {
  2202. NS_ASSERTION(ruleNode->mStyleData.GetStyleData(aSID) == nullptr,
  2203. "dependent bit with cached data makes no sense");
  2204. // Climb up to the next rule in the tree (a less specific rule).
  2205. rootNode = ruleNode;
  2206. ruleNode = ruleNode->mParent;
  2207. NS_ASSERTION(!(ruleNode->mNoneBits & bit), "can't have both bits set");
  2208. }
  2209. // Check for cached data after the inner loop above -- otherwise
  2210. // we'll miss it.
  2211. startStruct = ruleNode->mStyleData.GetStyleData(aSID);
  2212. if (startStruct) {
  2213. break; // We found a rule with fully specified data. We don't
  2214. } // need to go up the tree any further, since the remainder
  2215. // of this branch has already been computed.
  2216. // Ask the rule to fill in the properties that it specifies.
  2217. nsIStyleRule *rule = ruleNode->mRule;
  2218. if (rule) {
  2219. ruleData.mLevel = ruleNode->GetLevel();
  2220. ruleData.mIsImportantRule = ruleNode->IsImportantRule();
  2221. rule->MapRuleInfoInto(&ruleData);
  2222. }
  2223. // Now we check to see how many properties have been specified by
  2224. // the rules we've examined so far.
  2225. RuleDetail oldDetail = detail;
  2226. detail = CheckSpecifiedProperties(aSID, &ruleData);
  2227. if (oldDetail == eRuleNone && detail != eRuleNone) {
  2228. highestNode = ruleNode;
  2229. }
  2230. if (detail == eRuleFullReset ||
  2231. detail == eRuleFullMixed ||
  2232. detail == eRuleFullInherited) {
  2233. break; // We don't need to examine any more rules. All properties
  2234. } // have been fully specified.
  2235. // Climb up to the next rule in the tree (a less specific rule).
  2236. rootNode = ruleNode;
  2237. ruleNode = ruleNode->mParent;
  2238. }
  2239. bool recomputeDetail = false;
  2240. // If we are computing a style struct other than nsStyleVariables, and
  2241. // ruleData has any properties with variable references (nsCSSValues of
  2242. // type eCSSUnit_TokenStream), then we need to resolve these.
  2243. if (aSID != eStyleStruct_Variables) {
  2244. // A property's value might have became 'inherit' after resolving
  2245. // variable references. (This happens when an inherited property
  2246. // fails to parse its resolved value.) We need to recompute
  2247. // |detail| in case this happened.
  2248. recomputeDetail = ResolveVariableReferences(aSID, &ruleData, aContext);
  2249. }
  2250. // If needed, unset the properties that don't have a flag that allows
  2251. // them to be set for this style context. (For example, only some
  2252. // properties apply to :first-line and :first-letter.)
  2253. uint32_t pseudoRestriction = GetPseudoRestriction(aContext);
  2254. if (pseudoRestriction) {
  2255. UnsetPropertiesWithoutFlags(aSID, &ruleData, pseudoRestriction);
  2256. // We need to recompute |detail| based on the restrictions we just applied.
  2257. // We can adjust |detail| arbitrarily because of the restriction
  2258. // rule added in nsStyleSet::WalkRestrictionRule.
  2259. recomputeDetail = true;
  2260. }
  2261. if (recomputeDetail) {
  2262. detail = CheckSpecifiedProperties(aSID, &ruleData);
  2263. }
  2264. NS_ASSERTION(!startStruct || (detail != eRuleFullReset &&
  2265. detail != eRuleFullMixed &&
  2266. detail != eRuleFullInherited),
  2267. "can't have start struct and be fully specified");
  2268. bool isReset = nsCachedStyleData::IsReset(aSID);
  2269. if (!highestNode) {
  2270. highestNode = rootNode;
  2271. }
  2272. MOZ_ASSERT(!(aSID == eStyleStruct_Variables && startStruct),
  2273. "if we start caching Variables structs in the rule tree, then "
  2274. "not forcing detail to eRulePartialMixed just below is no "
  2275. "longer valid");
  2276. if (detail == eRuleNone && isReset) {
  2277. // We specified absolutely no rule information for a reset struct, and we
  2278. // may or may not have found a parent rule in the tree that specified all
  2279. // the rule information. Regardless, we don't need to use any cache
  2280. // conditions if we cache this struct in the rule tree.
  2281. //
  2282. // Normally ruleData.mConditions would already indicate that the struct
  2283. // is cacheable without conditions if detail is eRuleNone, but because
  2284. // of the UnsetPropertiesWithoutFlags call above, we may have encountered
  2285. // some rules with dependencies, which we then cleared out of ruleData.
  2286. //
  2287. // ruleData.mConditions could also indicate we are not cacheable at all,
  2288. // such as when AnimValuesStyleRule prevents us from caching structs
  2289. // when attempting to apply animations to pseudos.
  2290. //
  2291. // So if we we are uncacheable, we leave it, but if we are cacheable
  2292. // with dependencies, we convert that to cacheable without dependencies.
  2293. if (ruleData.mConditions.CacheableWithDependencies()) {
  2294. MOZ_ASSERT(pseudoRestriction,
  2295. "should only be cacheable with dependencies if we had a "
  2296. "pseudo restriction");
  2297. ruleData.mConditions.Clear();
  2298. } else {
  2299. // XXXheycam We shouldn't have `|| GetLevel() == SheetType::Transition`
  2300. // in the assertion condition, but rule nodes created by
  2301. // ResolveStyleByAddingRules don't call SetIsAnimationRule().
  2302. MOZ_ASSERT(ruleData.mConditions.CacheableWithoutDependencies() ||
  2303. ((HasAnimationData() ||
  2304. GetLevel() == SheetType::Transition) &&
  2305. aContext->GetParent() &&
  2306. aContext->GetParent()->HasPseudoElementData()),
  2307. "should only be uncacheable if we had an animation rule "
  2308. "and we're inside a pseudo");
  2309. }
  2310. }
  2311. if (!ruleData.mConditions.CacheableWithoutDependencies() &&
  2312. aSID != eStyleStruct_Variables) {
  2313. // Treat as though some data is specified to avoid the optimizations and
  2314. // force data computation.
  2315. //
  2316. // We don't need to do this for Variables structs since we know those are
  2317. // never cached in the rule tree, and it avoids wasteful computation of a
  2318. // new Variables struct when we have no additional variable declarations,
  2319. // which otherwise could happen when there is an AnimValuesStyleRule
  2320. // (which calls SetUncacheable for style contexts with pseudo data).
  2321. detail = eRulePartialMixed;
  2322. }
  2323. if (detail == eRuleNone && startStruct) {
  2324. // We specified absolutely no rule information, but a parent rule in the tree
  2325. // specified all the rule information. We set a bit along the branch from our
  2326. // node in the tree to the node that specified the data that tells nodes on that
  2327. // branch that they never need to examine their rules for this particular struct type
  2328. // ever again.
  2329. PropagateDependentBit(aSID, ruleNode, startStruct);
  2330. // For inherited structs, mark the struct (which will be set on
  2331. // the context by our caller) as not being owned by the context.
  2332. if (!isReset) {
  2333. aContext->AddStyleBit(nsCachedStyleData::GetBitForSID(aSID));
  2334. } else if (HasAnimationData()) {
  2335. // If we have animation data, the struct should be cached on the style
  2336. // context so that we can peek the struct.
  2337. // See comment in AnimValuesStyleRule::MapRuleInfoInto.
  2338. StoreStyleOnContext(aContext, aSID, startStruct);
  2339. }
  2340. return startStruct;
  2341. }
  2342. if ((!startStruct && !isReset &&
  2343. (detail == eRuleNone || detail == eRulePartialInherited)) ||
  2344. detail == eRuleFullInherited) {
  2345. // We specified no non-inherited information and neither did any of
  2346. // our parent rules.
  2347. // We set a bit along the branch from the highest node (ruleNode)
  2348. // down to our node (this) indicating that no non-inherited data was
  2349. // specified. This bit is guaranteed to be set already on the path
  2350. // from the highest node to the root node in the case where
  2351. // (detail == eRuleNone), which is the most common case here.
  2352. // We must check |!isReset| because the Compute*Data functions for
  2353. // reset structs wouldn't handle none bits correctly.
  2354. if (highestNode != this && !isReset) {
  2355. PropagateNoneBit(bit, highestNode);
  2356. }
  2357. // All information must necessarily be inherited from our parent style context.
  2358. // In the absence of any computed data in the rule tree and with
  2359. // no rules specified that didn't have values of 'inherit', we should check our parent.
  2360. nsStyleContext* parentContext = aContext->GetParent();
  2361. if (isReset) {
  2362. /* Reset structs don't inherit from first-line. */
  2363. /* See similar code in COMPUTE_START_RESET */
  2364. while (parentContext &&
  2365. parentContext->GetPseudo() == nsCSSPseudoElements::firstLine) {
  2366. parentContext = parentContext->GetParent();
  2367. }
  2368. if (parentContext && parentContext != aContext->GetParent()) {
  2369. PropagateGrandancestorBit(aContext, parentContext);
  2370. }
  2371. }
  2372. if (parentContext) {
  2373. // We have a parent, and so we should just inherit from the parent.
  2374. // Set the inherit bits on our context. These bits tell the style context that
  2375. // it never has to go back to the rule tree for data. Instead the style context tree
  2376. // should be walked to find the data.
  2377. const void* parentStruct = parentContext->StyleData(aSID);
  2378. aContext->AddStyleBit(bit); // makes const_cast OK.
  2379. aContext->SetStyle(aSID, const_cast<void*>(parentStruct));
  2380. if (isReset) {
  2381. parentContext->AddStyleBit(NS_STYLE_HAS_CHILD_THAT_USES_RESET_STYLE);
  2382. }
  2383. return parentStruct;
  2384. }
  2385. else
  2386. // We are the root. In the case of fonts, the default values just
  2387. // come from the pres context.
  2388. return SetDefaultOnRoot(aSID, aContext);
  2389. }
  2390. typedef const void* (nsRuleNode::*ComputeFunc)(void*, const nsRuleData*,
  2391. nsStyleContext*, nsRuleNode*,
  2392. RuleDetail,
  2393. const RuleNodeCacheConditions);
  2394. static const ComputeFunc sComputeFuncs[] = {
  2395. #define STYLE_STRUCT(name, checkdata_cb) &nsRuleNode::Compute##name##Data,
  2396. #include "nsStyleStructList.h"
  2397. #undef STYLE_STRUCT
  2398. };
  2399. // We need to compute the data from the information that the rules specified.
  2400. return (this->*sComputeFuncs[aSID])(startStruct, &ruleData, aContext,
  2401. highestNode, detail,
  2402. ruleData.mConditions);
  2403. }
  2404. const void*
  2405. nsRuleNode::SetDefaultOnRoot(const nsStyleStructID aSID, nsStyleContext* aContext)
  2406. {
  2407. switch (aSID) {
  2408. case eStyleStruct_Font:
  2409. {
  2410. nsStyleFont* fontData = new (mPresContext) nsStyleFont(mPresContext);
  2411. nscoord minimumFontSize = mPresContext->MinFontSize(fontData->mLanguage);
  2412. if (minimumFontSize > 0 && !mPresContext->IsChrome()) {
  2413. fontData->mFont.size = std::max(fontData->mSize, minimumFontSize);
  2414. }
  2415. else {
  2416. fontData->mFont.size = fontData->mSize;
  2417. }
  2418. aContext->SetStyle(eStyleStruct_Font, fontData);
  2419. return fontData;
  2420. }
  2421. case eStyleStruct_Display:
  2422. {
  2423. nsStyleDisplay* disp = new (mPresContext) nsStyleDisplay(mPresContext);
  2424. aContext->SetStyle(eStyleStruct_Display, disp);
  2425. return disp;
  2426. }
  2427. case eStyleStruct_Visibility:
  2428. {
  2429. nsStyleVisibility* vis = new (mPresContext) nsStyleVisibility(mPresContext);
  2430. aContext->SetStyle(eStyleStruct_Visibility, vis);
  2431. return vis;
  2432. }
  2433. case eStyleStruct_Text:
  2434. {
  2435. nsStyleText* text = new (mPresContext) nsStyleText(mPresContext);
  2436. aContext->SetStyle(eStyleStruct_Text, text);
  2437. return text;
  2438. }
  2439. case eStyleStruct_TextReset:
  2440. {
  2441. nsStyleTextReset* text = new (mPresContext) nsStyleTextReset(mPresContext);
  2442. aContext->SetStyle(eStyleStruct_TextReset, text);
  2443. return text;
  2444. }
  2445. case eStyleStruct_Color:
  2446. {
  2447. nsStyleColor* color = new (mPresContext) nsStyleColor(mPresContext);
  2448. aContext->SetStyle(eStyleStruct_Color, color);
  2449. return color;
  2450. }
  2451. case eStyleStruct_Background:
  2452. {
  2453. nsStyleBackground* bg = new (mPresContext) nsStyleBackground(mPresContext);
  2454. aContext->SetStyle(eStyleStruct_Background, bg);
  2455. return bg;
  2456. }
  2457. case eStyleStruct_Margin:
  2458. {
  2459. nsStyleMargin* margin = new (mPresContext) nsStyleMargin(mPresContext);
  2460. aContext->SetStyle(eStyleStruct_Margin, margin);
  2461. return margin;
  2462. }
  2463. case eStyleStruct_Border:
  2464. {
  2465. nsStyleBorder* border = new (mPresContext) nsStyleBorder(mPresContext);
  2466. aContext->SetStyle(eStyleStruct_Border, border);
  2467. return border;
  2468. }
  2469. case eStyleStruct_Padding:
  2470. {
  2471. nsStylePadding* padding = new (mPresContext) nsStylePadding(mPresContext);
  2472. aContext->SetStyle(eStyleStruct_Padding, padding);
  2473. return padding;
  2474. }
  2475. case eStyleStruct_Outline:
  2476. {
  2477. nsStyleOutline* outline = new (mPresContext) nsStyleOutline(mPresContext);
  2478. aContext->SetStyle(eStyleStruct_Outline, outline);
  2479. return outline;
  2480. }
  2481. case eStyleStruct_List:
  2482. {
  2483. nsStyleList* list = new (mPresContext) nsStyleList(mPresContext);
  2484. aContext->SetStyle(eStyleStruct_List, list);
  2485. return list;
  2486. }
  2487. case eStyleStruct_Position:
  2488. {
  2489. nsStylePosition* pos = new (mPresContext) nsStylePosition(mPresContext);
  2490. aContext->SetStyle(eStyleStruct_Position, pos);
  2491. return pos;
  2492. }
  2493. case eStyleStruct_Table:
  2494. {
  2495. nsStyleTable* table = new (mPresContext) nsStyleTable(mPresContext);
  2496. aContext->SetStyle(eStyleStruct_Table, table);
  2497. return table;
  2498. }
  2499. case eStyleStruct_TableBorder:
  2500. {
  2501. nsStyleTableBorder* table = new (mPresContext) nsStyleTableBorder(mPresContext);
  2502. aContext->SetStyle(eStyleStruct_TableBorder, table);
  2503. return table;
  2504. }
  2505. case eStyleStruct_Content:
  2506. {
  2507. nsStyleContent* content = new (mPresContext) nsStyleContent(mPresContext);
  2508. aContext->SetStyle(eStyleStruct_Content, content);
  2509. return content;
  2510. }
  2511. case eStyleStruct_UserInterface:
  2512. {
  2513. nsStyleUserInterface* ui = new (mPresContext) nsStyleUserInterface(mPresContext);
  2514. aContext->SetStyle(eStyleStruct_UserInterface, ui);
  2515. return ui;
  2516. }
  2517. case eStyleStruct_UIReset:
  2518. {
  2519. nsStyleUIReset* ui = new (mPresContext) nsStyleUIReset(mPresContext);
  2520. aContext->SetStyle(eStyleStruct_UIReset, ui);
  2521. return ui;
  2522. }
  2523. case eStyleStruct_XUL:
  2524. {
  2525. nsStyleXUL* xul = new (mPresContext) nsStyleXUL(mPresContext);
  2526. aContext->SetStyle(eStyleStruct_XUL, xul);
  2527. return xul;
  2528. }
  2529. case eStyleStruct_Column:
  2530. {
  2531. nsStyleColumn* column = new (mPresContext) nsStyleColumn(mPresContext);
  2532. aContext->SetStyle(eStyleStruct_Column, column);
  2533. return column;
  2534. }
  2535. case eStyleStruct_SVG:
  2536. {
  2537. nsStyleSVG* svg = new (mPresContext) nsStyleSVG(mPresContext);
  2538. aContext->SetStyle(eStyleStruct_SVG, svg);
  2539. return svg;
  2540. }
  2541. case eStyleStruct_SVGReset:
  2542. {
  2543. nsStyleSVGReset* svgReset = new (mPresContext) nsStyleSVGReset(mPresContext);
  2544. aContext->SetStyle(eStyleStruct_SVGReset, svgReset);
  2545. return svgReset;
  2546. }
  2547. case eStyleStruct_Variables:
  2548. {
  2549. nsStyleVariables* vars = new (mPresContext) nsStyleVariables(mPresContext);
  2550. aContext->SetStyle(eStyleStruct_Variables, vars);
  2551. return vars;
  2552. }
  2553. case eStyleStruct_Effects:
  2554. {
  2555. nsStyleEffects* effects = new (mPresContext) nsStyleEffects(mPresContext);
  2556. aContext->SetStyle(eStyleStruct_Effects, effects);
  2557. return effects;
  2558. }
  2559. default:
  2560. /*
  2561. * unhandled case: nsStyleStructID_Length.
  2562. * last item of nsStyleStructID, to know its length.
  2563. */
  2564. MOZ_ASSERT(false, "unexpected SID");
  2565. return nullptr;
  2566. }
  2567. return nullptr;
  2568. }
  2569. /**
  2570. * Begin an nsRuleNode::Compute*Data function for an inherited struct.
  2571. *
  2572. * @param type_ The nsStyle* type this function computes.
  2573. * @param data_ Variable (declared here) holding the result of this
  2574. * function.
  2575. * @param parentdata_ Variable (declared here) holding the parent style
  2576. * context's data for this struct.
  2577. */
  2578. #define COMPUTE_START_INHERITED(type_, data_, parentdata_) \
  2579. NS_ASSERTION(aRuleDetail != eRuleFullInherited, \
  2580. "should not have bothered calling Compute*Data"); \
  2581. \
  2582. nsStyleContext* parentContext = aContext->GetParent(); \
  2583. \
  2584. nsStyle##type_* data_ = nullptr; \
  2585. mozilla::Maybe<nsStyle##type_> maybeFakeParentData; \
  2586. const nsStyle##type_* parentdata_ = nullptr; \
  2587. RuleNodeCacheConditions conditions = aConditions; \
  2588. \
  2589. /* If |conditions.Cacheable()| might be true by the time we're done, we */ \
  2590. /* can't call parentContext->Style##type_() since it could recur into */ \
  2591. /* setting the same struct on the same rule node, causing a leak. */ \
  2592. if (aRuleDetail != eRuleFullReset && \
  2593. (!aStartStruct || (aRuleDetail != eRulePartialReset && \
  2594. aRuleDetail != eRuleNone))) { \
  2595. if (parentContext) { \
  2596. parentdata_ = parentContext->Style##type_(); \
  2597. } else { \
  2598. maybeFakeParentData.emplace(mPresContext); \
  2599. parentdata_ = maybeFakeParentData.ptr(); \
  2600. } \
  2601. } \
  2602. if (eStyleStruct_##type_ == eStyleStruct_Variables) { \
  2603. /* no need to copy construct an nsStyleVariables, as we will copy */ \
  2604. /* inherited variables (and call SetUncacheable()) in */ \
  2605. /* ComputeVariablesData */ \
  2606. data_ = new (mPresContext) nsStyle##type_(mPresContext); \
  2607. } else if (aStartStruct) { \
  2608. /* We only need to compute the delta between this computed data and */ \
  2609. /* our computed data. */ \
  2610. data_ = new (mPresContext) \
  2611. nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct)); \
  2612. } else { \
  2613. if (aRuleDetail != eRuleFullMixed && aRuleDetail != eRuleFullReset) { \
  2614. /* No question. We will have to inherit. Go ahead and init */ \
  2615. /* with inherited vals from parent. */ \
  2616. conditions.SetUncacheable(); \
  2617. if (parentdata_) { \
  2618. data_ = new (mPresContext) nsStyle##type_(*parentdata_); \
  2619. } else { \
  2620. data_ = new (mPresContext) nsStyle##type_(mPresContext); \
  2621. } \
  2622. } else { \
  2623. data_ = new (mPresContext) nsStyle##type_(mPresContext); \
  2624. } \
  2625. } \
  2626. \
  2627. if (!parentdata_) { \
  2628. parentdata_ = data_; \
  2629. } \
  2630. /**
  2631. * Begin an nsRuleNode::Compute*Data function for a reset struct.
  2632. *
  2633. * @param type_ The nsStyle* type this function computes.
  2634. * @param data_ Variable (declared here) holding the result of this
  2635. * function.
  2636. * @param parentdata_ Variable (declared here) holding the parent style
  2637. * context's data for this struct.
  2638. */
  2639. #define COMPUTE_START_RESET(type_, data_, parentdata_) \
  2640. NS_ASSERTION(aRuleDetail != eRuleFullInherited, \
  2641. "should not have bothered calling Compute*Data"); \
  2642. \
  2643. nsStyleContext* parentContext = aContext->GetParent(); \
  2644. /* Reset structs don't inherit from first-line */ \
  2645. /* See similar code in WalkRuleTree */ \
  2646. while (parentContext && \
  2647. parentContext->GetPseudo() == nsCSSPseudoElements::firstLine) { \
  2648. parentContext = parentContext->GetParent(); \
  2649. } \
  2650. \
  2651. nsStyle##type_* data_; \
  2652. if (aStartStruct) { \
  2653. /* We only need to compute the delta between this computed data and */ \
  2654. /* our computed data. */ \
  2655. data_ = new (mPresContext) \
  2656. nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct)); \
  2657. } else { \
  2658. data_ = new (mPresContext) nsStyle##type_(mPresContext); \
  2659. } \
  2660. /* If |conditions.Cacheable()| might be true by the time we're done, we */ \
  2661. /* can't call parentContext->Style##type_() since it could recur into */ \
  2662. /* setting the same struct on the same rule node, causing a leak. */ \
  2663. mozilla::Maybe<nsStyle##type_> maybeFakeParentData; \
  2664. const nsStyle##type_* parentdata_ = data_; \
  2665. if (aRuleDetail != eRuleFullReset && \
  2666. aRuleDetail != eRulePartialReset && \
  2667. aRuleDetail != eRuleNone) { \
  2668. if (parentContext) { \
  2669. parentdata_ = parentContext->Style##type_(); \
  2670. } else { \
  2671. maybeFakeParentData.emplace(mPresContext); \
  2672. parentdata_ = maybeFakeParentData.ptr(); \
  2673. } \
  2674. } \
  2675. RuleNodeCacheConditions conditions = aConditions;
  2676. /**
  2677. * End an nsRuleNode::Compute*Data function for an inherited struct.
  2678. *
  2679. * @param type_ The nsStyle* type this function computes.
  2680. * @param data_ Variable holding the result of this function.
  2681. */
  2682. #define COMPUTE_END_INHERITED(type_, data_) \
  2683. NS_POSTCONDITION(!conditions.CacheableWithoutDependencies() || \
  2684. aRuleDetail == eRuleFullReset || \
  2685. (aStartStruct && aRuleDetail == eRulePartialReset), \
  2686. "conditions.CacheableWithoutDependencies() must be false " \
  2687. "for inherited structs unless all properties have been " \
  2688. "specified with values other than inherit"); \
  2689. if (conditions.CacheableWithoutDependencies()) { \
  2690. /* We were fully specified and can therefore be cached right on the */ \
  2691. /* rule node. */ \
  2692. if (!aHighestNode->mStyleData.mInheritedData) { \
  2693. aHighestNode->mStyleData.mInheritedData = \
  2694. new (mPresContext) nsInheritedStyleData; \
  2695. } \
  2696. NS_ASSERTION(!aHighestNode->mStyleData.mInheritedData-> \
  2697. mStyleStructs[eStyleStruct_##type_], \
  2698. "Going to leak style data"); \
  2699. aHighestNode->mStyleData.mInheritedData-> \
  2700. mStyleStructs[eStyleStruct_##type_] = data_; \
  2701. /* Propagate the bit down. */ \
  2702. PropagateDependentBit(eStyleStruct_##type_, aHighestNode, data_); \
  2703. /* Tell the style context that it doesn't own the data */ \
  2704. aContext->AddStyleBit(NS_STYLE_INHERIT_BIT(type_)); \
  2705. } \
  2706. /* For inherited structs, our caller will cache the data on the */ \
  2707. /* style context */ \
  2708. \
  2709. return data_;
  2710. /**
  2711. * End an nsRuleNode::Compute*Data function for a reset struct.
  2712. *
  2713. * @param type_ The nsStyle* type this function computes.
  2714. * @param data_ Variable holding the result of this function.
  2715. */
  2716. #define COMPUTE_END_RESET(type_, data_) \
  2717. NS_POSTCONDITION(!conditions.CacheableWithoutDependencies() || \
  2718. aRuleDetail == eRuleNone || \
  2719. aRuleDetail == eRulePartialReset || \
  2720. aRuleDetail == eRuleFullReset, \
  2721. "conditions.CacheableWithoutDependencies() must be false " \
  2722. "for reset structs if any properties were specified as " \
  2723. "inherit"); \
  2724. if (conditions.CacheableWithoutDependencies()) { \
  2725. /* We were fully specified and can therefore be cached right on the */ \
  2726. /* rule node. */ \
  2727. if (!aHighestNode->mStyleData.mResetData) { \
  2728. aHighestNode->mStyleData.mResetData = \
  2729. new (mPresContext) nsConditionalResetStyleData; \
  2730. } \
  2731. NS_ASSERTION(!aHighestNode->mStyleData.mResetData-> \
  2732. GetStyleData(eStyleStruct_##type_), \
  2733. "Going to leak style data"); \
  2734. aHighestNode->mStyleData.mResetData-> \
  2735. SetStyleData(eStyleStruct_##type_, data_); \
  2736. /* Propagate the bit down. */ \
  2737. PropagateDependentBit(eStyleStruct_##type_, aHighestNode, data_); \
  2738. if (HasAnimationData()) { \
  2739. /* If we have animation data, the struct should be cached on the */ \
  2740. /* style context so that we can peek the struct. */ \
  2741. /* See comment in AnimValuesStyleRule::MapRuleInfoInto. */ \
  2742. StoreStyleOnContext(aContext, eStyleStruct_##type_, data_); \
  2743. } \
  2744. } else if (conditions.Cacheable()) { \
  2745. if (!mStyleData.mResetData) { \
  2746. mStyleData.mResetData = new (mPresContext) nsConditionalResetStyleData; \
  2747. } \
  2748. mStyleData.mResetData-> \
  2749. SetStyleData(eStyleStruct_##type_, mPresContext, data_, conditions); \
  2750. /* Tell the style context that it doesn't own the data */ \
  2751. aContext->AddStyleBit(NS_STYLE_INHERIT_BIT(type_)); \
  2752. aContext->SetStyle(eStyleStruct_##type_, data_); \
  2753. } else { \
  2754. /* We can't be cached in the rule node. We have to be put right */ \
  2755. /* on the style context. */ \
  2756. aContext->SetStyle(eStyleStruct_##type_, data_); \
  2757. if (aContext->GetParent()) { \
  2758. /* This is pessimistic; we could be uncacheable because we had a */ \
  2759. /* relative font-weight, for example, which does not need to defeat */ \
  2760. /* the restyle optimizations in RestyleManager.cpp that look at */ \
  2761. /* NS_STYLE_HAS_CHILD_THAT_USES_RESET_STYLE. */ \
  2762. aContext->GetParent()-> \
  2763. AddStyleBit(NS_STYLE_HAS_CHILD_THAT_USES_RESET_STYLE); \
  2764. } \
  2765. } \
  2766. \
  2767. return data_;
  2768. // This function figures out how much scaling should be suppressed to
  2769. // satisfy scriptminsize. This is our attempt to implement
  2770. // http://www.w3.org/TR/MathML2/chapter3.html#id.3.3.4.2.2
  2771. // This is called after mScriptLevel, mScriptMinSize and mScriptSizeMultiplier
  2772. // have been set in aFont.
  2773. //
  2774. // Here are the invariants we enforce:
  2775. // 1) A decrease in size must not reduce the size below minscriptsize.
  2776. // 2) An increase in size must not increase the size above the size we would
  2777. // have if minscriptsize had not been applied anywhere.
  2778. // 3) The scriptlevel-induced size change must between 1.0 and the parent's
  2779. // scriptsizemultiplier^(new script level - old script level), as close to the
  2780. // latter as possible subject to constraints 1 and 2.
  2781. static nscoord
  2782. ComputeScriptLevelSize(const nsStyleFont* aFont, const nsStyleFont* aParentFont,
  2783. nsPresContext* aPresContext, nscoord* aUnconstrainedSize)
  2784. {
  2785. int32_t scriptLevelChange =
  2786. aFont->mScriptLevel - aParentFont->mScriptLevel;
  2787. if (scriptLevelChange == 0) {
  2788. *aUnconstrainedSize = aParentFont->mScriptUnconstrainedSize;
  2789. // Constraint #3 says that we cannot change size, and #1 and #2 are always
  2790. // satisfied with no change. It's important this be fast because it covers
  2791. // all non-MathML content.
  2792. return aParentFont->mSize;
  2793. }
  2794. // Compute actual value of minScriptSize
  2795. nscoord minScriptSize = aParentFont->mScriptMinSize;
  2796. if (aFont->mAllowZoom) {
  2797. minScriptSize = nsStyleFont::ZoomText(aPresContext, minScriptSize);
  2798. }
  2799. double scriptLevelScale =
  2800. pow(aParentFont->mScriptSizeMultiplier, scriptLevelChange);
  2801. // Compute the size we would have had if minscriptsize had never been
  2802. // applied, also prevent overflow (bug 413274)
  2803. *aUnconstrainedSize =
  2804. NSToCoordRoundWithClamp(aParentFont->mScriptUnconstrainedSize*scriptLevelScale);
  2805. // Compute the size we could get via scriptlevel change
  2806. nscoord scriptLevelSize =
  2807. NSToCoordRoundWithClamp(aParentFont->mSize*scriptLevelScale);
  2808. if (scriptLevelScale <= 1.0) {
  2809. if (aParentFont->mSize <= minScriptSize) {
  2810. // We can't decrease the font size at all, so just stick to no change
  2811. // (authors are allowed to explicitly set the font size smaller than
  2812. // minscriptsize)
  2813. return aParentFont->mSize;
  2814. }
  2815. // We can decrease, so apply constraint #1
  2816. return std::max(minScriptSize, scriptLevelSize);
  2817. } else {
  2818. // scriptminsize can only make sizes larger than the unconstrained size
  2819. NS_ASSERTION(*aUnconstrainedSize <= scriptLevelSize, "How can this ever happen?");
  2820. // Apply constraint #2
  2821. return std::min(scriptLevelSize, std::max(*aUnconstrainedSize, minScriptSize));
  2822. }
  2823. }
  2824. /* static */ nscoord
  2825. nsRuleNode::CalcFontPointSize(int32_t aHTMLSize, int32_t aBasePointSize,
  2826. nsPresContext* aPresContext,
  2827. nsFontSizeType aFontSizeType)
  2828. {
  2829. #define sFontSizeTableMin 9
  2830. #define sFontSizeTableMax 16
  2831. // This table seems to be the one used by MacIE5. We hope its adoption in Mozilla
  2832. // and eventually in WinIE5.5 will help to establish a standard rendering across
  2833. // platforms and browsers. For now, it is used only in Strict mode. More can be read
  2834. // in the document written by Todd Farhner at:
  2835. // http://style.verso.com/font_size_intervals/altintervals.html
  2836. //
  2837. static int32_t sStrictFontSizeTable[sFontSizeTableMax - sFontSizeTableMin + 1][8] =
  2838. {
  2839. { 9, 9, 9, 9, 11, 14, 18, 27},
  2840. { 9, 9, 9, 10, 12, 15, 20, 30},
  2841. { 9, 9, 10, 11, 13, 17, 22, 33},
  2842. { 9, 9, 10, 12, 14, 18, 24, 36},
  2843. { 9, 10, 12, 13, 16, 20, 26, 39},
  2844. { 9, 10, 12, 14, 17, 21, 28, 42},
  2845. { 9, 10, 13, 15, 18, 23, 30, 45},
  2846. { 9, 10, 13, 16, 18, 24, 32, 48}
  2847. };
  2848. // HTML 1 2 3 4 5 6 7
  2849. // CSS xxs xs s m l xl xxl
  2850. // |
  2851. // user pref
  2852. //
  2853. //------------------------------------------------------------
  2854. //
  2855. // This table gives us compatibility with WinNav4 for the default fonts only.
  2856. // In WinNav4, the default fonts were:
  2857. //
  2858. // Times/12pt == Times/16px at 96ppi
  2859. // Courier/10pt == Courier/13px at 96ppi
  2860. //
  2861. // The 2 lines below marked "anchored" have the exact pixel sizes used by
  2862. // WinNav4 for Times/12pt and Courier/10pt at 96ppi. As you can see, the
  2863. // HTML size 3 (user pref) for those 2 anchored lines is 13px and 16px.
  2864. //
  2865. // All values other than the anchored values were filled in by hand, never
  2866. // going below 9px, and maintaining a "diagonal" relationship. See for
  2867. // example the 13s -- they follow a diagonal line through the table.
  2868. //
  2869. static int32_t sQuirksFontSizeTable[sFontSizeTableMax - sFontSizeTableMin + 1][8] =
  2870. {
  2871. { 9, 9, 9, 9, 11, 14, 18, 28 },
  2872. { 9, 9, 9, 10, 12, 15, 20, 31 },
  2873. { 9, 9, 9, 11, 13, 17, 22, 34 },
  2874. { 9, 9, 10, 12, 14, 18, 24, 37 },
  2875. { 9, 9, 10, 13, 16, 20, 26, 40 }, // anchored (13)
  2876. { 9, 9, 11, 14, 17, 21, 28, 42 },
  2877. { 9, 10, 12, 15, 17, 23, 30, 45 },
  2878. { 9, 10, 13, 16, 18, 24, 32, 48 } // anchored (16)
  2879. };
  2880. // HTML 1 2 3 4 5 6 7
  2881. // CSS xxs xs s m l xl xxl
  2882. // |
  2883. // user pref
  2884. #if 0
  2885. //
  2886. // These are the exact pixel values used by WinIE5 at 96ppi.
  2887. //
  2888. { ?, 8, 11, 12, 13, 16, 21, 32 }, // smallest
  2889. { ?, 9, 12, 13, 16, 21, 27, 40 }, // smaller
  2890. { ?, 10, 13, 16, 18, 24, 32, 48 }, // medium
  2891. { ?, 13, 16, 19, 21, 27, 37, ?? }, // larger
  2892. { ?, 16, 19, 21, 24, 32, 43, ?? } // largest
  2893. //
  2894. // HTML 1 2 3 4 5 6 7
  2895. // CSS ? ? ? ? ? ? ? ?
  2896. //
  2897. // (CSS not tested yet.)
  2898. //
  2899. #endif
  2900. static int32_t sFontSizeFactors[8] = { 60,75,89,100,120,150,200,300 };
  2901. static int32_t sCSSColumns[7] = {0, 1, 2, 3, 4, 5, 6}; // xxs...xxl
  2902. static int32_t sHTMLColumns[7] = {1, 2, 3, 4, 5, 6, 7}; // 1...7
  2903. double dFontSize;
  2904. if (aFontSizeType == eFontSize_HTML) {
  2905. aHTMLSize--; // input as 1-7
  2906. }
  2907. if (aHTMLSize < 0) {
  2908. aHTMLSize = 0;
  2909. } else if (aHTMLSize > 6) {
  2910. aHTMLSize = 6;
  2911. }
  2912. int32_t* column;
  2913. switch (aFontSizeType)
  2914. {
  2915. case eFontSize_HTML: column = sHTMLColumns; break;
  2916. case eFontSize_CSS: column = sCSSColumns; break;
  2917. }
  2918. // Make special call specifically for fonts (needed PrintPreview)
  2919. int32_t fontSize = nsPresContext::AppUnitsToIntCSSPixels(aBasePointSize);
  2920. if ((fontSize >= sFontSizeTableMin) && (fontSize <= sFontSizeTableMax))
  2921. {
  2922. int32_t row = fontSize - sFontSizeTableMin;
  2923. if (aPresContext->CompatibilityMode() == eCompatibility_NavQuirks) {
  2924. dFontSize = nsPresContext::CSSPixelsToAppUnits(sQuirksFontSizeTable[row][column[aHTMLSize]]);
  2925. } else {
  2926. dFontSize = nsPresContext::CSSPixelsToAppUnits(sStrictFontSizeTable[row][column[aHTMLSize]]);
  2927. }
  2928. } else {
  2929. int32_t factor = sFontSizeFactors[column[aHTMLSize]];
  2930. dFontSize = (factor * aBasePointSize) / 100;
  2931. }
  2932. if (1.0 < dFontSize) {
  2933. return (nscoord)dFontSize;
  2934. }
  2935. return (nscoord)1;
  2936. }
  2937. //------------------------------------------------------------------------------
  2938. //
  2939. //------------------------------------------------------------------------------
  2940. /* static */ nscoord
  2941. nsRuleNode::FindNextSmallerFontSize(nscoord aFontSize, int32_t aBasePointSize,
  2942. nsPresContext* aPresContext,
  2943. nsFontSizeType aFontSizeType)
  2944. {
  2945. int32_t index;
  2946. int32_t indexMin;
  2947. int32_t indexMax;
  2948. float relativePosition;
  2949. nscoord smallerSize;
  2950. nscoord indexFontSize = aFontSize; // XXX initialize to quell a spurious gcc3.2 warning
  2951. nscoord smallestIndexFontSize;
  2952. nscoord largestIndexFontSize;
  2953. nscoord smallerIndexFontSize;
  2954. nscoord largerIndexFontSize;
  2955. nscoord onePx = nsPresContext::CSSPixelsToAppUnits(1);
  2956. if (aFontSizeType == eFontSize_HTML) {
  2957. indexMin = 1;
  2958. indexMax = 7;
  2959. } else {
  2960. indexMin = 0;
  2961. indexMax = 6;
  2962. }
  2963. smallestIndexFontSize = CalcFontPointSize(indexMin, aBasePointSize, aPresContext, aFontSizeType);
  2964. largestIndexFontSize = CalcFontPointSize(indexMax, aBasePointSize, aPresContext, aFontSizeType);
  2965. if (aFontSize > smallestIndexFontSize) {
  2966. if (aFontSize < NSToCoordRound(float(largestIndexFontSize) * 1.5)) { // smaller will be in HTML table
  2967. // find largest index smaller than current
  2968. for (index = indexMax; index >= indexMin; index--) {
  2969. indexFontSize = CalcFontPointSize(index, aBasePointSize, aPresContext, aFontSizeType);
  2970. if (indexFontSize < aFontSize) {
  2971. break;
  2972. }
  2973. }
  2974. // set up points beyond table for interpolation purposes
  2975. if (indexFontSize == smallestIndexFontSize) {
  2976. smallerIndexFontSize = indexFontSize - onePx;
  2977. largerIndexFontSize = CalcFontPointSize(index+1, aBasePointSize, aPresContext, aFontSizeType);
  2978. } else if (indexFontSize == largestIndexFontSize) {
  2979. smallerIndexFontSize = CalcFontPointSize(index-1, aBasePointSize, aPresContext, aFontSizeType);
  2980. largerIndexFontSize = NSToCoordRound(float(largestIndexFontSize) * 1.5);
  2981. } else {
  2982. smallerIndexFontSize = CalcFontPointSize(index-1, aBasePointSize, aPresContext, aFontSizeType);
  2983. largerIndexFontSize = CalcFontPointSize(index+1, aBasePointSize, aPresContext, aFontSizeType);
  2984. }
  2985. // compute the relative position of the parent size between the two closest indexed sizes
  2986. relativePosition = float(aFontSize - indexFontSize) / float(largerIndexFontSize - indexFontSize);
  2987. // set the new size to have the same relative position between the next smallest two indexed sizes
  2988. smallerSize = smallerIndexFontSize + NSToCoordRound(relativePosition * (indexFontSize - smallerIndexFontSize));
  2989. } else { // larger than HTML table, drop by 33%
  2990. smallerSize = NSToCoordRound(float(aFontSize) / 1.5);
  2991. }
  2992. } else { // smaller than HTML table, drop by 1px
  2993. smallerSize = std::max(aFontSize - onePx, onePx);
  2994. }
  2995. return smallerSize;
  2996. }
  2997. //------------------------------------------------------------------------------
  2998. //
  2999. //------------------------------------------------------------------------------
  3000. /* static */ nscoord
  3001. nsRuleNode::FindNextLargerFontSize(nscoord aFontSize, int32_t aBasePointSize,
  3002. nsPresContext* aPresContext,
  3003. nsFontSizeType aFontSizeType)
  3004. {
  3005. int32_t index;
  3006. int32_t indexMin;
  3007. int32_t indexMax;
  3008. float relativePosition;
  3009. nscoord adjustment;
  3010. nscoord largerSize;
  3011. nscoord indexFontSize = aFontSize; // XXX initialize to quell a spurious gcc3.2 warning
  3012. nscoord smallestIndexFontSize;
  3013. nscoord largestIndexFontSize;
  3014. nscoord smallerIndexFontSize;
  3015. nscoord largerIndexFontSize;
  3016. nscoord onePx = nsPresContext::CSSPixelsToAppUnits(1);
  3017. if (aFontSizeType == eFontSize_HTML) {
  3018. indexMin = 1;
  3019. indexMax = 7;
  3020. } else {
  3021. indexMin = 0;
  3022. indexMax = 6;
  3023. }
  3024. smallestIndexFontSize = CalcFontPointSize(indexMin, aBasePointSize, aPresContext, aFontSizeType);
  3025. largestIndexFontSize = CalcFontPointSize(indexMax, aBasePointSize, aPresContext, aFontSizeType);
  3026. if (aFontSize > (smallestIndexFontSize - onePx)) {
  3027. if (aFontSize < largestIndexFontSize) { // larger will be in HTML table
  3028. // find smallest index larger than current
  3029. for (index = indexMin; index <= indexMax; index++) {
  3030. indexFontSize = CalcFontPointSize(index, aBasePointSize, aPresContext, aFontSizeType);
  3031. if (indexFontSize > aFontSize) {
  3032. break;
  3033. }
  3034. }
  3035. // set up points beyond table for interpolation purposes
  3036. if (indexFontSize == smallestIndexFontSize) {
  3037. smallerIndexFontSize = indexFontSize - onePx;
  3038. largerIndexFontSize = CalcFontPointSize(index+1, aBasePointSize, aPresContext, aFontSizeType);
  3039. } else if (indexFontSize == largestIndexFontSize) {
  3040. smallerIndexFontSize = CalcFontPointSize(index-1, aBasePointSize, aPresContext, aFontSizeType);
  3041. largerIndexFontSize = NSCoordSaturatingMultiply(largestIndexFontSize, 1.5);
  3042. } else {
  3043. smallerIndexFontSize = CalcFontPointSize(index-1, aBasePointSize, aPresContext, aFontSizeType);
  3044. largerIndexFontSize = CalcFontPointSize(index+1, aBasePointSize, aPresContext, aFontSizeType);
  3045. }
  3046. // compute the relative position of the parent size between the two closest indexed sizes
  3047. relativePosition = float(aFontSize - smallerIndexFontSize) / float(indexFontSize - smallerIndexFontSize);
  3048. // set the new size to have the same relative position between the next largest two indexed sizes
  3049. adjustment = NSCoordSaturatingNonnegativeMultiply(largerIndexFontSize - indexFontSize, relativePosition);
  3050. largerSize = NSCoordSaturatingAdd(indexFontSize, adjustment);
  3051. } else { // larger than HTML table, increase by 50%
  3052. largerSize = NSCoordSaturatingMultiply(aFontSize, 1.5);
  3053. }
  3054. } else { // smaller than HTML table, increase by 1px
  3055. largerSize = NSCoordSaturatingAdd(aFontSize, onePx);
  3056. }
  3057. return largerSize;
  3058. }
  3059. struct SetFontSizeCalcOps : public css::BasicCoordCalcOps,
  3060. public css::NumbersAlreadyNormalizedOps
  3061. {
  3062. // The parameters beyond aValue that we need for CalcLengthWith.
  3063. const nscoord mParentSize;
  3064. const nsStyleFont* const mParentFont;
  3065. nsPresContext* const mPresContext;
  3066. nsStyleContext* const mStyleContext;
  3067. const bool mAtRoot;
  3068. RuleNodeCacheConditions& mConditions;
  3069. SetFontSizeCalcOps(nscoord aParentSize, const nsStyleFont* aParentFont,
  3070. nsPresContext* aPresContext,
  3071. nsStyleContext* aStyleContext,
  3072. bool aAtRoot,
  3073. RuleNodeCacheConditions& aConditions)
  3074. : mParentSize(aParentSize),
  3075. mParentFont(aParentFont),
  3076. mPresContext(aPresContext),
  3077. mStyleContext(aStyleContext),
  3078. mAtRoot(aAtRoot),
  3079. mConditions(aConditions)
  3080. {
  3081. }
  3082. result_type ComputeLeafValue(const nsCSSValue& aValue)
  3083. {
  3084. nscoord size;
  3085. if (aValue.IsLengthUnit()) {
  3086. // Note that font-based length units use the parent's size
  3087. // unadjusted for scriptlevel changes. A scriptlevel change
  3088. // between us and the parent is simply ignored.
  3089. size = CalcLengthWith(aValue, mParentSize,
  3090. mParentFont,
  3091. mStyleContext, mPresContext, mAtRoot,
  3092. true, mConditions);
  3093. if (!aValue.IsRelativeLengthUnit() && mParentFont->mAllowZoom) {
  3094. size = nsStyleFont::ZoomText(mPresContext, size);
  3095. }
  3096. } else if (eCSSUnit_Percent == aValue.GetUnit()) {
  3097. mConditions.SetUncacheable();
  3098. // Note that % units use the parent's size unadjusted for scriptlevel
  3099. // changes. A scriptlevel change between us and the parent is simply
  3100. // ignored.
  3101. // aValue.GetPercentValue() may be negative for, e.g., calc(-50%)
  3102. size = NSCoordSaturatingMultiply(mParentSize, aValue.GetPercentValue());
  3103. } else {
  3104. MOZ_ASSERT(false, "unexpected value");
  3105. size = mParentSize;
  3106. }
  3107. return size;
  3108. }
  3109. };
  3110. /* static */ void
  3111. nsRuleNode::SetFontSize(nsPresContext* aPresContext,
  3112. nsStyleContext* aContext,
  3113. const nsRuleData* aRuleData,
  3114. const nsStyleFont* aFont,
  3115. const nsStyleFont* aParentFont,
  3116. nscoord* aSize,
  3117. const nsFont& aSystemFont,
  3118. nscoord aParentSize,
  3119. nscoord aScriptLevelAdjustedParentSize,
  3120. bool aUsedStartStruct,
  3121. bool aAtRoot,
  3122. RuleNodeCacheConditions& aConditions)
  3123. {
  3124. // If false, means that *aSize has not been zoomed. If true, means that
  3125. // *aSize has been zoomed iff aParentFont->mAllowZoom is true.
  3126. bool sizeIsZoomedAccordingToParent = false;
  3127. int32_t baseSize = (int32_t) aPresContext->
  3128. GetDefaultFont(aFont->mGenericID, aFont->mLanguage)->size;
  3129. const nsCSSValue* sizeValue = aRuleData->ValueForFontSize();
  3130. if (eCSSUnit_Enumerated == sizeValue->GetUnit()) {
  3131. int32_t value = sizeValue->GetIntValue();
  3132. if ((NS_STYLE_FONT_SIZE_XXSMALL <= value) &&
  3133. (value <= NS_STYLE_FONT_SIZE_XXLARGE)) {
  3134. *aSize = CalcFontPointSize(value, baseSize,
  3135. aPresContext, eFontSize_CSS);
  3136. } else if (NS_STYLE_FONT_SIZE_XXXLARGE == value) {
  3137. // <font size="7"> is not specified in CSS, so we don't use eFontSize_CSS.
  3138. *aSize = CalcFontPointSize(value, baseSize, aPresContext);
  3139. } else if (NS_STYLE_FONT_SIZE_LARGER == value ||
  3140. NS_STYLE_FONT_SIZE_SMALLER == value) {
  3141. aConditions.SetUncacheable();
  3142. // Un-zoom so we use the tables correctly. We'll then rezoom due
  3143. // to the |zoom = true| above.
  3144. // Note that relative units here use the parent's size unadjusted
  3145. // for scriptlevel changes. A scriptlevel change between us and the parent
  3146. // is simply ignored.
  3147. nscoord parentSize = aParentSize;
  3148. if (aParentFont->mAllowZoom) {
  3149. parentSize = nsStyleFont::UnZoomText(aPresContext, parentSize);
  3150. }
  3151. if (NS_STYLE_FONT_SIZE_LARGER == value) {
  3152. *aSize = FindNextLargerFontSize(parentSize,
  3153. baseSize, aPresContext, eFontSize_CSS);
  3154. NS_ASSERTION(*aSize >= parentSize,
  3155. "FindNextLargerFontSize failed");
  3156. } else {
  3157. *aSize = FindNextSmallerFontSize(parentSize,
  3158. baseSize, aPresContext, eFontSize_CSS);
  3159. NS_ASSERTION(*aSize < parentSize ||
  3160. parentSize <= nsPresContext::CSSPixelsToAppUnits(1),
  3161. "FindNextSmallerFontSize failed");
  3162. }
  3163. } else {
  3164. NS_NOTREACHED("unexpected value");
  3165. }
  3166. } else if (sizeValue->IsLengthUnit() ||
  3167. sizeValue->GetUnit() == eCSSUnit_Percent ||
  3168. sizeValue->IsCalcUnit()) {
  3169. SetFontSizeCalcOps ops(aParentSize, aParentFont,
  3170. aPresContext, aContext,
  3171. aAtRoot,
  3172. aConditions);
  3173. *aSize = css::ComputeCalc(*sizeValue, ops);
  3174. if (*aSize < 0) {
  3175. MOZ_ASSERT(sizeValue->IsCalcUnit(),
  3176. "negative lengths and percents should be rejected by parser");
  3177. *aSize = 0;
  3178. }
  3179. // The calc ops will always zoom its result according to the value
  3180. // of aParentFont->mAllowZoom.
  3181. sizeIsZoomedAccordingToParent = true;
  3182. } else if (eCSSUnit_System_Font == sizeValue->GetUnit()) {
  3183. // this becomes our cascading size
  3184. *aSize = aSystemFont.size;
  3185. } else if (eCSSUnit_Inherit == sizeValue->GetUnit() ||
  3186. eCSSUnit_Unset == sizeValue->GetUnit()) {
  3187. aConditions.SetUncacheable();
  3188. // We apply scriptlevel change for this case, because the default is
  3189. // to inherit and we don't want explicit "inherit" to differ from the
  3190. // default.
  3191. *aSize = aScriptLevelAdjustedParentSize;
  3192. sizeIsZoomedAccordingToParent = true;
  3193. } else if (eCSSUnit_Initial == sizeValue->GetUnit()) {
  3194. // The initial value is 'medium', which has magical sizing based on
  3195. // the generic font family, so do that here too.
  3196. *aSize = baseSize;
  3197. } else {
  3198. NS_ASSERTION(eCSSUnit_Null == sizeValue->GetUnit(),
  3199. "What kind of font-size value is this?");
  3200. // if aUsedStartStruct is true, then every single property in the
  3201. // font struct is being set all at once. This means scriptlevel is not
  3202. // going to have any influence on the font size; there is no need to
  3203. // do anything here.
  3204. if (!aUsedStartStruct && aParentSize != aScriptLevelAdjustedParentSize) {
  3205. // There was no rule affecting the size but the size has been
  3206. // affected by the parent's size via scriptlevel change. So we cannot
  3207. // store the data in the rule tree.
  3208. aConditions.SetUncacheable();
  3209. *aSize = aScriptLevelAdjustedParentSize;
  3210. sizeIsZoomedAccordingToParent = true;
  3211. } else {
  3212. return;
  3213. }
  3214. }
  3215. // We want to zoom the cascaded size so that em-based measurements,
  3216. // line-heights, etc., work.
  3217. bool currentlyZoomed = sizeIsZoomedAccordingToParent &&
  3218. aParentFont->mAllowZoom;
  3219. if (!currentlyZoomed && aFont->mAllowZoom) {
  3220. *aSize = nsStyleFont::ZoomText(aPresContext, *aSize);
  3221. } else if (currentlyZoomed && !aFont->mAllowZoom) {
  3222. *aSize = nsStyleFont::UnZoomText(aPresContext, *aSize);
  3223. }
  3224. }
  3225. static int8_t ClampTo8Bit(int32_t aValue) {
  3226. if (aValue < -128) {
  3227. return -128;
  3228. }
  3229. if (aValue > 127) {
  3230. return 127;
  3231. }
  3232. return int8_t(aValue);
  3233. }
  3234. /* static */ void
  3235. nsRuleNode::SetFont(nsPresContext* aPresContext, nsStyleContext* aContext,
  3236. uint8_t aGenericFontID, const nsRuleData* aRuleData,
  3237. const nsStyleFont* aParentFont,
  3238. nsStyleFont* aFont, bool aUsedStartStruct,
  3239. RuleNodeCacheConditions& aConditions)
  3240. {
  3241. bool atRoot = !aContext->GetParent();
  3242. // -x-text-zoom: none, inherit, initial
  3243. bool allowZoom;
  3244. const nsCSSValue* textZoomValue = aRuleData->ValueForTextZoom();
  3245. if (eCSSUnit_Null != textZoomValue->GetUnit()) {
  3246. if (eCSSUnit_Inherit == textZoomValue->GetUnit()) {
  3247. allowZoom = aParentFont->mAllowZoom;
  3248. } else if (eCSSUnit_None == textZoomValue->GetUnit()) {
  3249. allowZoom = false;
  3250. } else {
  3251. MOZ_ASSERT(eCSSUnit_Initial == textZoomValue->GetUnit(),
  3252. "unexpected unit");
  3253. allowZoom = true;
  3254. }
  3255. aFont->EnableZoom(aPresContext, allowZoom);
  3256. }
  3257. // mLanguage must be set before before any of the CalcLengthWith calls
  3258. // (direct calls or calls via SetFontSize) for the cases where |aParentFont|
  3259. // is the same as |aFont|.
  3260. //
  3261. // -x-lang: string, inherit
  3262. // This is not a real CSS property, it is an HTML attribute mapped to CSS.
  3263. const nsCSSValue* langValue = aRuleData->ValueForLang();
  3264. if (eCSSUnit_Ident == langValue->GetUnit()) {
  3265. nsAutoString lang;
  3266. langValue->GetStringValue(lang);
  3267. nsContentUtils::ASCIIToLower(lang);
  3268. aFont->mLanguage = NS_Atomize(lang);
  3269. aFont->mExplicitLanguage = true;
  3270. }
  3271. const nsFont* defaultVariableFont =
  3272. aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID,
  3273. aFont->mLanguage);
  3274. // -moz-system-font: enum (never inherit!)
  3275. static_assert(
  3276. NS_STYLE_FONT_CAPTION == LookAndFeel::eFont_Caption &&
  3277. NS_STYLE_FONT_ICON == LookAndFeel::eFont_Icon &&
  3278. NS_STYLE_FONT_MENU == LookAndFeel::eFont_Menu &&
  3279. NS_STYLE_FONT_MESSAGE_BOX == LookAndFeel::eFont_MessageBox &&
  3280. NS_STYLE_FONT_SMALL_CAPTION == LookAndFeel::eFont_SmallCaption &&
  3281. NS_STYLE_FONT_STATUS_BAR == LookAndFeel::eFont_StatusBar &&
  3282. NS_STYLE_FONT_WINDOW == LookAndFeel::eFont_Window &&
  3283. NS_STYLE_FONT_DOCUMENT == LookAndFeel::eFont_Document &&
  3284. NS_STYLE_FONT_WORKSPACE == LookAndFeel::eFont_Workspace &&
  3285. NS_STYLE_FONT_DESKTOP == LookAndFeel::eFont_Desktop &&
  3286. NS_STYLE_FONT_INFO == LookAndFeel::eFont_Info &&
  3287. NS_STYLE_FONT_DIALOG == LookAndFeel::eFont_Dialog &&
  3288. NS_STYLE_FONT_BUTTON == LookAndFeel::eFont_Button &&
  3289. NS_STYLE_FONT_PULL_DOWN_MENU == LookAndFeel::eFont_PullDownMenu &&
  3290. NS_STYLE_FONT_LIST == LookAndFeel::eFont_List &&
  3291. NS_STYLE_FONT_FIELD == LookAndFeel::eFont_Field,
  3292. "LookAndFeel.h system-font constants out of sync with nsStyleConsts.h");
  3293. // Fall back to defaultVariableFont.
  3294. nsFont systemFont = *defaultVariableFont;
  3295. const nsCSSValue* systemFontValue = aRuleData->ValueForSystemFont();
  3296. if (eCSSUnit_Enumerated == systemFontValue->GetUnit()) {
  3297. gfxFontStyle fontStyle;
  3298. LookAndFeel::FontID fontID =
  3299. (LookAndFeel::FontID)systemFontValue->GetIntValue();
  3300. float devPerCSS =
  3301. (float)nsPresContext::AppUnitsPerCSSPixel() /
  3302. aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom();
  3303. nsAutoString systemFontName;
  3304. if (LookAndFeel::GetFont(fontID, systemFontName, fontStyle, devPerCSS)) {
  3305. systemFontName.Trim("\"'");
  3306. systemFont.fontlist = FontFamilyList(systemFontName, eUnquotedName);
  3307. systemFont.fontlist.SetDefaultFontType(eFamily_none);
  3308. systemFont.style = fontStyle.style;
  3309. systemFont.systemFont = fontStyle.systemFont;
  3310. systemFont.weight = fontStyle.weight;
  3311. systemFont.stretch = fontStyle.stretch;
  3312. systemFont.size =
  3313. NSFloatPixelsToAppUnits(fontStyle.size,
  3314. aPresContext->DeviceContext()->
  3315. AppUnitsPerDevPixelAtUnitFullZoom());
  3316. //systemFont.langGroup = fontStyle.langGroup;
  3317. systemFont.sizeAdjust = fontStyle.sizeAdjust;
  3318. #ifdef XP_WIN
  3319. // XXXldb This platform-specific stuff should be in the
  3320. // LookAndFeel implementation, not here.
  3321. // XXXzw Should we even still *have* this code? It looks to be making
  3322. // old, probably obsolete assumptions.
  3323. if (fontID == LookAndFeel::eFont_Field ||
  3324. fontID == LookAndFeel::eFont_Button ||
  3325. fontID == LookAndFeel::eFont_List) {
  3326. // As far as I can tell the system default fonts and sizes
  3327. // on MS-Windows for Buttons, Listboxes/Comboxes and Text Fields are
  3328. // all pre-determined and cannot be changed by either the control panel
  3329. // or programmatically.
  3330. // Fields (text fields)
  3331. // Button and Selects (listboxes/comboboxes)
  3332. // We use whatever font is defined by the system. Which it appears
  3333. // (and the assumption is) it is always a proportional font. Then we
  3334. // always use 2 points smaller than what the browser has defined as
  3335. // the default proportional font.
  3336. // Assumption: system defined font is proportional
  3337. systemFont.size =
  3338. std::max(defaultVariableFont->size -
  3339. nsPresContext::CSSPointsToAppUnits(2), 0);
  3340. }
  3341. #endif
  3342. }
  3343. }
  3344. // font-family: font family list, enum, inherit
  3345. const nsCSSValue* familyValue = aRuleData->ValueForFontFamily();
  3346. NS_ASSERTION(eCSSUnit_Enumerated != familyValue->GetUnit(),
  3347. "system fonts should not be in mFamily anymore");
  3348. if (eCSSUnit_FontFamilyList == familyValue->GetUnit()) {
  3349. // set the correct font if we are using DocumentFonts OR we are overriding for XUL
  3350. // MJA: bug 31816
  3351. bool useDocumentFonts =
  3352. aPresContext->GetCachedBoolPref(kPresContext_UseDocumentFonts);
  3353. if (aGenericFontID == kGenericFont_NONE ||
  3354. (!useDocumentFonts && (aGenericFontID == kGenericFont_cursive ||
  3355. aGenericFontID == kGenericFont_fantasy))) {
  3356. FontFamilyType defaultGeneric =
  3357. defaultVariableFont->fontlist.FirstGeneric();
  3358. MOZ_ASSERT(defaultVariableFont->fontlist.Length() == 1 &&
  3359. (defaultGeneric == eFamily_serif ||
  3360. defaultGeneric == eFamily_sans_serif));
  3361. if (defaultGeneric != eFamily_none) {
  3362. if (useDocumentFonts) {
  3363. aFont->mFont.fontlist.SetDefaultFontType(defaultGeneric);
  3364. } else {
  3365. // Either prioritize the first generic in the list,
  3366. // or (if there isn't one) prepend the default variable font.
  3367. if (!aFont->mFont.fontlist.PrioritizeFirstGeneric()) {
  3368. aFont->mFont.fontlist.PrependGeneric(defaultGeneric);
  3369. }
  3370. }
  3371. }
  3372. } else {
  3373. aFont->mFont.fontlist.SetDefaultFontType(eFamily_none);
  3374. }
  3375. aFont->mFont.systemFont = false;
  3376. // Technically this is redundant with the code below, but it's good
  3377. // to have since we'll still want it once we get rid of
  3378. // SetGenericFont (bug 380915).
  3379. aFont->mGenericID = aGenericFontID;
  3380. } else if (eCSSUnit_System_Font == familyValue->GetUnit()) {
  3381. aFont->mFont.fontlist = systemFont.fontlist;
  3382. aFont->mFont.systemFont = true;
  3383. aFont->mGenericID = kGenericFont_NONE;
  3384. } else if (eCSSUnit_Inherit == familyValue->GetUnit() ||
  3385. eCSSUnit_Unset == familyValue->GetUnit()) {
  3386. aConditions.SetUncacheable();
  3387. aFont->mFont.fontlist = aParentFont->mFont.fontlist;
  3388. aFont->mFont.systemFont = aParentFont->mFont.systemFont;
  3389. aFont->mGenericID = aParentFont->mGenericID;
  3390. } else if (eCSSUnit_Initial == familyValue->GetUnit()) {
  3391. aFont->mFont.fontlist = defaultVariableFont->fontlist;
  3392. aFont->mFont.systemFont = defaultVariableFont->systemFont;
  3393. aFont->mGenericID = kGenericFont_NONE;
  3394. }
  3395. // When we're in the loop in SetGenericFont, we must ensure that we
  3396. // always keep aFont->mFlags set to the correct generic. But we have
  3397. // to be careful not to touch it when we're called directly from
  3398. // ComputeFontData, because we could have a start struct.
  3399. if (aGenericFontID != kGenericFont_NONE) {
  3400. aFont->mGenericID = aGenericFontID;
  3401. }
  3402. // -moz-math-variant: enum, inherit, initial
  3403. SetValue(*aRuleData->ValueForMathVariant(), aFont->mMathVariant,
  3404. aConditions,
  3405. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  3406. aParentFont->mMathVariant, NS_MATHML_MATHVARIANT_NONE);
  3407. // -moz-math-display: enum, inherit, initial
  3408. SetValue(*aRuleData->ValueForMathDisplay(), aFont->mMathDisplay,
  3409. aConditions,
  3410. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  3411. aParentFont->mMathDisplay, NS_MATHML_DISPLAYSTYLE_INLINE);
  3412. // font-smoothing: enum, inherit, initial
  3413. SetValue(*aRuleData->ValueForOsxFontSmoothing(),
  3414. aFont->mFont.smoothing, aConditions,
  3415. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  3416. aParentFont->mFont.smoothing,
  3417. defaultVariableFont->smoothing);
  3418. // font-style: enum, inherit, initial, -moz-system-font
  3419. if (aFont->mMathVariant != NS_MATHML_MATHVARIANT_NONE) {
  3420. // -moz-math-variant overrides font-style
  3421. aFont->mFont.style = NS_FONT_STYLE_NORMAL;
  3422. } else {
  3423. SetValue(*aRuleData->ValueForFontStyle(),
  3424. aFont->mFont.style, aConditions,
  3425. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  3426. aParentFont->mFont.style,
  3427. defaultVariableFont->style,
  3428. Unused, Unused, Unused, systemFont.style);
  3429. }
  3430. // font-weight: int, enum, inherit, initial, -moz-system-font
  3431. // special handling for enum
  3432. const nsCSSValue* weightValue = aRuleData->ValueForFontWeight();
  3433. if (aFont->mMathVariant != NS_MATHML_MATHVARIANT_NONE) {
  3434. // -moz-math-variant overrides font-weight
  3435. aFont->mFont.weight = NS_FONT_WEIGHT_NORMAL;
  3436. } else if (eCSSUnit_Enumerated == weightValue->GetUnit()) {
  3437. int32_t value = weightValue->GetIntValue();
  3438. switch (value) {
  3439. case NS_STYLE_FONT_WEIGHT_NORMAL:
  3440. case NS_STYLE_FONT_WEIGHT_BOLD:
  3441. aFont->mFont.weight = value;
  3442. break;
  3443. case NS_STYLE_FONT_WEIGHT_BOLDER: {
  3444. aConditions.SetUncacheable();
  3445. int32_t inheritedValue = aParentFont->mFont.weight;
  3446. if (inheritedValue <= 300) {
  3447. aFont->mFont.weight = 400;
  3448. } else if (inheritedValue <= 500) {
  3449. aFont->mFont.weight = 700;
  3450. } else {
  3451. aFont->mFont.weight = 900;
  3452. }
  3453. break;
  3454. }
  3455. case NS_STYLE_FONT_WEIGHT_LIGHTER: {
  3456. aConditions.SetUncacheable();
  3457. int32_t inheritedValue = aParentFont->mFont.weight;
  3458. if (inheritedValue < 600) {
  3459. aFont->mFont.weight = 100;
  3460. } else if (inheritedValue < 800) {
  3461. aFont->mFont.weight = 400;
  3462. } else {
  3463. aFont->mFont.weight = 700;
  3464. }
  3465. break;
  3466. }
  3467. }
  3468. } else
  3469. SetValue(*weightValue, aFont->mFont.weight, aConditions,
  3470. SETVAL_INTEGER | SETVAL_UNSET_INHERIT,
  3471. aParentFont->mFont.weight,
  3472. defaultVariableFont->weight,
  3473. Unused, Unused, Unused, systemFont.weight);
  3474. // font-stretch: enum, inherit, initial, -moz-system-font
  3475. SetValue(*aRuleData->ValueForFontStretch(),
  3476. aFont->mFont.stretch, aConditions,
  3477. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  3478. aParentFont->mFont.stretch,
  3479. defaultVariableFont->stretch,
  3480. Unused, Unused, Unused, systemFont.stretch);
  3481. // Compute scriptlevel, scriptminsize and scriptsizemultiplier now so
  3482. // they're available for font-size computation.
  3483. // -moz-script-min-size: length
  3484. const nsCSSValue* scriptMinSizeValue = aRuleData->ValueForScriptMinSize();
  3485. if (scriptMinSizeValue->IsLengthUnit()) {
  3486. // scriptminsize in font units (em, ex) has to be interpreted relative
  3487. // to the parent font, or the size definitions are circular and we
  3488. //
  3489. aFont->mScriptMinSize =
  3490. CalcLengthWith(*scriptMinSizeValue, aParentFont->mSize,
  3491. aParentFont,
  3492. aContext, aPresContext, atRoot, true /* aUseUserFontSet */,
  3493. aConditions);
  3494. }
  3495. // -moz-script-size-multiplier: factor, inherit, initial
  3496. SetFactor(*aRuleData->ValueForScriptSizeMultiplier(),
  3497. aFont->mScriptSizeMultiplier,
  3498. aConditions, aParentFont->mScriptSizeMultiplier,
  3499. NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER,
  3500. SETFCT_POSITIVE | SETFCT_UNSET_INHERIT);
  3501. // -moz-script-level: integer, number, inherit
  3502. const nsCSSValue* scriptLevelValue = aRuleData->ValueForScriptLevel();
  3503. if (eCSSUnit_Integer == scriptLevelValue->GetUnit()) {
  3504. // "relative"
  3505. aConditions.SetUncacheable();
  3506. aFont->mScriptLevel = ClampTo8Bit(aParentFont->mScriptLevel + scriptLevelValue->GetIntValue());
  3507. } else if (eCSSUnit_Number == scriptLevelValue->GetUnit()) {
  3508. // "absolute"
  3509. aFont->mScriptLevel = ClampTo8Bit(int32_t(scriptLevelValue->GetFloatValue()));
  3510. } else if (eCSSUnit_Auto == scriptLevelValue->GetUnit()) {
  3511. // auto
  3512. aConditions.SetUncacheable();
  3513. aFont->mScriptLevel = ClampTo8Bit(aParentFont->mScriptLevel +
  3514. (aParentFont->mMathDisplay ==
  3515. NS_MATHML_DISPLAYSTYLE_INLINE ? 1 : 0));
  3516. } else if (eCSSUnit_Inherit == scriptLevelValue->GetUnit() ||
  3517. eCSSUnit_Unset == scriptLevelValue->GetUnit()) {
  3518. aConditions.SetUncacheable();
  3519. aFont->mScriptLevel = aParentFont->mScriptLevel;
  3520. } else if (eCSSUnit_Initial == scriptLevelValue->GetUnit()) {
  3521. aFont->mScriptLevel = 0;
  3522. }
  3523. // font-kerning: none, enum, inherit, initial, -moz-system-font
  3524. SetValue(*aRuleData->ValueForFontKerning(),
  3525. aFont->mFont.kerning, aConditions,
  3526. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  3527. aParentFont->mFont.kerning,
  3528. defaultVariableFont->kerning,
  3529. Unused, Unused, Unused, systemFont.kerning);
  3530. // font-synthesis: none, enum (bit field), inherit, initial, -moz-system-font
  3531. SetValue(*aRuleData->ValueForFontSynthesis(),
  3532. aFont->mFont.synthesis, aConditions,
  3533. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  3534. aParentFont->mFont.synthesis,
  3535. defaultVariableFont->synthesis,
  3536. Unused, /* none */ 0, Unused, systemFont.synthesis);
  3537. // font-variant-alternates: normal, enum (bit field) + functions, inherit,
  3538. // initial, -moz-system-font
  3539. const nsCSSValue* variantAlternatesValue =
  3540. aRuleData->ValueForFontVariantAlternates();
  3541. int32_t variantAlternates = 0;
  3542. switch (variantAlternatesValue->GetUnit()) {
  3543. case eCSSUnit_Inherit:
  3544. case eCSSUnit_Unset:
  3545. aFont->mFont.CopyAlternates(aParentFont->mFont);
  3546. aConditions.SetUncacheable();
  3547. break;
  3548. case eCSSUnit_Initial:
  3549. case eCSSUnit_Normal:
  3550. aFont->mFont.variantAlternates = 0;
  3551. aFont->mFont.alternateValues.Clear();
  3552. aFont->mFont.featureValueLookup = nullptr;
  3553. break;
  3554. case eCSSUnit_Pair:
  3555. NS_ASSERTION(variantAlternatesValue->GetPairValue().mXValue.GetUnit() ==
  3556. eCSSUnit_Enumerated, "strange unit for variantAlternates");
  3557. variantAlternates =
  3558. variantAlternatesValue->GetPairValue().mXValue.GetIntValue();
  3559. aFont->mFont.variantAlternates = variantAlternates;
  3560. if (variantAlternates & NS_FONT_VARIANT_ALTERNATES_FUNCTIONAL_MASK) {
  3561. // fetch the feature lookup object from the styleset
  3562. MOZ_ASSERT(aPresContext->StyleSet()->IsGecko(),
  3563. "ServoStyleSets should not have rule nodes");
  3564. aFont->mFont.featureValueLookup =
  3565. aPresContext->StyleSet()->AsGecko()->GetFontFeatureValuesLookup();
  3566. NS_ASSERTION(variantAlternatesValue->GetPairValue().mYValue.GetUnit() ==
  3567. eCSSUnit_List, "function list not a list value");
  3568. nsStyleUtil::ComputeFunctionalAlternates(
  3569. variantAlternatesValue->GetPairValue().mYValue.GetListValue(),
  3570. aFont->mFont.alternateValues);
  3571. }
  3572. break;
  3573. default:
  3574. break;
  3575. }
  3576. // font-variant-caps: normal, enum, inherit, initial, -moz-system-font
  3577. SetValue(*aRuleData->ValueForFontVariantCaps(),
  3578. aFont->mFont.variantCaps, aConditions,
  3579. SETVAL_ENUMERATED |SETVAL_UNSET_INHERIT,
  3580. aParentFont->mFont.variantCaps,
  3581. defaultVariableFont->variantCaps,
  3582. Unused, Unused, /* normal */ 0, systemFont.variantCaps);
  3583. // font-variant-east-asian: normal, enum (bit field), inherit, initial,
  3584. // -moz-system-font
  3585. SetValue(*aRuleData->ValueForFontVariantEastAsian(),
  3586. aFont->mFont.variantEastAsian, aConditions,
  3587. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  3588. aParentFont->mFont.variantEastAsian,
  3589. defaultVariableFont->variantEastAsian,
  3590. Unused, Unused, /* normal */ 0, systemFont.variantEastAsian);
  3591. // font-variant-ligatures: normal, none, enum (bit field), inherit, initial,
  3592. // -moz-system-font
  3593. SetValue(*aRuleData->ValueForFontVariantLigatures(),
  3594. aFont->mFont.variantLigatures, aConditions,
  3595. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  3596. aParentFont->mFont.variantLigatures,
  3597. defaultVariableFont->variantLigatures,
  3598. Unused, NS_FONT_VARIANT_LIGATURES_NONE, /* normal */ 0,
  3599. systemFont.variantLigatures);
  3600. // font-variant-numeric: normal, enum (bit field), inherit, initial,
  3601. // -moz-system-font
  3602. SetValue(*aRuleData->ValueForFontVariantNumeric(),
  3603. aFont->mFont.variantNumeric, aConditions,
  3604. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  3605. aParentFont->mFont.variantNumeric,
  3606. defaultVariableFont->variantNumeric,
  3607. Unused, Unused, /* normal */ 0, systemFont.variantNumeric);
  3608. // font-variant-position: normal, enum, inherit, initial,
  3609. // -moz-system-font
  3610. SetValue(*aRuleData->ValueForFontVariantPosition(),
  3611. aFont->mFont.variantPosition, aConditions,
  3612. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  3613. aParentFont->mFont.variantPosition,
  3614. defaultVariableFont->variantPosition,
  3615. Unused, Unused, /* normal */ 0, systemFont.variantPosition);
  3616. // font-feature-settings
  3617. const nsCSSValue* featureSettingsValue =
  3618. aRuleData->ValueForFontFeatureSettings();
  3619. switch (featureSettingsValue->GetUnit()) {
  3620. case eCSSUnit_Null:
  3621. break;
  3622. case eCSSUnit_Normal:
  3623. case eCSSUnit_Initial:
  3624. aFont->mFont.fontFeatureSettings.Clear();
  3625. break;
  3626. case eCSSUnit_Inherit:
  3627. case eCSSUnit_Unset:
  3628. aConditions.SetUncacheable();
  3629. aFont->mFont.fontFeatureSettings = aParentFont->mFont.fontFeatureSettings;
  3630. break;
  3631. case eCSSUnit_System_Font:
  3632. aFont->mFont.fontFeatureSettings = systemFont.fontFeatureSettings;
  3633. break;
  3634. case eCSSUnit_PairList:
  3635. case eCSSUnit_PairListDep:
  3636. ComputeFontFeatures(featureSettingsValue->GetPairListValue(),
  3637. aFont->mFont.fontFeatureSettings);
  3638. break;
  3639. default:
  3640. MOZ_ASSERT(false, "unexpected value unit");
  3641. break;
  3642. }
  3643. // font-language-override
  3644. const nsCSSValue* languageOverrideValue =
  3645. aRuleData->ValueForFontLanguageOverride();
  3646. if (eCSSUnit_Inherit == languageOverrideValue->GetUnit() ||
  3647. eCSSUnit_Unset == languageOverrideValue->GetUnit()) {
  3648. aConditions.SetUncacheable();
  3649. aFont->mFont.languageOverride = aParentFont->mFont.languageOverride;
  3650. } else if (eCSSUnit_Normal == languageOverrideValue->GetUnit() ||
  3651. eCSSUnit_Initial == languageOverrideValue->GetUnit()) {
  3652. aFont->mFont.languageOverride.Truncate();
  3653. } else if (eCSSUnit_System_Font == languageOverrideValue->GetUnit()) {
  3654. aFont->mFont.languageOverride = systemFont.languageOverride;
  3655. } else if (eCSSUnit_String == languageOverrideValue->GetUnit()) {
  3656. languageOverrideValue->GetStringValue(aFont->mFont.languageOverride);
  3657. }
  3658. // -moz-min-font-size-ratio: percent, inherit
  3659. const nsCSSValue* minFontSizeRatio = aRuleData->ValueForMinFontSizeRatio();
  3660. switch (minFontSizeRatio->GetUnit()) {
  3661. case eCSSUnit_Null:
  3662. break;
  3663. case eCSSUnit_Unset:
  3664. case eCSSUnit_Inherit:
  3665. aFont->mMinFontSizeRatio = aParentFont->mMinFontSizeRatio;
  3666. aConditions.SetUncacheable();
  3667. break;
  3668. case eCSSUnit_Initial:
  3669. aFont->mMinFontSizeRatio = 100; // 100%
  3670. break;
  3671. case eCSSUnit_Percent: {
  3672. // While percentages are parsed as floating point numbers, we
  3673. // only store an integer in the range [0, 255] since that's all
  3674. // we need for now.
  3675. float percent = minFontSizeRatio->GetPercentValue() * 100;
  3676. if (percent < 0) {
  3677. percent = 0;
  3678. } else if (percent > 255) {
  3679. percent = 255;
  3680. }
  3681. aFont->mMinFontSizeRatio = uint8_t(percent);
  3682. break;
  3683. }
  3684. default:
  3685. MOZ_ASSERT_UNREACHABLE("Unknown unit for -moz-min-font-size-ratio");
  3686. }
  3687. nscoord scriptLevelAdjustedUnconstrainedParentSize;
  3688. // font-size: enum, length, percent, inherit
  3689. nscoord scriptLevelAdjustedParentSize =
  3690. ComputeScriptLevelSize(aFont, aParentFont, aPresContext,
  3691. &scriptLevelAdjustedUnconstrainedParentSize);
  3692. NS_ASSERTION(!aUsedStartStruct || aFont->mScriptUnconstrainedSize == aFont->mSize,
  3693. "If we have a start struct, we should have reset everything coming in here");
  3694. // Compute whether we're affected by scriptMinSize *before* calling
  3695. // SetFontSize, since aParentFont might be the same as aFont. If it
  3696. // is, calling SetFontSize might throw off our calculation.
  3697. bool affectedByScriptMinSize =
  3698. aParentFont->mSize != aParentFont->mScriptUnconstrainedSize ||
  3699. scriptLevelAdjustedParentSize !=
  3700. scriptLevelAdjustedUnconstrainedParentSize;
  3701. SetFontSize(aPresContext, aContext,
  3702. aRuleData, aFont, aParentFont,
  3703. &aFont->mSize,
  3704. systemFont, aParentFont->mSize, scriptLevelAdjustedParentSize,
  3705. aUsedStartStruct, atRoot, aConditions);
  3706. if (!aPresContext->Document()->GetMathMLEnabled()) {
  3707. MOZ_ASSERT(!affectedByScriptMinSize);
  3708. // If MathML is not enabled, we don't need to mark this node as
  3709. // uncacheable. If it becomes enabled, code in
  3710. // nsMathMLElementFactory will rebuild the rule tree and style data
  3711. // when MathML is first enabled (see nsMathMLElement::BindToTree).
  3712. aFont->mScriptUnconstrainedSize = aFont->mSize;
  3713. } else if (!affectedByScriptMinSize) {
  3714. // Fast path: we have not been affected by scriptminsize so we don't
  3715. // need to call SetFontSize again to compute the
  3716. // scriptminsize-unconstrained size. This is OK even if we have a
  3717. // start struct, because if we have a start struct then 'font-size'
  3718. // was specified and so scriptminsize has no effect.
  3719. aFont->mScriptUnconstrainedSize = aFont->mSize;
  3720. // It's possible we could, in the future, have a different parent,
  3721. // which would lead to a different affectedByScriptMinSize.
  3722. aConditions.SetUncacheable();
  3723. } else {
  3724. // see previous else-if
  3725. aConditions.SetUncacheable();
  3726. // Use a separate conditions object because it might get a
  3727. // *different* font-size dependency. We can ignore it because we've
  3728. // already called SetUncacheable.
  3729. RuleNodeCacheConditions unconstrainedConditions;
  3730. SetFontSize(aPresContext, aContext,
  3731. aRuleData, aFont, aParentFont,
  3732. &aFont->mScriptUnconstrainedSize,
  3733. systemFont, aParentFont->mScriptUnconstrainedSize,
  3734. scriptLevelAdjustedUnconstrainedParentSize,
  3735. aUsedStartStruct, atRoot, unconstrainedConditions);
  3736. }
  3737. NS_ASSERTION(aFont->mScriptUnconstrainedSize <= aFont->mSize,
  3738. "scriptminsize should never be making things bigger");
  3739. nscoord fontSize = aFont->mSize;
  3740. // enforce the user' specified minimum font-size on the value that we expose
  3741. // (but don't change font-size:0, since that would unhide hidden text)
  3742. if (fontSize > 0) {
  3743. nscoord minFontSize = aPresContext->MinFontSize(aFont->mLanguage);
  3744. if (minFontSize < 0) {
  3745. minFontSize = 0;
  3746. } else {
  3747. minFontSize = (minFontSize * aFont->mMinFontSizeRatio) / 100;
  3748. }
  3749. if (fontSize < minFontSize && !aPresContext->IsChrome()) {
  3750. // override the minimum font-size constraint
  3751. fontSize = minFontSize;
  3752. }
  3753. }
  3754. aFont->mFont.size = fontSize;
  3755. // font-size-adjust: number, none, inherit, initial, -moz-system-font
  3756. const nsCSSValue* sizeAdjustValue = aRuleData->ValueForFontSizeAdjust();
  3757. if (eCSSUnit_System_Font == sizeAdjustValue->GetUnit()) {
  3758. aFont->mFont.sizeAdjust = systemFont.sizeAdjust;
  3759. } else {
  3760. SetFactor(*sizeAdjustValue, aFont->mFont.sizeAdjust,
  3761. aConditions, aParentFont->mFont.sizeAdjust, -1.0f,
  3762. SETFCT_NONE | SETFCT_UNSET_INHERIT);
  3763. }
  3764. }
  3765. /* static */ void
  3766. nsRuleNode::ComputeFontFeatures(const nsCSSValuePairList *aFeaturesList,
  3767. nsTArray<gfxFontFeature>& aFeatureSettings)
  3768. {
  3769. aFeatureSettings.Clear();
  3770. for (const nsCSSValuePairList* p = aFeaturesList; p; p = p->mNext) {
  3771. gfxFontFeature feat = {0, 0};
  3772. MOZ_ASSERT(aFeaturesList->mXValue.GetUnit() == eCSSUnit_String,
  3773. "unexpected value unit");
  3774. // tag is a 4-byte ASCII sequence
  3775. nsAutoString tag;
  3776. p->mXValue.GetStringValue(tag);
  3777. if (tag.Length() != 4) {
  3778. continue;
  3779. }
  3780. // parsing validates that these are ASCII chars
  3781. // tags are always big-endian
  3782. feat.mTag = (tag[0] << 24) | (tag[1] << 16) | (tag[2] << 8) | tag[3];
  3783. // value
  3784. NS_ASSERTION(p->mYValue.GetUnit() == eCSSUnit_Integer,
  3785. "should have found an integer unit");
  3786. feat.mValue = p->mYValue.GetIntValue();
  3787. aFeatureSettings.AppendElement(feat);
  3788. }
  3789. }
  3790. // This should die (bug 380915).
  3791. //
  3792. // SetGenericFont:
  3793. // - backtrack to an ancestor with the same generic font name (possibly
  3794. // up to the root where default values come from the presentation context)
  3795. // - re-apply cascading rules from there without caching intermediate values
  3796. /* static */ void
  3797. nsRuleNode::SetGenericFont(nsPresContext* aPresContext,
  3798. nsStyleContext* aContext,
  3799. uint8_t aGenericFontID,
  3800. nsStyleFont* aFont)
  3801. {
  3802. // walk up the contexts until a context with the desired generic font
  3803. AutoTArray<nsStyleContext*, 8> contextPath;
  3804. contextPath.AppendElement(aContext);
  3805. nsStyleContext* higherContext = aContext->GetParent();
  3806. while (higherContext) {
  3807. if (higherContext->StyleFont()->mGenericID == aGenericFontID) {
  3808. // done walking up the higher contexts
  3809. break;
  3810. }
  3811. contextPath.AppendElement(higherContext);
  3812. higherContext = higherContext->GetParent();
  3813. }
  3814. // re-apply the cascading rules, starting from the higher context
  3815. // If we stopped earlier because we reached the root of the style tree,
  3816. // we will start with the default generic font from the presentation
  3817. // context. Otherwise we start with the higher context.
  3818. const nsFont* defaultFont =
  3819. aPresContext->GetDefaultFont(aGenericFontID, aFont->mLanguage);
  3820. nsStyleFont parentFont(*defaultFont, aPresContext);
  3821. if (higherContext) {
  3822. const nsStyleFont* tmpFont = higherContext->StyleFont();
  3823. parentFont = *tmpFont;
  3824. }
  3825. *aFont = parentFont;
  3826. uint32_t fontBit = nsCachedStyleData::GetBitForSID(eStyleStruct_Font);
  3827. // use placement new[] on the result of alloca() to allocate a
  3828. // variable-sized stack array, including execution of constructors,
  3829. // and use an RAII class to run the destructors too.
  3830. size_t nprops = nsCSSProps::PropertyCountInStruct(eStyleStruct_Font);
  3831. void* dataStorage = alloca(nprops * sizeof(nsCSSValue));
  3832. for (int32_t i = contextPath.Length() - 1; i >= 0; --i) {
  3833. nsStyleContext* context = contextPath[i];
  3834. AutoCSSValueArray dataArray(dataStorage, nprops);
  3835. nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Font), dataArray.get(),
  3836. aPresContext, context);
  3837. ruleData.mValueOffsets[eStyleStruct_Font] = 0;
  3838. // Trimmed down version of ::WalkRuleTree() to re-apply the style rules
  3839. // Note that we *do* need to do this for our own data, since what is
  3840. // in |fontData| in ComputeFontData is only for the rules below
  3841. // aStartStruct.
  3842. for (nsRuleNode* ruleNode = context->RuleNode(); ruleNode;
  3843. ruleNode = ruleNode->GetParent()) {
  3844. if (ruleNode->mNoneBits & fontBit) {
  3845. // no more font rules on this branch, get out
  3846. break;
  3847. }
  3848. nsIStyleRule *rule = ruleNode->GetRule();
  3849. if (rule) {
  3850. ruleData.mLevel = ruleNode->GetLevel();
  3851. ruleData.mIsImportantRule = ruleNode->IsImportantRule();
  3852. rule->MapRuleInfoInto(&ruleData);
  3853. }
  3854. }
  3855. // Compute the delta from the information that the rules specified
  3856. // Avoid unnecessary operations in SetFont(). But we care if it's
  3857. // the final value that we're computing.
  3858. if (i != 0) {
  3859. ruleData.ValueForFontFamily()->Reset();
  3860. }
  3861. ResolveVariableReferences(eStyleStruct_Font, &ruleData, aContext);
  3862. RuleNodeCacheConditions dummy;
  3863. nsRuleNode::SetFont(aPresContext, context,
  3864. aGenericFontID, &ruleData, &parentFont, aFont,
  3865. false, dummy);
  3866. parentFont = *aFont;
  3867. }
  3868. if (higherContext && contextPath.Length() > 1) {
  3869. // contextPath is a list of all ancestor style contexts, so it must have
  3870. // at least two elements for it to result in a dependency on grandancestor
  3871. // styles.
  3872. PropagateGrandancestorBit(aContext, higherContext);
  3873. }
  3874. }
  3875. const void*
  3876. nsRuleNode::ComputeFontData(void* aStartStruct,
  3877. const nsRuleData* aRuleData,
  3878. nsStyleContext* aContext,
  3879. nsRuleNode* aHighestNode,
  3880. const RuleDetail aRuleDetail,
  3881. const RuleNodeCacheConditions aConditions)
  3882. {
  3883. COMPUTE_START_INHERITED(Font, font, parentFont)
  3884. // NOTE: The |aRuleDetail| passed in is a little bit conservative due
  3885. // to the -moz-system-font property. We really don't need to consider
  3886. // it here in determining whether to cache in the rule tree. However,
  3887. // we do need to consider it in WalkRuleTree when deciding whether to
  3888. // walk further up the tree. So this means that when the font struct
  3889. // is fully specified using *longhand* properties (excluding
  3890. // -moz-system-font), we won't cache in the rule tree even though we
  3891. // could. However, it's pretty unlikely authors will do that
  3892. // (although there is a pretty good chance they'll fully specify it
  3893. // using the 'font' shorthand).
  3894. // Figure out if we are a generic font
  3895. uint8_t generic = kGenericFont_NONE;
  3896. // XXXldb What if we would have had a string if we hadn't been doing
  3897. // the optimization with a non-null aStartStruct?
  3898. const nsCSSValue* familyValue = aRuleData->ValueForFontFamily();
  3899. if (eCSSUnit_FontFamilyList == familyValue->GetUnit()) {
  3900. const FontFamilyList* fontlist = familyValue->GetFontFamilyListValue();
  3901. FontFamilyList& fl = font->mFont.fontlist;
  3902. fl = *fontlist;
  3903. // extract the first generic in the fontlist, if exists
  3904. FontFamilyType fontType = fontlist->FirstGeneric();
  3905. // if only a single generic, set the generic type
  3906. if (fontlist->Length() == 1) {
  3907. switch (fontType) {
  3908. case eFamily_serif:
  3909. generic = kGenericFont_serif;
  3910. break;
  3911. case eFamily_sans_serif:
  3912. generic = kGenericFont_sans_serif;
  3913. break;
  3914. case eFamily_monospace:
  3915. generic = kGenericFont_monospace;
  3916. break;
  3917. case eFamily_cursive:
  3918. generic = kGenericFont_cursive;
  3919. break;
  3920. case eFamily_fantasy:
  3921. generic = kGenericFont_fantasy;
  3922. break;
  3923. case eFamily_moz_fixed:
  3924. generic = kGenericFont_moz_fixed;
  3925. break;
  3926. default:
  3927. break;
  3928. }
  3929. }
  3930. }
  3931. // Now compute our font struct
  3932. if (generic == kGenericFont_NONE) {
  3933. // continue the normal processing
  3934. nsRuleNode::SetFont(mPresContext, aContext, generic,
  3935. aRuleData, parentFont, font,
  3936. aStartStruct != nullptr, conditions);
  3937. } else {
  3938. // re-calculate the font as a generic font
  3939. conditions.SetUncacheable();
  3940. nsRuleNode::SetGenericFont(mPresContext, aContext, generic,
  3941. font);
  3942. }
  3943. COMPUTE_END_INHERITED(Font, font)
  3944. }
  3945. template <typename T>
  3946. inline uint32_t ListLength(const T* aList)
  3947. {
  3948. uint32_t len = 0;
  3949. while (aList) {
  3950. len++;
  3951. aList = aList->mNext;
  3952. }
  3953. return len;
  3954. }
  3955. static already_AddRefed<nsCSSShadowArray>
  3956. GetShadowData(const nsCSSValueList* aList,
  3957. nsStyleContext* aContext,
  3958. bool aIsBoxShadow,
  3959. nsPresContext* aPresContext,
  3960. RuleNodeCacheConditions& aConditions)
  3961. {
  3962. uint32_t arrayLength = ListLength(aList);
  3963. MOZ_ASSERT(arrayLength > 0,
  3964. "Non-null text-shadow list, yet we counted 0 items.");
  3965. RefPtr<nsCSSShadowArray> shadowList =
  3966. new(arrayLength) nsCSSShadowArray(arrayLength);
  3967. if (!shadowList) {
  3968. return nullptr;
  3969. }
  3970. nsStyleCoord tempCoord;
  3971. DebugOnly<bool> unitOK;
  3972. for (nsCSSShadowItem* item = shadowList->ShadowAt(0);
  3973. aList;
  3974. aList = aList->mNext, ++item) {
  3975. MOZ_ASSERT(aList->mValue.GetUnit() == eCSSUnit_Array,
  3976. "expecting a plain array value");
  3977. nsCSSValue::Array *arr = aList->mValue.GetArrayValue();
  3978. // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
  3979. unitOK = SetCoord(arr->Item(0), tempCoord, nsStyleCoord(),
  3980. SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
  3981. aContext, aPresContext, aConditions);
  3982. NS_ASSERTION(unitOK, "unexpected unit");
  3983. item->mXOffset = tempCoord.GetCoordValue();
  3984. unitOK = SetCoord(arr->Item(1), tempCoord, nsStyleCoord(),
  3985. SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
  3986. aContext, aPresContext, aConditions);
  3987. NS_ASSERTION(unitOK, "unexpected unit");
  3988. item->mYOffset = tempCoord.GetCoordValue();
  3989. // Blur radius is optional in the current box-shadow spec
  3990. if (arr->Item(2).GetUnit() != eCSSUnit_Null) {
  3991. unitOK = SetCoord(arr->Item(2), tempCoord, nsStyleCoord(),
  3992. SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY |
  3993. SETCOORD_CALC_CLAMP_NONNEGATIVE,
  3994. aContext, aPresContext, aConditions);
  3995. NS_ASSERTION(unitOK, "unexpected unit");
  3996. item->mRadius = tempCoord.GetCoordValue();
  3997. } else {
  3998. item->mRadius = 0;
  3999. }
  4000. // Find the spread radius
  4001. if (aIsBoxShadow && arr->Item(3).GetUnit() != eCSSUnit_Null) {
  4002. unitOK = SetCoord(arr->Item(3), tempCoord, nsStyleCoord(),
  4003. SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
  4004. aContext, aPresContext, aConditions);
  4005. NS_ASSERTION(unitOK, "unexpected unit");
  4006. item->mSpread = tempCoord.GetCoordValue();
  4007. } else {
  4008. item->mSpread = 0;
  4009. }
  4010. if (arr->Item(4).GetUnit() != eCSSUnit_Null) {
  4011. item->mHasColor = true;
  4012. // 2nd argument can be bogus since inherit is not a valid color
  4013. unitOK = SetColor(arr->Item(4), 0, aPresContext, aContext, item->mColor,
  4014. aConditions);
  4015. NS_ASSERTION(unitOK, "unexpected unit");
  4016. }
  4017. if (aIsBoxShadow && arr->Item(5).GetUnit() == eCSSUnit_Enumerated) {
  4018. NS_ASSERTION(arr->Item(5).GetIntValue()
  4019. == uint8_t(StyleBoxShadowType::Inset),
  4020. "invalid keyword type for box shadow");
  4021. item->mInset = true;
  4022. } else {
  4023. item->mInset = false;
  4024. }
  4025. }
  4026. return shadowList.forget();
  4027. }
  4028. struct TextEmphasisChars
  4029. {
  4030. const char16_t* mFilled;
  4031. const char16_t* mOpen;
  4032. };
  4033. #define TEXT_EMPHASIS_CHARS_LIST() \
  4034. TEXT_EMPHASIS_CHARS_ITEM(u"", u"", NONE) \
  4035. TEXT_EMPHASIS_CHARS_ITEM(u"\u2022", u"\u25e6", DOT) \
  4036. TEXT_EMPHASIS_CHARS_ITEM(u"\u25cf", u"\u25cb", CIRCLE) \
  4037. TEXT_EMPHASIS_CHARS_ITEM(u"\u25c9", u"\u25ce", DOUBLE_CIRCLE) \
  4038. TEXT_EMPHASIS_CHARS_ITEM(u"\u25b2", u"\u25b3", TRIANGLE) \
  4039. TEXT_EMPHASIS_CHARS_ITEM(u"\ufe45", u"\ufe46", SESAME)
  4040. static constexpr TextEmphasisChars kTextEmphasisChars[] =
  4041. {
  4042. #define TEXT_EMPHASIS_CHARS_ITEM(filled_, open_, type_) \
  4043. { filled_, open_ }, // type_
  4044. TEXT_EMPHASIS_CHARS_LIST()
  4045. #undef TEXT_EMPHASIS_CHARS_ITEM
  4046. };
  4047. #define TEXT_EMPHASIS_CHARS_ITEM(filled_, open_, type_) \
  4048. static_assert(ArrayLength(filled_) <= 2 && \
  4049. ArrayLength(open_) <= 2, \
  4050. "emphasis marks should have no more than one char"); \
  4051. static_assert( \
  4052. *kTextEmphasisChars[NS_STYLE_TEXT_EMPHASIS_STYLE_##type_].mFilled == \
  4053. *filled_, "filled " #type_ " should be " #filled_); \
  4054. static_assert( \
  4055. *kTextEmphasisChars[NS_STYLE_TEXT_EMPHASIS_STYLE_##type_].mOpen == \
  4056. *open_, "open " #type_ " should be " #open_);
  4057. TEXT_EMPHASIS_CHARS_LIST()
  4058. #undef TEXT_EMPHASIS_CHARS_ITEM
  4059. #undef TEXT_EMPHASIS_CHARS_LIST
  4060. static void
  4061. TruncateStringToSingleGrapheme(nsAString& aStr)
  4062. {
  4063. unicode::ClusterIterator iter(aStr.Data(), aStr.Length());
  4064. if (!iter.AtEnd()) {
  4065. iter.Next();
  4066. if (!iter.AtEnd()) {
  4067. // Not mutating the string for common cases helps memory use
  4068. // since we share the buffer from the specified style into the
  4069. // computed style.
  4070. aStr.Truncate(iter - aStr.Data());
  4071. }
  4072. }
  4073. }
  4074. struct LengthNumberCalcObj
  4075. {
  4076. float mValue;
  4077. bool mIsNumber;
  4078. };
  4079. struct RealNumberComputedCalc
  4080. {
  4081. // We use float for mLength, so it can support real numbers.
  4082. float mLength = 0.0f;
  4083. float mPercent = 0.0f;
  4084. bool mIsNumber = false;
  4085. };
  4086. struct LengthNumberCalcOps : public css::NumbersAlreadyNormalizedOps
  4087. {
  4088. typedef LengthNumberCalcObj result_type;
  4089. nsStyleContext* const mStyleContext;
  4090. nsPresContext* const mPresContext;
  4091. RuleNodeCacheConditions& mConditions;
  4092. LengthNumberCalcOps(nsStyleContext* aStyleContext,
  4093. nsPresContext* aPresContext,
  4094. RuleNodeCacheConditions& aConditions)
  4095. : mStyleContext(aStyleContext),
  4096. mPresContext(aPresContext),
  4097. mConditions(aConditions)
  4098. {
  4099. }
  4100. result_type
  4101. MergeAdditive(nsCSSUnit aCalcFunction,
  4102. result_type aValue1, result_type aValue2)
  4103. {
  4104. MOZ_ASSERT(aValue1.mIsNumber == aValue2.mIsNumber);
  4105. LengthNumberCalcObj result;
  4106. result.mIsNumber = aValue1.mIsNumber;
  4107. if (aCalcFunction == eCSSUnit_Calc_Plus) {
  4108. result.mValue = aValue1.mValue + aValue2.mValue;
  4109. return result;
  4110. }
  4111. MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Minus,
  4112. "unexpected unit");
  4113. result.mValue = aValue1.mValue - aValue2.mValue;
  4114. return result;
  4115. }
  4116. result_type
  4117. MergeMultiplicativeL(nsCSSUnit aCalcFunction,
  4118. float aValue1, result_type aValue2)
  4119. {
  4120. MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Times_L,
  4121. "unexpected unit");
  4122. LengthNumberCalcObj result;
  4123. result.mIsNumber = aValue2.mIsNumber;
  4124. result.mValue = aValue1 * aValue2.mValue;
  4125. return result;
  4126. }
  4127. result_type
  4128. MergeMultiplicativeR(nsCSSUnit aCalcFunction,
  4129. result_type aValue1, float aValue2)
  4130. {
  4131. LengthNumberCalcObj result;
  4132. result.mIsNumber = aValue1.mIsNumber;
  4133. if (aCalcFunction == eCSSUnit_Calc_Times_R) {
  4134. result.mValue = aValue1.mValue * aValue2;
  4135. return result;
  4136. }
  4137. MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Divided,
  4138. "unexpected unit");
  4139. result.mValue = aValue1.mValue / aValue2;
  4140. return result;
  4141. }
  4142. result_type ComputeLeafValue(const nsCSSValue& aValue)
  4143. {
  4144. LengthNumberCalcObj result;
  4145. if (aValue.IsLengthUnit()) {
  4146. result.mIsNumber = false;
  4147. result.mValue = CalcLength(aValue, mStyleContext,
  4148. mPresContext, mConditions);
  4149. } else if (eCSSUnit_Number == aValue.GetUnit()) {
  4150. result.mIsNumber = true;
  4151. result.mValue = aValue.GetFloatValue();
  4152. } else {
  4153. MOZ_ASSERT(false, "unexpected value");
  4154. result.mIsNumber = true;
  4155. result.mValue = 1.0f;
  4156. }
  4157. return result;
  4158. }
  4159. };
  4160. // This is like LengthNumberCalcOps, but then for real/float.
  4161. struct LengthPercentNumberCalcOps : public css::NumbersAlreadyNormalizedOps
  4162. {
  4163. typedef RealNumberComputedCalc result_type;
  4164. nsStyleContext* const mContext;
  4165. nsPresContext* const mPresContext;
  4166. RuleNodeCacheConditions& mConditions;
  4167. bool mHasPercent = false;
  4168. LengthPercentNumberCalcOps(nsStyleContext* aContext,
  4169. nsPresContext* aPresContext,
  4170. RuleNodeCacheConditions& aConditions)
  4171. : mContext(aContext),
  4172. mPresContext(aPresContext),
  4173. mConditions(aConditions) { }
  4174. result_type
  4175. MergeAdditive(nsCSSUnit aCalcFunction,
  4176. result_type aValue1, result_type aValue2)
  4177. {
  4178. MOZ_ASSERT(aValue1.mIsNumber == aValue2.mIsNumber);
  4179. MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Plus ||
  4180. aCalcFunction == eCSSUnit_Calc_Minus,
  4181. "unexpected unit");
  4182. result_type result;
  4183. result.mIsNumber = aValue1.mIsNumber;
  4184. if (aCalcFunction == eCSSUnit_Calc_Plus) {
  4185. result.mLength = aValue1.mLength + aValue2.mLength;
  4186. result.mPercent = aValue1.mPercent + aValue2.mPercent;
  4187. } else {
  4188. result.mLength = aValue2.mLength == NS_IEEEPositiveInfinity() ?
  4189. 0.0f :
  4190. aValue1.mLength - aValue2.mLength;
  4191. result.mPercent = aValue1.mPercent - aValue2.mPercent;
  4192. }
  4193. return result;
  4194. }
  4195. result_type
  4196. MergeMultiplicativeL(nsCSSUnit aCalcFunction,
  4197. float aValue1, result_type aValue2)
  4198. {
  4199. MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Times_L,
  4200. "unexpected unit");
  4201. result_type result;
  4202. result.mLength = aValue1 * aValue2.mLength;
  4203. result.mPercent = aValue1 * aValue2.mPercent;
  4204. result.mIsNumber = aValue2.mIsNumber;
  4205. return result;
  4206. }
  4207. result_type
  4208. MergeMultiplicativeR(nsCSSUnit aCalcFunction,
  4209. result_type aValue1, float aValue2)
  4210. {
  4211. MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Times_R ||
  4212. aCalcFunction == eCSSUnit_Calc_Divided,
  4213. "unexpected unit");
  4214. result_type result;
  4215. if (aCalcFunction == eCSSUnit_Calc_Divided) {
  4216. aValue2 = 1.0f / aValue2;
  4217. }
  4218. result.mLength = aValue1.mLength * aValue2;
  4219. result.mPercent = aValue1.mPercent * aValue2;
  4220. result.mIsNumber = aValue1.mIsNumber;
  4221. return result;
  4222. }
  4223. result_type
  4224. ComputeLeafValue(const nsCSSValue& aValue)
  4225. {
  4226. result_type result;
  4227. if (aValue.IsLengthUnit()) {
  4228. result.mLength = CalcLength(aValue, mContext, mPresContext, mConditions);
  4229. } else if (aValue.GetUnit() == eCSSUnit_Percent) {
  4230. result.mPercent = aValue.GetPercentValue();
  4231. mHasPercent = true;
  4232. } else if (aValue.GetUnit() == eCSSUnit_Number) {
  4233. result.mLength = aValue.GetFloatValue();
  4234. result.mIsNumber = true;
  4235. } else {
  4236. MOZ_ASSERT_UNREACHABLE("unexpected unit");
  4237. result.mLength = CalcLength(aValue, mContext, mPresContext, mConditions);
  4238. }
  4239. return result;
  4240. }
  4241. };
  4242. struct SetLineHeightCalcOps : public LengthNumberCalcOps
  4243. {
  4244. SetLineHeightCalcOps(nsStyleContext* aStyleContext,
  4245. nsPresContext* aPresContext,
  4246. RuleNodeCacheConditions& aConditions)
  4247. : LengthNumberCalcOps(aStyleContext, aPresContext, aConditions)
  4248. {
  4249. }
  4250. result_type ComputeLeafValue(const nsCSSValue& aValue)
  4251. {
  4252. LengthNumberCalcObj result;
  4253. if (aValue.IsLengthUnit()) {
  4254. result.mIsNumber = false;
  4255. result.mValue = CalcLength(aValue, mStyleContext,
  4256. mPresContext, mConditions);
  4257. } else if (eCSSUnit_Percent == aValue.GetUnit()) {
  4258. mConditions.SetUncacheable();
  4259. result.mIsNumber = false;
  4260. nscoord fontSize = mStyleContext->StyleFont()->mFont.size;
  4261. result.mValue = fontSize * aValue.GetPercentValue();
  4262. } else if (eCSSUnit_Number == aValue.GetUnit()) {
  4263. result.mIsNumber = true;
  4264. result.mValue = aValue.GetFloatValue();
  4265. } else {
  4266. MOZ_ASSERT(false, "unexpected value");
  4267. result.mIsNumber = true;
  4268. result.mValue = 1.0f;
  4269. }
  4270. return result;
  4271. }
  4272. };
  4273. const void*
  4274. nsRuleNode::ComputeTextData(void* aStartStruct,
  4275. const nsRuleData* aRuleData,
  4276. nsStyleContext* aContext,
  4277. nsRuleNode* aHighestNode,
  4278. const RuleDetail aRuleDetail,
  4279. const RuleNodeCacheConditions aConditions)
  4280. {
  4281. COMPUTE_START_INHERITED(Text, text, parentText)
  4282. auto setComplexColor = [&](const nsCSSValue* aValue,
  4283. StyleComplexColor nsStyleText::* aField) {
  4284. SetComplexColor<eUnsetInherit>(*aValue, parentText->*aField,
  4285. StyleComplexColor::CurrentColor(),
  4286. mPresContext, text->*aField, conditions);
  4287. };
  4288. // tab-size: number, length, calc, inherit
  4289. const nsCSSValue* tabSizeValue = aRuleData->ValueForTabSize();
  4290. if (tabSizeValue->GetUnit() == eCSSUnit_Initial) {
  4291. text->mTabSize = nsStyleCoord(float(NS_STYLE_TABSIZE_INITIAL), eStyleUnit_Factor);
  4292. } else if (eCSSUnit_Calc == tabSizeValue->GetUnit()) {
  4293. LengthNumberCalcOps ops(aContext, mPresContext, conditions);
  4294. LengthNumberCalcObj obj = css::ComputeCalc(*tabSizeValue, ops);
  4295. float value = obj.mValue < 0 ? 0 : obj.mValue;
  4296. if (obj.mIsNumber) {
  4297. text->mTabSize.SetFactorValue(value);
  4298. } else {
  4299. text->mTabSize.SetCoordValue(
  4300. NSToCoordRoundWithClamp(value));
  4301. }
  4302. } else {
  4303. SetCoord(*tabSizeValue, text->mTabSize, parentText->mTabSize,
  4304. SETCOORD_LH | SETCOORD_FACTOR | SETCOORD_UNSET_INHERIT,
  4305. aContext, mPresContext, conditions);
  4306. }
  4307. // letter-spacing: normal, length, inherit
  4308. SetCoord(*aRuleData->ValueForLetterSpacing(),
  4309. text->mLetterSpacing, parentText->mLetterSpacing,
  4310. SETCOORD_LH | SETCOORD_NORMAL | SETCOORD_INITIAL_NORMAL |
  4311. SETCOORD_CALC_LENGTH_ONLY | SETCOORD_UNSET_INHERIT,
  4312. aContext, mPresContext, conditions);
  4313. // text-shadow: none, list, inherit, initial
  4314. const nsCSSValue* textShadowValue = aRuleData->ValueForTextShadow();
  4315. if (textShadowValue->GetUnit() != eCSSUnit_Null) {
  4316. text->mTextShadow = nullptr;
  4317. // Don't need to handle none/initial explicitly: The above assignment
  4318. // takes care of that
  4319. if (textShadowValue->GetUnit() == eCSSUnit_Inherit ||
  4320. textShadowValue->GetUnit() == eCSSUnit_Unset) {
  4321. conditions.SetUncacheable();
  4322. text->mTextShadow = parentText->mTextShadow;
  4323. } else if (textShadowValue->GetUnit() == eCSSUnit_List ||
  4324. textShadowValue->GetUnit() == eCSSUnit_ListDep) {
  4325. // List of arrays
  4326. text->mTextShadow = GetShadowData(textShadowValue->GetListValue(),
  4327. aContext, false, mPresContext, conditions);
  4328. }
  4329. }
  4330. // line-height: normal, number, length, percent, calc, inherit
  4331. const nsCSSValue* lineHeightValue = aRuleData->ValueForLineHeight();
  4332. if (eCSSUnit_Percent == lineHeightValue->GetUnit()) {
  4333. conditions.SetUncacheable();
  4334. // Use |mFont.size| to pick up minimum font size.
  4335. text->mLineHeight.SetCoordValue(
  4336. NSToCoordRound(float(aContext->StyleFont()->mFont.size) *
  4337. lineHeightValue->GetPercentValue()));
  4338. } else if (eCSSUnit_Initial == lineHeightValue->GetUnit() ||
  4339. eCSSUnit_System_Font == lineHeightValue->GetUnit()) {
  4340. text->mLineHeight.SetNormalValue();
  4341. } else if (eCSSUnit_Calc == lineHeightValue->GetUnit()) {
  4342. SetLineHeightCalcOps ops(aContext, mPresContext, conditions);
  4343. LengthNumberCalcObj obj = css::ComputeCalc(*lineHeightValue, ops);
  4344. if (obj.mIsNumber) {
  4345. text->mLineHeight.SetFactorValue(obj.mValue);
  4346. } else {
  4347. text->mLineHeight.SetCoordValue(
  4348. NSToCoordRoundWithClamp(obj.mValue));
  4349. }
  4350. } else {
  4351. SetCoord(*lineHeightValue, text->mLineHeight, parentText->mLineHeight,
  4352. SETCOORD_LEH | SETCOORD_FACTOR | SETCOORD_NORMAL |
  4353. SETCOORD_UNSET_INHERIT,
  4354. aContext, mPresContext, conditions);
  4355. if (lineHeightValue->IsLengthUnit() &&
  4356. !lineHeightValue->IsRelativeLengthUnit()) {
  4357. nscoord lh = nsStyleFont::ZoomText(mPresContext,
  4358. text->mLineHeight.GetCoordValue());
  4359. conditions.SetUncacheable();
  4360. const nsStyleFont *font = aContext->StyleFont();
  4361. nscoord minimumFontSize = mPresContext->MinFontSize(font->mLanguage);
  4362. if (minimumFontSize > 0 && !mPresContext->IsChrome()) {
  4363. if (font->mSize != 0) {
  4364. lh = nscoord(float(lh) * float(font->mFont.size) / float(font->mSize));
  4365. } else {
  4366. // Never shrink line heights as a result of minFontSize
  4367. lh = std::max(lh, minimumFontSize);
  4368. }
  4369. }
  4370. text->mLineHeight.SetCoordValue(lh);
  4371. }
  4372. }
  4373. // text-align: enum, string, pair(enum|string), inherit, initial
  4374. // NOTE: string is not implemented yet.
  4375. const nsCSSValue* textAlignValue = aRuleData->ValueForTextAlign();
  4376. text->mTextAlignTrue = false;
  4377. if (eCSSUnit_String == textAlignValue->GetUnit()) {
  4378. NS_NOTYETIMPLEMENTED("align string");
  4379. } else if (eCSSUnit_Enumerated == textAlignValue->GetUnit() &&
  4380. NS_STYLE_TEXT_ALIGN_MOZ_CENTER_OR_INHERIT ==
  4381. textAlignValue->GetIntValue()) {
  4382. conditions.SetUncacheable();
  4383. uint8_t parentAlign = parentText->mTextAlign;
  4384. text->mTextAlign = (NS_STYLE_TEXT_ALIGN_START == parentAlign) ?
  4385. NS_STYLE_TEXT_ALIGN_CENTER : parentAlign;
  4386. } else if (eCSSUnit_Enumerated == textAlignValue->GetUnit() &&
  4387. NS_STYLE_TEXT_ALIGN_MATCH_PARENT ==
  4388. textAlignValue->GetIntValue()) {
  4389. conditions.SetUncacheable();
  4390. nsStyleContext* parent = aContext->GetParent();
  4391. if (parent) {
  4392. uint8_t parentAlign = parentText->mTextAlign;
  4393. uint8_t parentDirection = parent->StyleVisibility()->mDirection;
  4394. switch (parentAlign) {
  4395. case NS_STYLE_TEXT_ALIGN_START:
  4396. text->mTextAlign = parentDirection == NS_STYLE_DIRECTION_RTL ?
  4397. NS_STYLE_TEXT_ALIGN_RIGHT : NS_STYLE_TEXT_ALIGN_LEFT;
  4398. break;
  4399. case NS_STYLE_TEXT_ALIGN_END:
  4400. text->mTextAlign = parentDirection == NS_STYLE_DIRECTION_RTL ?
  4401. NS_STYLE_TEXT_ALIGN_LEFT : NS_STYLE_TEXT_ALIGN_RIGHT;
  4402. break;
  4403. default:
  4404. text->mTextAlign = parentAlign;
  4405. }
  4406. }
  4407. } else {
  4408. if (eCSSUnit_Pair == textAlignValue->GetUnit()) {
  4409. // Two values were specified, one must be 'true'.
  4410. text->mTextAlignTrue = true;
  4411. const nsCSSValuePair& textAlignValuePair = textAlignValue->GetPairValue();
  4412. textAlignValue = &textAlignValuePair.mXValue;
  4413. if (eCSSUnit_Enumerated == textAlignValue->GetUnit()) {
  4414. if (textAlignValue->GetIntValue() == NS_STYLE_TEXT_ALIGN_UNSAFE) {
  4415. textAlignValue = &textAlignValuePair.mYValue;
  4416. }
  4417. } else if (eCSSUnit_String == textAlignValue->GetUnit()) {
  4418. NS_NOTYETIMPLEMENTED("align string");
  4419. }
  4420. } else if (eCSSUnit_Inherit == textAlignValue->GetUnit() ||
  4421. eCSSUnit_Unset == textAlignValue->GetUnit()) {
  4422. text->mTextAlignTrue = parentText->mTextAlignTrue;
  4423. }
  4424. SetValue(*textAlignValue, text->mTextAlign, conditions,
  4425. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  4426. parentText->mTextAlign,
  4427. NS_STYLE_TEXT_ALIGN_START);
  4428. }
  4429. // text-align-last: enum, pair(enum), inherit, initial
  4430. const nsCSSValue* textAlignLastValue = aRuleData->ValueForTextAlignLast();
  4431. text->mTextAlignLastTrue = false;
  4432. if (eCSSUnit_Pair == textAlignLastValue->GetUnit()) {
  4433. // Two values were specified, one must be 'true'.
  4434. text->mTextAlignLastTrue = true;
  4435. const nsCSSValuePair& textAlignLastValuePair = textAlignLastValue->GetPairValue();
  4436. textAlignLastValue = &textAlignLastValuePair.mXValue;
  4437. if (eCSSUnit_Enumerated == textAlignLastValue->GetUnit()) {
  4438. if (textAlignLastValue->GetIntValue() == NS_STYLE_TEXT_ALIGN_UNSAFE) {
  4439. textAlignLastValue = &textAlignLastValuePair.mYValue;
  4440. }
  4441. }
  4442. } else if (eCSSUnit_Inherit == textAlignLastValue->GetUnit() ||
  4443. eCSSUnit_Unset == textAlignLastValue->GetUnit()) {
  4444. text->mTextAlignLastTrue = parentText->mTextAlignLastTrue;
  4445. }
  4446. SetValue(*textAlignLastValue, text->mTextAlignLast,
  4447. conditions,
  4448. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  4449. parentText->mTextAlignLast,
  4450. NS_STYLE_TEXT_ALIGN_AUTO);
  4451. // text-indent: length, percent, calc, inherit, initial
  4452. SetCoord(*aRuleData->ValueForTextIndent(), text->mTextIndent, parentText->mTextIndent,
  4453. SETCOORD_LPH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC |
  4454. SETCOORD_UNSET_INHERIT,
  4455. aContext, mPresContext, conditions);
  4456. // text-justify: enum, inherit, initial
  4457. SetValue(*aRuleData->ValueForTextJustify(), text->mTextJustify, conditions,
  4458. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  4459. parentText->mTextJustify,
  4460. StyleTextJustify::Auto);
  4461. // text-transform: enum, inherit, initial
  4462. SetValue(*aRuleData->ValueForTextTransform(), text->mTextTransform, conditions,
  4463. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  4464. parentText->mTextTransform,
  4465. NS_STYLE_TEXT_TRANSFORM_NONE);
  4466. // white-space: enum, inherit, initial
  4467. SetValue(*aRuleData->ValueForWhiteSpace(), text->mWhiteSpace, conditions,
  4468. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  4469. parentText->mWhiteSpace,
  4470. NS_STYLE_WHITESPACE_NORMAL);
  4471. // word-break: enum, inherit, initial
  4472. SetValue(*aRuleData->ValueForWordBreak(), text->mWordBreak, conditions,
  4473. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  4474. parentText->mWordBreak,
  4475. NS_STYLE_WORDBREAK_NORMAL);
  4476. // word-spacing: normal, length, percent, inherit
  4477. const nsCSSValue* wordSpacingValue = aRuleData->ValueForWordSpacing();
  4478. if (wordSpacingValue->GetUnit() == eCSSUnit_Normal) {
  4479. // Do this so that "normal" computes to 0px, as the CSS 2.1 spec requires.
  4480. text->mWordSpacing.SetCoordValue(0);
  4481. } else {
  4482. SetCoord(*aRuleData->ValueForWordSpacing(),
  4483. text->mWordSpacing, parentText->mWordSpacing,
  4484. SETCOORD_LPH | SETCOORD_INITIAL_ZERO |
  4485. SETCOORD_STORE_CALC | SETCOORD_UNSET_INHERIT,
  4486. aContext, mPresContext, conditions);
  4487. }
  4488. // overflow-wrap: enum, inherit, initial
  4489. SetValue(*aRuleData->ValueForOverflowWrap(), text->mOverflowWrap, conditions,
  4490. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  4491. parentText->mOverflowWrap,
  4492. NS_STYLE_OVERFLOWWRAP_NORMAL);
  4493. // hyphens: enum, inherit, initial
  4494. SetValue(*aRuleData->ValueForHyphens(), text->mHyphens, conditions,
  4495. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  4496. parentText->mHyphens,
  4497. NS_STYLE_HYPHENS_MANUAL);
  4498. // ruby-align: enum, inherit, initial
  4499. SetValue(*aRuleData->ValueForRubyAlign(),
  4500. text->mRubyAlign, conditions,
  4501. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  4502. parentText->mRubyAlign,
  4503. NS_STYLE_RUBY_ALIGN_SPACE_AROUND);
  4504. // ruby-position: enum, inherit, initial
  4505. SetValue(*aRuleData->ValueForRubyPosition(),
  4506. text->mRubyPosition, conditions,
  4507. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  4508. parentText->mRubyPosition,
  4509. NS_STYLE_RUBY_POSITION_OVER);
  4510. // text-size-adjust: none, auto, inherit, initial
  4511. SetValue(*aRuleData->ValueForTextSizeAdjust(), text->mTextSizeAdjust,
  4512. conditions, SETVAL_UNSET_INHERIT,
  4513. parentText->mTextSizeAdjust,
  4514. /* initial */ NS_STYLE_TEXT_SIZE_ADJUST_AUTO,
  4515. /* auto */ NS_STYLE_TEXT_SIZE_ADJUST_AUTO,
  4516. /* none */ NS_STYLE_TEXT_SIZE_ADJUST_NONE, Unused, Unused);
  4517. // text-combine-upright: enum, inherit, initial
  4518. SetValue(*aRuleData->ValueForTextCombineUpright(),
  4519. text->mTextCombineUpright,
  4520. conditions,
  4521. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  4522. parentText->mTextCombineUpright,
  4523. NS_STYLE_TEXT_COMBINE_UPRIGHT_NONE);
  4524. // text-emphasis-color: color, string, inherit, initial
  4525. setComplexColor(aRuleData->ValueForTextEmphasisColor(),
  4526. &nsStyleText::mTextEmphasisColor);
  4527. // text-emphasis-position: enum, inherit, initial
  4528. SetValue(*aRuleData->ValueForTextEmphasisPosition(),
  4529. text->mTextEmphasisPosition,
  4530. conditions,
  4531. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  4532. parentText->mTextEmphasisPosition,
  4533. NS_STYLE_TEXT_EMPHASIS_POSITION_OVER |
  4534. NS_STYLE_TEXT_EMPHASIS_POSITION_RIGHT);
  4535. // text-emphasis-style: string, enum, inherit, initial
  4536. const nsCSSValue* textEmphasisStyleValue =
  4537. aRuleData->ValueForTextEmphasisStyle();
  4538. switch (textEmphasisStyleValue->GetUnit()) {
  4539. case eCSSUnit_Null:
  4540. break;
  4541. case eCSSUnit_Initial:
  4542. case eCSSUnit_None: {
  4543. text->mTextEmphasisStyle = NS_STYLE_TEXT_EMPHASIS_STYLE_NONE;
  4544. text->mTextEmphasisStyleString = u"";
  4545. break;
  4546. }
  4547. case eCSSUnit_Inherit:
  4548. case eCSSUnit_Unset: {
  4549. conditions.SetUncacheable();
  4550. text->mTextEmphasisStyle = parentText->mTextEmphasisStyle;
  4551. text->mTextEmphasisStyleString = parentText->mTextEmphasisStyleString;
  4552. break;
  4553. }
  4554. case eCSSUnit_Enumerated: {
  4555. auto style = textEmphasisStyleValue->GetIntValue();
  4556. // If shape part is not specified, compute it according to the
  4557. // writing-mode. Note that, if the fill part (filled/open) is not
  4558. // specified, we compute it to filled per spec. Since that value
  4559. // is zero, no additional computation is needed. See the assertion
  4560. // in CSSParserImpl::ParseTextEmphasisStyle().
  4561. if (!(style & NS_STYLE_TEXT_EMPHASIS_STYLE_SHAPE_MASK)) {
  4562. conditions.SetUncacheable();
  4563. if (WritingMode(aContext).IsVertical()) {
  4564. style |= NS_STYLE_TEXT_EMPHASIS_STYLE_SESAME;
  4565. } else {
  4566. style |= NS_STYLE_TEXT_EMPHASIS_STYLE_CIRCLE;
  4567. }
  4568. }
  4569. text->mTextEmphasisStyle = style;
  4570. size_t shape = style & NS_STYLE_TEXT_EMPHASIS_STYLE_SHAPE_MASK;
  4571. MOZ_ASSERT(shape > 0 && shape < ArrayLength(kTextEmphasisChars));
  4572. const TextEmphasisChars& chars = kTextEmphasisChars[shape];
  4573. text->mTextEmphasisStyleString =
  4574. (style & NS_STYLE_TEXT_EMPHASIS_STYLE_FILL_MASK) ==
  4575. NS_STYLE_TEXT_EMPHASIS_STYLE_FILLED ? chars.mFilled : chars.mOpen;
  4576. break;
  4577. }
  4578. case eCSSUnit_String: {
  4579. text->mTextEmphasisStyle = NS_STYLE_TEXT_EMPHASIS_STYLE_STRING;
  4580. nsString strValue;
  4581. textEmphasisStyleValue->GetStringValue(strValue);
  4582. TruncateStringToSingleGrapheme(strValue);
  4583. text->mTextEmphasisStyleString = strValue;
  4584. break;
  4585. }
  4586. default:
  4587. MOZ_ASSERT_UNREACHABLE("Unknown value unit type");
  4588. }
  4589. // text-rendering: enum, inherit, initial
  4590. SetValue(*aRuleData->ValueForTextRendering(),
  4591. text->mTextRendering, conditions,
  4592. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  4593. parentText->mTextRendering,
  4594. NS_STYLE_TEXT_RENDERING_AUTO);
  4595. // -webkit-text-fill-color: color, string, inherit, initial
  4596. setComplexColor(aRuleData->ValueForWebkitTextFillColor(),
  4597. &nsStyleText::mWebkitTextFillColor);
  4598. // -webkit-text-stroke-color: color, string, inherit, initial
  4599. setComplexColor(aRuleData->ValueForWebkitTextStrokeColor(),
  4600. &nsStyleText::mWebkitTextStrokeColor);
  4601. // -webkit-text-stroke-width: length, inherit, initial, enum
  4602. const nsCSSValue*
  4603. webkitTextStrokeWidthValue = aRuleData->ValueForWebkitTextStrokeWidth();
  4604. if (webkitTextStrokeWidthValue->GetUnit() == eCSSUnit_Enumerated) {
  4605. NS_ASSERTION(webkitTextStrokeWidthValue->GetIntValue() == NS_STYLE_BORDER_WIDTH_THIN ||
  4606. webkitTextStrokeWidthValue->GetIntValue() == NS_STYLE_BORDER_WIDTH_MEDIUM ||
  4607. webkitTextStrokeWidthValue->GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK,
  4608. "Unexpected enum value");
  4609. text->mWebkitTextStrokeWidth.SetCoordValue(
  4610. mPresContext->GetBorderWidthTable()[webkitTextStrokeWidthValue->GetIntValue()]);
  4611. } else {
  4612. SetCoord(*webkitTextStrokeWidthValue, text->mWebkitTextStrokeWidth,
  4613. parentText->mWebkitTextStrokeWidth,
  4614. SETCOORD_LH | SETCOORD_CALC_LENGTH_ONLY |
  4615. SETCOORD_CALC_CLAMP_NONNEGATIVE |
  4616. SETCOORD_INITIAL_ZERO | SETCOORD_UNSET_INHERIT,
  4617. aContext, mPresContext, conditions);
  4618. }
  4619. // -moz-control-character-visibility: enum, inherit, initial
  4620. SetValue(*aRuleData->ValueForControlCharacterVisibility(),
  4621. text->mControlCharacterVisibility,
  4622. conditions,
  4623. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  4624. parentText->mControlCharacterVisibility,
  4625. nsCSSParser::ControlCharVisibilityDefault());
  4626. COMPUTE_END_INHERITED(Text, text)
  4627. }
  4628. const void*
  4629. nsRuleNode::ComputeTextResetData(void* aStartStruct,
  4630. const nsRuleData* aRuleData,
  4631. nsStyleContext* aContext,
  4632. nsRuleNode* aHighestNode,
  4633. const RuleDetail aRuleDetail,
  4634. const RuleNodeCacheConditions aConditions)
  4635. {
  4636. COMPUTE_START_RESET(TextReset, text, parentText)
  4637. // text-decoration-line: enum (bit field), inherit, initial
  4638. const nsCSSValue* decorationLineValue =
  4639. aRuleData->ValueForTextDecorationLine();
  4640. if (eCSSUnit_Enumerated == decorationLineValue->GetUnit()) {
  4641. int32_t td = decorationLineValue->GetIntValue();
  4642. text->mTextDecorationLine = td;
  4643. if (td & NS_STYLE_TEXT_DECORATION_LINE_PREF_ANCHORS) {
  4644. bool underlineLinks =
  4645. mPresContext->GetCachedBoolPref(kPresContext_UnderlineLinks);
  4646. if (underlineLinks) {
  4647. text->mTextDecorationLine |= NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
  4648. } else {
  4649. text->mTextDecorationLine &= ~NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
  4650. }
  4651. }
  4652. } else if (eCSSUnit_Inherit == decorationLineValue->GetUnit()) {
  4653. conditions.SetUncacheable();
  4654. text->mTextDecorationLine = parentText->mTextDecorationLine;
  4655. } else if (eCSSUnit_Initial == decorationLineValue->GetUnit() ||
  4656. eCSSUnit_Unset == decorationLineValue->GetUnit()) {
  4657. text->mTextDecorationLine = NS_STYLE_TEXT_DECORATION_LINE_NONE;
  4658. }
  4659. // text-decoration-color: color, string, enum, inherit, initial
  4660. SetComplexColor<eUnsetInitial>(*aRuleData->ValueForTextDecorationColor(),
  4661. parentText->mTextDecorationColor,
  4662. StyleComplexColor::CurrentColor(),
  4663. mPresContext,
  4664. text->mTextDecorationColor, conditions);
  4665. // text-decoration-style: enum, inherit, initial
  4666. const nsCSSValue* decorationStyleValue =
  4667. aRuleData->ValueForTextDecorationStyle();
  4668. if (eCSSUnit_Enumerated == decorationStyleValue->GetUnit()) {
  4669. text->mTextDecorationStyle = decorationStyleValue->GetIntValue();
  4670. } else if (eCSSUnit_Inherit == decorationStyleValue->GetUnit()) {
  4671. text->mTextDecorationStyle = parentText->mTextDecorationStyle;
  4672. conditions.SetUncacheable();
  4673. } else if (eCSSUnit_Initial == decorationStyleValue->GetUnit() ||
  4674. eCSSUnit_Unset == decorationStyleValue->GetUnit()) {
  4675. text->mTextDecorationStyle = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
  4676. }
  4677. // text-overflow: enum, string, pair(enum|string), inherit, initial
  4678. const nsCSSValue* textOverflowValue =
  4679. aRuleData->ValueForTextOverflow();
  4680. if (eCSSUnit_Initial == textOverflowValue->GetUnit() ||
  4681. eCSSUnit_Unset == textOverflowValue->GetUnit()) {
  4682. text->mTextOverflow = nsStyleTextOverflow();
  4683. } else if (eCSSUnit_Inherit == textOverflowValue->GetUnit()) {
  4684. conditions.SetUncacheable();
  4685. text->mTextOverflow = parentText->mTextOverflow;
  4686. } else if (eCSSUnit_Enumerated == textOverflowValue->GetUnit()) {
  4687. // A single enumerated value.
  4688. SetValue(*textOverflowValue, text->mTextOverflow.mRight.mType,
  4689. conditions,
  4690. SETVAL_ENUMERATED, parentText->mTextOverflow.mRight.mType,
  4691. NS_STYLE_TEXT_OVERFLOW_CLIP);
  4692. text->mTextOverflow.mRight.mString.Truncate();
  4693. text->mTextOverflow.mLeft.mType = NS_STYLE_TEXT_OVERFLOW_CLIP;
  4694. text->mTextOverflow.mLeft.mString.Truncate();
  4695. text->mTextOverflow.mLogicalDirections = true;
  4696. } else if (eCSSUnit_String == textOverflowValue->GetUnit()) {
  4697. // A single string value.
  4698. text->mTextOverflow.mRight.mType = NS_STYLE_TEXT_OVERFLOW_STRING;
  4699. textOverflowValue->GetStringValue(text->mTextOverflow.mRight.mString);
  4700. text->mTextOverflow.mLeft.mType = NS_STYLE_TEXT_OVERFLOW_CLIP;
  4701. text->mTextOverflow.mLeft.mString.Truncate();
  4702. text->mTextOverflow.mLogicalDirections = true;
  4703. } else if (eCSSUnit_Pair == textOverflowValue->GetUnit()) {
  4704. // Two values were specified.
  4705. text->mTextOverflow.mLogicalDirections = false;
  4706. const nsCSSValuePair& textOverflowValuePair =
  4707. textOverflowValue->GetPairValue();
  4708. const nsCSSValue *textOverflowLeftValue = &textOverflowValuePair.mXValue;
  4709. if (eCSSUnit_Enumerated == textOverflowLeftValue->GetUnit()) {
  4710. SetValue(*textOverflowLeftValue, text->mTextOverflow.mLeft.mType,
  4711. conditions,
  4712. SETVAL_ENUMERATED, parentText->mTextOverflow.mLeft.mType,
  4713. NS_STYLE_TEXT_OVERFLOW_CLIP);
  4714. text->mTextOverflow.mLeft.mString.Truncate();
  4715. } else if (eCSSUnit_String == textOverflowLeftValue->GetUnit()) {
  4716. textOverflowLeftValue->GetStringValue(text->mTextOverflow.mLeft.mString);
  4717. text->mTextOverflow.mLeft.mType = NS_STYLE_TEXT_OVERFLOW_STRING;
  4718. }
  4719. const nsCSSValue *textOverflowRightValue = &textOverflowValuePair.mYValue;
  4720. if (eCSSUnit_Enumerated == textOverflowRightValue->GetUnit()) {
  4721. SetValue(*textOverflowRightValue, text->mTextOverflow.mRight.mType,
  4722. conditions,
  4723. SETVAL_ENUMERATED, parentText->mTextOverflow.mRight.mType,
  4724. NS_STYLE_TEXT_OVERFLOW_CLIP);
  4725. text->mTextOverflow.mRight.mString.Truncate();
  4726. } else if (eCSSUnit_String == textOverflowRightValue->GetUnit()) {
  4727. textOverflowRightValue->GetStringValue(text->mTextOverflow.mRight.mString);
  4728. text->mTextOverflow.mRight.mType = NS_STYLE_TEXT_OVERFLOW_STRING;
  4729. }
  4730. }
  4731. // unicode-bidi: enum, inherit, initial
  4732. SetValue(*aRuleData->ValueForUnicodeBidi(), text->mUnicodeBidi, conditions,
  4733. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  4734. parentText->mUnicodeBidi,
  4735. NS_STYLE_UNICODE_BIDI_NORMAL);
  4736. // initial-letter: normal, number, array(number, integer?), initial
  4737. const nsCSSValue* initialLetterValue = aRuleData->ValueForInitialLetter();
  4738. if (initialLetterValue->GetUnit() == eCSSUnit_Null) {
  4739. // We don't want to change anything in this case.
  4740. } else if (initialLetterValue->GetUnit() == eCSSUnit_Inherit) {
  4741. conditions.SetUncacheable();
  4742. text->mInitialLetterSink = parentText->mInitialLetterSink;
  4743. text->mInitialLetterSize = parentText->mInitialLetterSize;
  4744. } else if (initialLetterValue->GetUnit() == eCSSUnit_Initial ||
  4745. initialLetterValue->GetUnit() == eCSSUnit_Unset ||
  4746. initialLetterValue->GetUnit() == eCSSUnit_Normal) {
  4747. // Use invalid values in initial-letter property to mean normal. So we can
  4748. // determine whether it is normal by checking mInitialLetterSink == 0.
  4749. text->mInitialLetterSink = 0;
  4750. text->mInitialLetterSize = 0.0f;
  4751. } else if (initialLetterValue->GetUnit() == eCSSUnit_Array) {
  4752. const nsCSSValue& firstValue = initialLetterValue->GetArrayValue()->Item(0);
  4753. const nsCSSValue& secondValue = initialLetterValue->GetArrayValue()->Item(1);
  4754. MOZ_ASSERT(firstValue.GetUnit() == eCSSUnit_Number &&
  4755. secondValue.GetUnit() == eCSSUnit_Integer,
  4756. "unexpected value unit");
  4757. text->mInitialLetterSize = firstValue.GetFloatValue();
  4758. text->mInitialLetterSink = secondValue.GetIntValue();
  4759. } else if (initialLetterValue->GetUnit() == eCSSUnit_Number) {
  4760. text->mInitialLetterSize = initialLetterValue->GetFloatValue();
  4761. text->mInitialLetterSink = NSToCoordFloorClamped(text->mInitialLetterSize);
  4762. } else {
  4763. MOZ_ASSERT_UNREACHABLE("unknown unit for initial-letter");
  4764. }
  4765. COMPUTE_END_RESET(TextReset, text)
  4766. }
  4767. const void*
  4768. nsRuleNode::ComputeUserInterfaceData(void* aStartStruct,
  4769. const nsRuleData* aRuleData,
  4770. nsStyleContext* aContext,
  4771. nsRuleNode* aHighestNode,
  4772. const RuleDetail aRuleDetail,
  4773. const RuleNodeCacheConditions aConditions)
  4774. {
  4775. COMPUTE_START_INHERITED(UserInterface, ui, parentUI)
  4776. auto setComplexColor = [&](const nsCSSValue* aValue,
  4777. StyleComplexColor nsStyleUserInterface::* aField) {
  4778. SetComplexColor<eUnsetInherit>(*aValue, parentUI->*aField,
  4779. StyleComplexColor::Auto(),
  4780. mPresContext, ui->*aField, conditions);
  4781. };
  4782. // cursor: enum, url, inherit
  4783. const nsCSSValue* cursorValue = aRuleData->ValueForCursor();
  4784. nsCSSUnit cursorUnit = cursorValue->GetUnit();
  4785. if (cursorUnit != eCSSUnit_Null) {
  4786. ui->mCursorImages.Clear();
  4787. if (cursorUnit == eCSSUnit_Inherit ||
  4788. cursorUnit == eCSSUnit_Unset) {
  4789. conditions.SetUncacheable();
  4790. ui->mCursor = parentUI->mCursor;
  4791. ui->mCursorImages = parentUI->mCursorImages;
  4792. } else if (cursorUnit == eCSSUnit_Initial) {
  4793. ui->mCursor = NS_STYLE_CURSOR_AUTO;
  4794. } else {
  4795. // The parser will never create a list that is *all* URL values --
  4796. // that's invalid.
  4797. MOZ_ASSERT(cursorUnit == eCSSUnit_List || cursorUnit == eCSSUnit_ListDep,
  4798. "unrecognized cursor unit");
  4799. const nsCSSValueList* list = cursorValue->GetListValue();
  4800. for ( ; list->mValue.GetUnit() == eCSSUnit_Array; list = list->mNext) {
  4801. nsCSSValue::Array* arr = list->mValue.GetArrayValue();
  4802. imgRequestProxy* req =
  4803. GetImageRequest(aContext->PresContext(), arr->Item(0));
  4804. if (req) {
  4805. nsCursorImage* item = ui->mCursorImages.AppendElement();
  4806. item->SetImage(req);
  4807. if (arr->Item(1).GetUnit() != eCSSUnit_Null) {
  4808. item->mHaveHotspot = true;
  4809. item->mHotspotX = arr->Item(1).GetFloatValue();
  4810. item->mHotspotY = arr->Item(2).GetFloatValue();
  4811. }
  4812. }
  4813. }
  4814. NS_ASSERTION(list, "Must have non-array value at the end");
  4815. NS_ASSERTION(list->mValue.GetUnit() == eCSSUnit_Enumerated,
  4816. "Unexpected fallback value at end of cursor list");
  4817. ui->mCursor = list->mValue.GetIntValue();
  4818. }
  4819. }
  4820. // user-input: enum, inherit, initial
  4821. SetValue(*aRuleData->ValueForUserInput(),
  4822. ui->mUserInput, conditions,
  4823. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  4824. parentUI->mUserInput,
  4825. StyleUserInput::Auto);
  4826. // user-modify: enum, inherit, initial
  4827. SetValue(*aRuleData->ValueForUserModify(),
  4828. ui->mUserModify, conditions,
  4829. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  4830. parentUI->mUserModify,
  4831. StyleUserModify::ReadOnly);
  4832. // user-focus: enum, inherit, initial
  4833. SetValue(*aRuleData->ValueForUserFocus(),
  4834. ui->mUserFocus, conditions,
  4835. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  4836. parentUI->mUserFocus,
  4837. StyleUserFocus::None);
  4838. // pointer-events: enum, inherit, initial
  4839. SetValue(*aRuleData->ValueForPointerEvents(), ui->mPointerEvents,
  4840. conditions,
  4841. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  4842. parentUI->mPointerEvents,
  4843. NS_STYLE_POINTER_EVENTS_AUTO);
  4844. // caret-color: auto, color, inherit
  4845. setComplexColor(aRuleData->ValueForCaretColor(),
  4846. &nsStyleUserInterface::mCaretColor);
  4847. // scrollbar-width: auto, thin, none
  4848. SetValue(*aRuleData->ValueForScrollbarWidth(),
  4849. ui->mScrollbarWidth,
  4850. conditions,
  4851. SETVAL_ENUMERATED,
  4852. parentUI->mScrollbarWidth,
  4853. StyleScrollbarWidth::Auto);
  4854. COMPUTE_END_INHERITED(UserInterface, ui)
  4855. }
  4856. const void*
  4857. nsRuleNode::ComputeUIResetData(void* aStartStruct,
  4858. const nsRuleData* aRuleData,
  4859. nsStyleContext* aContext,
  4860. nsRuleNode* aHighestNode,
  4861. const RuleDetail aRuleDetail,
  4862. const RuleNodeCacheConditions aConditions)
  4863. {
  4864. COMPUTE_START_RESET(UIReset, ui, parentUI)
  4865. // user-select: enum, inherit, initial
  4866. SetValue(*aRuleData->ValueForUserSelect(),
  4867. ui->mUserSelect, conditions,
  4868. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  4869. parentUI->mUserSelect,
  4870. StyleUserSelect::Auto);
  4871. // ime-mode: enum, inherit, initial
  4872. SetValue(*aRuleData->ValueForImeMode(),
  4873. ui->mIMEMode, conditions,
  4874. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  4875. parentUI->mIMEMode,
  4876. NS_STYLE_IME_MODE_AUTO);
  4877. // force-broken-image-icons: integer, inherit, initial
  4878. SetValue(*aRuleData->ValueForForceBrokenImageIcon(),
  4879. ui->mForceBrokenImageIcon,
  4880. conditions,
  4881. SETVAL_INTEGER | SETVAL_UNSET_INITIAL,
  4882. parentUI->mForceBrokenImageIcon, 0);
  4883. // -moz-window-dragging: enum, inherit, initial
  4884. SetValue(*aRuleData->ValueForWindowDragging(),
  4885. ui->mWindowDragging, conditions,
  4886. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  4887. parentUI->mWindowDragging,
  4888. StyleWindowDragging::Default);
  4889. // -moz-window-shadow: enum, inherit, initial
  4890. SetValue(*aRuleData->ValueForWindowShadow(),
  4891. ui->mWindowShadow, conditions,
  4892. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  4893. parentUI->mWindowShadow,
  4894. NS_STYLE_WINDOW_SHADOW_DEFAULT);
  4895. COMPUTE_END_RESET(UIReset, ui)
  4896. }
  4897. // Information about each transition or animation property that is
  4898. // constant.
  4899. struct TransitionPropInfo {
  4900. nsCSSPropertyID property;
  4901. // Location of the count of the property's computed value.
  4902. uint32_t nsStyleDisplay::* sdCount;
  4903. };
  4904. // Each property's index in this array must match its index in the
  4905. // mutable array |transitionPropData| below.
  4906. static const TransitionPropInfo transitionPropInfo[4] = {
  4907. { eCSSProperty_transition_delay,
  4908. &nsStyleDisplay::mTransitionDelayCount },
  4909. { eCSSProperty_transition_duration,
  4910. &nsStyleDisplay::mTransitionDurationCount },
  4911. { eCSSProperty_transition_property,
  4912. &nsStyleDisplay::mTransitionPropertyCount },
  4913. { eCSSProperty_transition_timing_function,
  4914. &nsStyleDisplay::mTransitionTimingFunctionCount },
  4915. };
  4916. // Each property's index in this array must match its index in the
  4917. // mutable array |animationPropData| below.
  4918. static const TransitionPropInfo animationPropInfo[8] = {
  4919. { eCSSProperty_animation_delay,
  4920. &nsStyleDisplay::mAnimationDelayCount },
  4921. { eCSSProperty_animation_duration,
  4922. &nsStyleDisplay::mAnimationDurationCount },
  4923. { eCSSProperty_animation_name,
  4924. &nsStyleDisplay::mAnimationNameCount },
  4925. { eCSSProperty_animation_timing_function,
  4926. &nsStyleDisplay::mAnimationTimingFunctionCount },
  4927. { eCSSProperty_animation_direction,
  4928. &nsStyleDisplay::mAnimationDirectionCount },
  4929. { eCSSProperty_animation_fill_mode,
  4930. &nsStyleDisplay::mAnimationFillModeCount },
  4931. { eCSSProperty_animation_play_state,
  4932. &nsStyleDisplay::mAnimationPlayStateCount },
  4933. { eCSSProperty_animation_iteration_count,
  4934. &nsStyleDisplay::mAnimationIterationCountCount },
  4935. };
  4936. // Information about each transition or animation property that changes
  4937. // during ComputeDisplayData.
  4938. struct TransitionPropData {
  4939. const nsCSSValueList *list;
  4940. nsCSSUnit unit;
  4941. uint32_t num;
  4942. };
  4943. static uint32_t
  4944. CountTransitionProps(const TransitionPropInfo* aInfo,
  4945. TransitionPropData* aData,
  4946. size_t aLength,
  4947. nsStyleDisplay* aDisplay,
  4948. const nsStyleDisplay* aParentDisplay,
  4949. const nsRuleData* aRuleData,
  4950. RuleNodeCacheConditions& aConditions)
  4951. {
  4952. // The four transition properties or eight animation properties are
  4953. // stored in nsCSSDisplay in a single array for all properties. The
  4954. // number of transitions is equal to the number of items in the
  4955. // longest property's value. Properties that have fewer values than
  4956. // the longest are filled in by repeating the list. However, this
  4957. // repetition does not extend the computed value of that particular
  4958. // property (for purposes of inheritance, or, in our code, for when
  4959. // other properties are overridden by a more specific rule).
  4960. // But actually, since the spec isn't clear yet, we'll fully compute
  4961. // all of them (so we can switch easily later), but only care about
  4962. // the ones up to the number of items for 'transition-property', per
  4963. // http://lists.w3.org/Archives/Public/www-style/2009Aug/0109.html .
  4964. // Transitions are difficult to handle correctly because of this. For
  4965. // example, we need to handle scenarios such as:
  4966. // * a more general rule specifies transition-property: a, b, c;
  4967. // * a more specific rule overrides as transition-property: d;
  4968. //
  4969. // If only the general rule applied, we would fill in the extra
  4970. // properties (duration, delay, etc) with initial values to create 3
  4971. // fully-specified transitions. But when the more specific rule
  4972. // applies, we should only create a single transition. In order to do
  4973. // this we need to remember which properties were explicitly specified
  4974. // and which ones were just filled in with initial values to get a
  4975. // fully-specified transition, which we do by remembering the number
  4976. // of values for each property.
  4977. uint32_t numTransitions = 0;
  4978. for (size_t i = 0; i < aLength; ++i) {
  4979. const TransitionPropInfo& info = aInfo[i];
  4980. TransitionPropData& data = aData[i];
  4981. // cache whether any of the properties are specified as 'inherit' so
  4982. // we can use it below
  4983. const nsCSSValue& value = *aRuleData->ValueFor(info.property);
  4984. data.unit = value.GetUnit();
  4985. data.list = (value.GetUnit() == eCSSUnit_List ||
  4986. value.GetUnit() == eCSSUnit_ListDep)
  4987. ? value.GetListValue() : nullptr;
  4988. // General algorithm to determine how many total transitions we need
  4989. // to build. For each property:
  4990. // - if there is no value specified in for the property in
  4991. // displayData, use the values from the start struct, but only if
  4992. // they were explicitly specified
  4993. // - if there is a value specified for the property in displayData:
  4994. // - if the value is 'inherit', count the number of values for
  4995. // that property are specified by the parent, but only those
  4996. // that were explicitly specified
  4997. // - otherwise, count the number of values specified in displayData
  4998. // calculate number of elements
  4999. if (data.unit == eCSSUnit_Inherit) {
  5000. data.num = aParentDisplay->*(info.sdCount);
  5001. aConditions.SetUncacheable();
  5002. } else if (data.list) {
  5003. data.num = ListLength(data.list);
  5004. } else {
  5005. data.num = aDisplay->*(info.sdCount);
  5006. }
  5007. if (data.num > numTransitions) {
  5008. numTransitions = data.num;
  5009. }
  5010. }
  5011. return numTransitions;
  5012. }
  5013. /* static */ void
  5014. nsRuleNode::ComputeTimingFunction(const nsCSSValue& aValue,
  5015. nsTimingFunction& aResult)
  5016. {
  5017. switch (aValue.GetUnit()) {
  5018. case eCSSUnit_Enumerated:
  5019. aResult = nsTimingFunction(aValue.GetIntValue());
  5020. break;
  5021. case eCSSUnit_Cubic_Bezier:
  5022. {
  5023. nsCSSValue::Array* array = aValue.GetArrayValue();
  5024. NS_ASSERTION(array && array->Count() == 4,
  5025. "Need 4 control points");
  5026. aResult = nsTimingFunction(array->Item(0).GetFloatValue(),
  5027. array->Item(1).GetFloatValue(),
  5028. array->Item(2).GetFloatValue(),
  5029. array->Item(3).GetFloatValue());
  5030. }
  5031. break;
  5032. case eCSSUnit_Steps:
  5033. {
  5034. nsCSSValue::Array* array = aValue.GetArrayValue();
  5035. NS_ASSERTION(array && array->Count() == 2,
  5036. "Need 2 items");
  5037. NS_ASSERTION(array->Item(0).GetUnit() == eCSSUnit_Integer,
  5038. "unexpected first value");
  5039. NS_ASSERTION(array->Item(1).GetUnit() == eCSSUnit_Enumerated &&
  5040. (array->Item(1).GetIntValue() ==
  5041. NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START ||
  5042. array->Item(1).GetIntValue() ==
  5043. NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END ||
  5044. array->Item(1).GetIntValue() == -1),
  5045. "unexpected second value");
  5046. nsTimingFunction::Type type =
  5047. (array->Item(1).GetIntValue() ==
  5048. NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START) ?
  5049. nsTimingFunction::Type::StepStart :
  5050. nsTimingFunction::Type::StepEnd;
  5051. aResult = nsTimingFunction(type, array->Item(0).GetIntValue());
  5052. }
  5053. break;
  5054. default:
  5055. NS_NOTREACHED("Invalid transition property unit");
  5056. }
  5057. }
  5058. static uint8_t
  5059. GetWillChangeBitFieldFromPropFlags(const nsCSSPropertyID& aProp)
  5060. {
  5061. uint8_t willChangeBitField = 0;
  5062. if (nsCSSProps::PropHasFlags(aProp, CSS_PROPERTY_CREATES_STACKING_CONTEXT)) {
  5063. willChangeBitField |= NS_STYLE_WILL_CHANGE_STACKING_CONTEXT;
  5064. }
  5065. if (nsCSSProps::PropHasFlags(aProp, CSS_PROPERTY_FIXPOS_CB)) {
  5066. willChangeBitField |= NS_STYLE_WILL_CHANGE_FIXPOS_CB;
  5067. }
  5068. if (nsCSSProps::PropHasFlags(aProp, CSS_PROPERTY_ABSPOS_CB)) {
  5069. willChangeBitField |= NS_STYLE_WILL_CHANGE_ABSPOS_CB;
  5070. }
  5071. return willChangeBitField;
  5072. }
  5073. const void*
  5074. nsRuleNode::ComputeDisplayData(void* aStartStruct,
  5075. const nsRuleData* aRuleData,
  5076. nsStyleContext* aContext,
  5077. nsRuleNode* aHighestNode,
  5078. const RuleDetail aRuleDetail,
  5079. const RuleNodeCacheConditions aConditions)
  5080. {
  5081. COMPUTE_START_RESET(Display, display, parentDisplay)
  5082. // We may have ended up with aStartStruct's values of mDisplay and
  5083. // mFloat, but those may not be correct if our style data overrides
  5084. // its position or float properties. Reset to mOriginalDisplay and
  5085. // mOriginalFloat; if it turns out we still need the display/floats
  5086. // adjustments, we'll do them below.
  5087. display->mDisplay = display->mOriginalDisplay;
  5088. display->mFloat = display->mOriginalFloat;
  5089. // Each property's index in this array must match its index in the
  5090. // const array |transitionPropInfo| above.
  5091. TransitionPropData transitionPropData[4];
  5092. TransitionPropData& delay = transitionPropData[0];
  5093. TransitionPropData& duration = transitionPropData[1];
  5094. TransitionPropData& property = transitionPropData[2];
  5095. TransitionPropData& timingFunction = transitionPropData[3];
  5096. #define FOR_ALL_TRANSITION_PROPS(var_) \
  5097. for (uint32_t var_ = 0; var_ < 4; ++var_)
  5098. // CSS Transitions
  5099. uint32_t numTransitions =
  5100. CountTransitionProps(transitionPropInfo, transitionPropData,
  5101. ArrayLength(transitionPropData),
  5102. display, parentDisplay, aRuleData,
  5103. conditions);
  5104. display->mTransitions.SetLengthNonZero(numTransitions);
  5105. FOR_ALL_TRANSITION_PROPS(p) {
  5106. const TransitionPropInfo& i = transitionPropInfo[p];
  5107. TransitionPropData& d = transitionPropData[p];
  5108. display->*(i.sdCount) = d.num;
  5109. }
  5110. // Fill in the transitions we just allocated with the appropriate values.
  5111. for (uint32_t i = 0; i < numTransitions; ++i) {
  5112. StyleTransition *transition = &display->mTransitions[i];
  5113. if (i >= delay.num) {
  5114. MOZ_ASSERT(delay.num, "delay.num must be greater than 0");
  5115. transition->SetDelay(display->mTransitions[i % delay.num].GetDelay());
  5116. } else if (delay.unit == eCSSUnit_Inherit) {
  5117. // FIXME (Bug 522599) (for all transition properties): write a test that
  5118. // detects when this was wrong for i >= delay.num if parent had
  5119. // count for this property not equal to length
  5120. MOZ_ASSERT(i < parentDisplay->mTransitionDelayCount,
  5121. "delay.num computed incorrectly");
  5122. MOZ_ASSERT(!conditions.Cacheable(),
  5123. "should have made conditions.Cacheable() false above");
  5124. transition->SetDelay(parentDisplay->mTransitions[i].GetDelay());
  5125. } else if (delay.unit == eCSSUnit_Initial ||
  5126. delay.unit == eCSSUnit_Unset) {
  5127. transition->SetDelay(0.0);
  5128. } else if (delay.list) {
  5129. switch (delay.list->mValue.GetUnit()) {
  5130. case eCSSUnit_Seconds:
  5131. transition->SetDelay(PR_MSEC_PER_SEC *
  5132. delay.list->mValue.GetFloatValue());
  5133. break;
  5134. case eCSSUnit_Milliseconds:
  5135. transition->SetDelay(delay.list->mValue.GetFloatValue());
  5136. break;
  5137. default:
  5138. NS_NOTREACHED("Invalid delay unit");
  5139. }
  5140. }
  5141. if (i >= duration.num) {
  5142. MOZ_ASSERT(duration.num, "duration.num must be greater than 0");
  5143. transition->SetDuration(
  5144. display->mTransitions[i % duration.num].GetDuration());
  5145. } else if (duration.unit == eCSSUnit_Inherit) {
  5146. MOZ_ASSERT(i < parentDisplay->mTransitionDurationCount,
  5147. "duration.num computed incorrectly");
  5148. MOZ_ASSERT(!conditions.Cacheable(),
  5149. "should have made conditions.Cacheable() false above");
  5150. transition->SetDuration(parentDisplay->mTransitions[i].GetDuration());
  5151. } else if (duration.unit == eCSSUnit_Initial ||
  5152. duration.unit == eCSSUnit_Unset) {
  5153. transition->SetDuration(0.0);
  5154. } else if (duration.list) {
  5155. switch (duration.list->mValue.GetUnit()) {
  5156. case eCSSUnit_Seconds:
  5157. transition->SetDuration(PR_MSEC_PER_SEC *
  5158. duration.list->mValue.GetFloatValue());
  5159. break;
  5160. case eCSSUnit_Milliseconds:
  5161. transition->SetDuration(duration.list->mValue.GetFloatValue());
  5162. break;
  5163. default:
  5164. NS_NOTREACHED("Invalid duration unit");
  5165. }
  5166. }
  5167. if (i >= property.num) {
  5168. MOZ_ASSERT(property.num, "property.num must be greater than 0");
  5169. transition->CopyPropertyFrom(display->mTransitions[i % property.num]);
  5170. } else if (property.unit == eCSSUnit_Inherit) {
  5171. MOZ_ASSERT(i < parentDisplay->mTransitionPropertyCount,
  5172. "property.num computed incorrectly");
  5173. MOZ_ASSERT(!conditions.Cacheable(),
  5174. "should have made conditions.Cacheable() false above");
  5175. transition->CopyPropertyFrom(parentDisplay->mTransitions[i]);
  5176. } else if (property.unit == eCSSUnit_Initial ||
  5177. property.unit == eCSSUnit_Unset) {
  5178. transition->SetProperty(eCSSPropertyExtra_all_properties);
  5179. } else if (property.unit == eCSSUnit_None) {
  5180. transition->SetProperty(eCSSPropertyExtra_no_properties);
  5181. } else if (property.list) {
  5182. const nsCSSValue &val = property.list->mValue;
  5183. if (val.GetUnit() == eCSSUnit_Ident) {
  5184. nsDependentString
  5185. propertyStr(property.list->mValue.GetStringBufferValue());
  5186. nsCSSPropertyID prop =
  5187. nsCSSProps::LookupProperty(propertyStr,
  5188. CSSEnabledState::eForAllContent);
  5189. if (prop == eCSSProperty_UNKNOWN ||
  5190. prop == eCSSPropertyExtra_variable) {
  5191. transition->SetUnknownProperty(prop, propertyStr);
  5192. } else {
  5193. transition->SetProperty(prop);
  5194. }
  5195. } else {
  5196. MOZ_ASSERT(val.GetUnit() == eCSSUnit_All,
  5197. "Invalid transition property unit");
  5198. transition->SetProperty(eCSSPropertyExtra_all_properties);
  5199. }
  5200. }
  5201. if (i >= timingFunction.num) {
  5202. MOZ_ASSERT(timingFunction.num,
  5203. "timingFunction.num must be greater than 0");
  5204. transition->SetTimingFunction(
  5205. display->mTransitions[i % timingFunction.num].GetTimingFunction());
  5206. } else if (timingFunction.unit == eCSSUnit_Inherit) {
  5207. MOZ_ASSERT(i < parentDisplay->mTransitionTimingFunctionCount,
  5208. "timingFunction.num computed incorrectly");
  5209. MOZ_ASSERT(!conditions.Cacheable(),
  5210. "should have made conditions.Cacheable() false above");
  5211. transition->SetTimingFunction(
  5212. parentDisplay->mTransitions[i].GetTimingFunction());
  5213. } else if (timingFunction.unit == eCSSUnit_Initial ||
  5214. timingFunction.unit == eCSSUnit_Unset) {
  5215. transition->SetTimingFunction(
  5216. nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE));
  5217. } else if (timingFunction.list) {
  5218. ComputeTimingFunction(timingFunction.list->mValue,
  5219. transition->TimingFunctionSlot());
  5220. }
  5221. FOR_ALL_TRANSITION_PROPS(p) {
  5222. const TransitionPropInfo& info = transitionPropInfo[p];
  5223. TransitionPropData& d = transitionPropData[p];
  5224. // if we're at the end of the list, start at the beginning and repeat
  5225. // until we're out of transitions to populate
  5226. if (d.list) {
  5227. d.list = d.list->mNext ? d.list->mNext :
  5228. aRuleData->ValueFor(info.property)->GetListValue();
  5229. }
  5230. }
  5231. }
  5232. // Each property's index in this array must match its index in the
  5233. // const array |animationPropInfo| above.
  5234. TransitionPropData animationPropData[8];
  5235. TransitionPropData& animDelay = animationPropData[0];
  5236. TransitionPropData& animDuration = animationPropData[1];
  5237. TransitionPropData& animName = animationPropData[2];
  5238. TransitionPropData& animTimingFunction = animationPropData[3];
  5239. TransitionPropData& animDirection = animationPropData[4];
  5240. TransitionPropData& animFillMode = animationPropData[5];
  5241. TransitionPropData& animPlayState = animationPropData[6];
  5242. TransitionPropData& animIterationCount = animationPropData[7];
  5243. #define FOR_ALL_ANIMATION_PROPS(var_) \
  5244. for (uint32_t var_ = 0; var_ < 8; ++var_)
  5245. // CSS Animations.
  5246. uint32_t numAnimations =
  5247. CountTransitionProps(animationPropInfo, animationPropData,
  5248. ArrayLength(animationPropData),
  5249. display, parentDisplay, aRuleData,
  5250. conditions);
  5251. display->mAnimations.SetLengthNonZero(numAnimations);
  5252. FOR_ALL_ANIMATION_PROPS(p) {
  5253. const TransitionPropInfo& i = animationPropInfo[p];
  5254. TransitionPropData& d = animationPropData[p];
  5255. display->*(i.sdCount) = d.num;
  5256. }
  5257. // Fill in the animations we just allocated with the appropriate values.
  5258. for (uint32_t i = 0; i < numAnimations; ++i) {
  5259. StyleAnimation *animation = &display->mAnimations[i];
  5260. if (i >= animDelay.num) {
  5261. MOZ_ASSERT(animDelay.num, "animDelay.num must be greater than 0");
  5262. animation->SetDelay(display->mAnimations[i % animDelay.num].GetDelay());
  5263. } else if (animDelay.unit == eCSSUnit_Inherit) {
  5264. // FIXME (Bug 522599) (for all animation properties): write a test that
  5265. // detects when this was wrong for i >= animDelay.num if parent had
  5266. // count for this property not equal to length
  5267. MOZ_ASSERT(i < parentDisplay->mAnimationDelayCount,
  5268. "animDelay.num computed incorrectly");
  5269. MOZ_ASSERT(!conditions.Cacheable(),
  5270. "should have made conditions.Cacheable() false above");
  5271. animation->SetDelay(parentDisplay->mAnimations[i].GetDelay());
  5272. } else if (animDelay.unit == eCSSUnit_Initial ||
  5273. animDelay.unit == eCSSUnit_Unset) {
  5274. animation->SetDelay(0.0);
  5275. } else if (animDelay.list) {
  5276. switch (animDelay.list->mValue.GetUnit()) {
  5277. case eCSSUnit_Seconds:
  5278. animation->SetDelay(PR_MSEC_PER_SEC *
  5279. animDelay.list->mValue.GetFloatValue());
  5280. break;
  5281. case eCSSUnit_Milliseconds:
  5282. animation->SetDelay(animDelay.list->mValue.GetFloatValue());
  5283. break;
  5284. default:
  5285. NS_NOTREACHED("Invalid delay unit");
  5286. }
  5287. }
  5288. if (i >= animDuration.num) {
  5289. MOZ_ASSERT(animDuration.num, "animDuration.num must be greater than 0");
  5290. animation->SetDuration(
  5291. display->mAnimations[i % animDuration.num].GetDuration());
  5292. } else if (animDuration.unit == eCSSUnit_Inherit) {
  5293. MOZ_ASSERT(i < parentDisplay->mAnimationDurationCount,
  5294. "animDuration.num computed incorrectly");
  5295. MOZ_ASSERT(!conditions.Cacheable(),
  5296. "should have made conditions.Cacheable() false above");
  5297. animation->SetDuration(parentDisplay->mAnimations[i].GetDuration());
  5298. } else if (animDuration.unit == eCSSUnit_Initial ||
  5299. animDuration.unit == eCSSUnit_Unset) {
  5300. animation->SetDuration(0.0);
  5301. } else if (animDuration.list) {
  5302. switch (animDuration.list->mValue.GetUnit()) {
  5303. case eCSSUnit_Seconds:
  5304. animation->SetDuration(PR_MSEC_PER_SEC *
  5305. animDuration.list->mValue.GetFloatValue());
  5306. break;
  5307. case eCSSUnit_Milliseconds:
  5308. animation->SetDuration(animDuration.list->mValue.GetFloatValue());
  5309. break;
  5310. default:
  5311. NS_NOTREACHED("Invalid duration unit");
  5312. }
  5313. }
  5314. if (i >= animName.num) {
  5315. MOZ_ASSERT(animName.num, "animName.num must be greater than 0");
  5316. animation->SetName(display->mAnimations[i % animName.num].GetName());
  5317. } else if (animName.unit == eCSSUnit_Inherit) {
  5318. MOZ_ASSERT(i < parentDisplay->mAnimationNameCount,
  5319. "animName.num computed incorrectly");
  5320. MOZ_ASSERT(!conditions.Cacheable(),
  5321. "should have made conditions.Cacheable() false above");
  5322. animation->SetName(parentDisplay->mAnimations[i].GetName());
  5323. } else if (animName.unit == eCSSUnit_Initial ||
  5324. animName.unit == eCSSUnit_Unset) {
  5325. animation->SetName(EmptyString());
  5326. } else if (animName.list) {
  5327. switch (animName.list->mValue.GetUnit()) {
  5328. case eCSSUnit_Ident: {
  5329. nsDependentString
  5330. nameStr(animName.list->mValue.GetStringBufferValue());
  5331. animation->SetName(nameStr);
  5332. break;
  5333. }
  5334. case eCSSUnit_None: {
  5335. animation->SetName(EmptyString());
  5336. break;
  5337. }
  5338. default:
  5339. MOZ_ASSERT(false, "Invalid animation-name unit");
  5340. }
  5341. }
  5342. if (i >= animTimingFunction.num) {
  5343. MOZ_ASSERT(animTimingFunction.num,
  5344. "animTimingFunction.num must be greater than 0");
  5345. animation->SetTimingFunction(
  5346. display->mAnimations[i % animTimingFunction.num].GetTimingFunction());
  5347. } else if (animTimingFunction.unit == eCSSUnit_Inherit) {
  5348. MOZ_ASSERT(i < parentDisplay->mAnimationTimingFunctionCount,
  5349. "animTimingFunction.num computed incorrectly");
  5350. MOZ_ASSERT(!conditions.Cacheable(),
  5351. "should have made conditions.Cacheable() false above");
  5352. animation->SetTimingFunction(
  5353. parentDisplay->mAnimations[i].GetTimingFunction());
  5354. } else if (animTimingFunction.unit == eCSSUnit_Initial ||
  5355. animTimingFunction.unit == eCSSUnit_Unset) {
  5356. animation->SetTimingFunction(
  5357. nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE));
  5358. } else if (animTimingFunction.list) {
  5359. ComputeTimingFunction(animTimingFunction.list->mValue,
  5360. animation->TimingFunctionSlot());
  5361. }
  5362. if (i >= animDirection.num) {
  5363. MOZ_ASSERT(animDirection.num,
  5364. "animDirection.num must be greater than 0");
  5365. animation->SetDirection(display->mAnimations[i % animDirection.num].GetDirection());
  5366. } else if (animDirection.unit == eCSSUnit_Inherit) {
  5367. MOZ_ASSERT(i < parentDisplay->mAnimationDirectionCount,
  5368. "animDirection.num computed incorrectly");
  5369. MOZ_ASSERT(!conditions.Cacheable(),
  5370. "should have made conditions.Cacheable() false above");
  5371. animation->SetDirection(parentDisplay->mAnimations[i].GetDirection());
  5372. } else if (animDirection.unit == eCSSUnit_Initial ||
  5373. animDirection.unit == eCSSUnit_Unset) {
  5374. animation->SetDirection(dom::PlaybackDirection::Normal);
  5375. } else if (animDirection.list) {
  5376. MOZ_ASSERT(animDirection.list->mValue.GetUnit() == eCSSUnit_Enumerated,
  5377. "Invalid animation-direction unit");
  5378. animation->SetDirection(
  5379. static_cast<dom::PlaybackDirection>(animDirection.list->mValue.GetIntValue()));
  5380. }
  5381. if (i >= animFillMode.num) {
  5382. MOZ_ASSERT(animFillMode.num, "animFillMode.num must be greater than 0");
  5383. animation->SetFillMode(display->mAnimations[i % animFillMode.num].GetFillMode());
  5384. } else if (animFillMode.unit == eCSSUnit_Inherit) {
  5385. MOZ_ASSERT(i < parentDisplay->mAnimationFillModeCount,
  5386. "animFillMode.num computed incorrectly");
  5387. MOZ_ASSERT(!conditions.Cacheable(),
  5388. "should have made conditions.Cacheable() false above");
  5389. animation->SetFillMode(parentDisplay->mAnimations[i].GetFillMode());
  5390. } else if (animFillMode.unit == eCSSUnit_Initial ||
  5391. animFillMode.unit == eCSSUnit_Unset) {
  5392. animation->SetFillMode(dom::FillMode::None);
  5393. } else if (animFillMode.list) {
  5394. MOZ_ASSERT(animFillMode.list->mValue.GetUnit() == eCSSUnit_Enumerated,
  5395. "Invalid animation-fill-mode unit");
  5396. animation->SetFillMode(
  5397. static_cast<dom::FillMode>(animFillMode.list->mValue.GetIntValue()));
  5398. }
  5399. if (i >= animPlayState.num) {
  5400. MOZ_ASSERT(animPlayState.num,
  5401. "animPlayState.num must be greater than 0");
  5402. animation->SetPlayState(display->mAnimations[i % animPlayState.num].GetPlayState());
  5403. } else if (animPlayState.unit == eCSSUnit_Inherit) {
  5404. MOZ_ASSERT(i < parentDisplay->mAnimationPlayStateCount,
  5405. "animPlayState.num computed incorrectly");
  5406. MOZ_ASSERT(!conditions.Cacheable(),
  5407. "should have made conditions.Cacheable() false above");
  5408. animation->SetPlayState(parentDisplay->mAnimations[i].GetPlayState());
  5409. } else if (animPlayState.unit == eCSSUnit_Initial ||
  5410. animPlayState.unit == eCSSUnit_Unset) {
  5411. animation->SetPlayState(NS_STYLE_ANIMATION_PLAY_STATE_RUNNING);
  5412. } else if (animPlayState.list) {
  5413. MOZ_ASSERT(animPlayState.list->mValue.GetUnit() == eCSSUnit_Enumerated,
  5414. "Invalid animation-play-state unit");
  5415. animation->SetPlayState(animPlayState.list->mValue.GetIntValue());
  5416. }
  5417. if (i >= animIterationCount.num) {
  5418. MOZ_ASSERT(animIterationCount.num,
  5419. "animIterationCount.num must be greater than 0");
  5420. animation->SetIterationCount(display->mAnimations[i % animIterationCount.num].GetIterationCount());
  5421. } else if (animIterationCount.unit == eCSSUnit_Inherit) {
  5422. MOZ_ASSERT(i < parentDisplay->mAnimationIterationCountCount,
  5423. "animIterationCount.num computed incorrectly");
  5424. MOZ_ASSERT(!conditions.Cacheable(),
  5425. "should have made conditions.Cacheable() false above");
  5426. animation->SetIterationCount(parentDisplay->mAnimations[i].GetIterationCount());
  5427. } else if (animIterationCount.unit == eCSSUnit_Initial ||
  5428. animIterationCount.unit == eCSSUnit_Unset) {
  5429. animation->SetIterationCount(1.0f);
  5430. } else if (animIterationCount.list) {
  5431. switch (animIterationCount.list->mValue.GetUnit()) {
  5432. case eCSSUnit_Enumerated:
  5433. MOZ_ASSERT(animIterationCount.list->mValue.GetIntValue() ==
  5434. NS_STYLE_ANIMATION_ITERATION_COUNT_INFINITE,
  5435. "unexpected value");
  5436. animation->SetIterationCount(NS_IEEEPositiveInfinity());
  5437. break;
  5438. case eCSSUnit_Number:
  5439. animation->SetIterationCount(
  5440. animIterationCount.list->mValue.GetFloatValue());
  5441. break;
  5442. default:
  5443. MOZ_ASSERT(false,
  5444. "unexpected animation-iteration-count unit");
  5445. }
  5446. }
  5447. FOR_ALL_ANIMATION_PROPS(p) {
  5448. const TransitionPropInfo& info = animationPropInfo[p];
  5449. TransitionPropData& d = animationPropData[p];
  5450. // if we're at the end of the list, start at the beginning and repeat
  5451. // until we're out of animations to populate
  5452. if (d.list) {
  5453. d.list = d.list->mNext ? d.list->mNext :
  5454. aRuleData->ValueFor(info.property)->GetListValue();
  5455. }
  5456. }
  5457. }
  5458. // display: enum, inherit, initial
  5459. SetValue(*aRuleData->ValueForDisplay(), display->mDisplay, conditions,
  5460. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  5461. parentDisplay->mDisplay,
  5462. StyleDisplay::Inline);
  5463. // contain: none, enum, inherit, initial
  5464. SetValue(*aRuleData->ValueForContain(), display->mContain, conditions,
  5465. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  5466. parentDisplay->mContain,
  5467. NS_STYLE_CONTAIN_NONE, Unused,
  5468. NS_STYLE_CONTAIN_NONE, Unused, Unused);
  5469. // scroll-behavior: enum, inherit, initial
  5470. SetValue(*aRuleData->ValueForScrollBehavior(), display->mScrollBehavior,
  5471. conditions,
  5472. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  5473. parentDisplay->mScrollBehavior, NS_STYLE_SCROLL_BEHAVIOR_AUTO);
  5474. // scroll-snap-type-x: none, enum, inherit, initial
  5475. SetValue(*aRuleData->ValueForScrollSnapTypeX(), display->mScrollSnapTypeX,
  5476. conditions,
  5477. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  5478. parentDisplay->mScrollSnapTypeX, NS_STYLE_SCROLL_SNAP_TYPE_NONE);
  5479. // scroll-snap-type-y: none, enum, inherit, initial
  5480. SetValue(*aRuleData->ValueForScrollSnapTypeY(), display->mScrollSnapTypeY,
  5481. conditions,
  5482. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  5483. parentDisplay->mScrollSnapTypeY, NS_STYLE_SCROLL_SNAP_TYPE_NONE);
  5484. // scroll-snap-points-x: none, inherit, initial
  5485. const nsCSSValue& scrollSnapPointsX = *aRuleData->ValueForScrollSnapPointsX();
  5486. switch (scrollSnapPointsX.GetUnit()) {
  5487. case eCSSUnit_Null:
  5488. break;
  5489. case eCSSUnit_Initial:
  5490. case eCSSUnit_Unset:
  5491. case eCSSUnit_None:
  5492. display->mScrollSnapPointsX.SetNoneValue();
  5493. break;
  5494. case eCSSUnit_Inherit:
  5495. display->mScrollSnapPointsX = parentDisplay->mScrollSnapPointsX;
  5496. conditions.SetUncacheable();
  5497. break;
  5498. case eCSSUnit_Function: {
  5499. nsCSSValue::Array* func = scrollSnapPointsX.GetArrayValue();
  5500. NS_ASSERTION(func->Item(0).GetKeywordValue() == eCSSKeyword_repeat,
  5501. "Expected repeat(), got another function name");
  5502. nsStyleCoord coord;
  5503. if (SetCoord(func->Item(1), coord, nsStyleCoord(),
  5504. SETCOORD_LP | SETCOORD_STORE_CALC |
  5505. SETCOORD_CALC_CLAMP_NONNEGATIVE,
  5506. aContext, mPresContext, conditions)) {
  5507. NS_ASSERTION(coord.GetUnit() == eStyleUnit_Coord ||
  5508. coord.GetUnit() == eStyleUnit_Percent ||
  5509. coord.GetUnit() == eStyleUnit_Calc,
  5510. "unexpected unit");
  5511. display->mScrollSnapPointsX = coord;
  5512. }
  5513. break;
  5514. }
  5515. default:
  5516. NS_NOTREACHED("unexpected unit");
  5517. }
  5518. // scroll-snap-points-y: none, inherit, initial
  5519. const nsCSSValue& scrollSnapPointsY = *aRuleData->ValueForScrollSnapPointsY();
  5520. switch (scrollSnapPointsY.GetUnit()) {
  5521. case eCSSUnit_Null:
  5522. break;
  5523. case eCSSUnit_Initial:
  5524. case eCSSUnit_Unset:
  5525. case eCSSUnit_None:
  5526. display->mScrollSnapPointsY.SetNoneValue();
  5527. break;
  5528. case eCSSUnit_Inherit:
  5529. display->mScrollSnapPointsY = parentDisplay->mScrollSnapPointsY;
  5530. conditions.SetUncacheable();
  5531. break;
  5532. case eCSSUnit_Function: {
  5533. nsCSSValue::Array* func = scrollSnapPointsY.GetArrayValue();
  5534. NS_ASSERTION(func->Item(0).GetKeywordValue() == eCSSKeyword_repeat,
  5535. "Expected repeat(), got another function name");
  5536. nsStyleCoord coord;
  5537. if (SetCoord(func->Item(1), coord, nsStyleCoord(),
  5538. SETCOORD_LP | SETCOORD_STORE_CALC |
  5539. SETCOORD_CALC_CLAMP_NONNEGATIVE,
  5540. aContext, mPresContext, conditions)) {
  5541. NS_ASSERTION(coord.GetUnit() == eStyleUnit_Coord ||
  5542. coord.GetUnit() == eStyleUnit_Percent ||
  5543. coord.GetUnit() == eStyleUnit_Calc,
  5544. "unexpected unit");
  5545. display->mScrollSnapPointsY = coord;
  5546. }
  5547. break;
  5548. }
  5549. default:
  5550. NS_NOTREACHED("unexpected unit");
  5551. }
  5552. // scroll-snap-destination: inherit, initial
  5553. const nsCSSValue& snapDestination = *aRuleData->ValueForScrollSnapDestination();
  5554. switch (snapDestination.GetUnit()) {
  5555. case eCSSUnit_Null:
  5556. break;
  5557. case eCSSUnit_Initial:
  5558. case eCSSUnit_Unset:
  5559. display->mScrollSnapDestination.SetInitialZeroValues();
  5560. break;
  5561. case eCSSUnit_Inherit:
  5562. display->mScrollSnapDestination = parentDisplay->mScrollSnapDestination;
  5563. conditions.SetUncacheable();
  5564. break;
  5565. default: {
  5566. ComputePositionValue(aContext, snapDestination,
  5567. display->mScrollSnapDestination, conditions);
  5568. }
  5569. }
  5570. // scroll-snap-coordinate: none, inherit, initial
  5571. const nsCSSValue& snapCoordinate = *aRuleData->ValueForScrollSnapCoordinate();
  5572. switch (snapCoordinate.GetUnit()) {
  5573. case eCSSUnit_Null:
  5574. break;
  5575. case eCSSUnit_Initial:
  5576. case eCSSUnit_Unset:
  5577. case eCSSUnit_None:
  5578. // Unset and Initial is none, indicated by an empty array
  5579. display->mScrollSnapCoordinate.Clear();
  5580. break;
  5581. case eCSSUnit_Inherit:
  5582. display->mScrollSnapCoordinate = parentDisplay->mScrollSnapCoordinate;
  5583. conditions.SetUncacheable();
  5584. break;
  5585. case eCSSUnit_List: {
  5586. display->mScrollSnapCoordinate.Clear();
  5587. const nsCSSValueList* item = snapCoordinate.GetListValue();
  5588. do {
  5589. NS_ASSERTION(item->mValue.GetUnit() != eCSSUnit_Null &&
  5590. item->mValue.GetUnit() != eCSSUnit_Inherit &&
  5591. item->mValue.GetUnit() != eCSSUnit_Initial &&
  5592. item->mValue.GetUnit() != eCSSUnit_Unset,
  5593. "unexpected unit");
  5594. Position* pos = display->mScrollSnapCoordinate.AppendElement();
  5595. ComputePositionValue(aContext, item->mValue, *pos, conditions);
  5596. item = item->mNext;
  5597. } while(item);
  5598. break;
  5599. }
  5600. default:
  5601. NS_NOTREACHED("unexpected unit");
  5602. }
  5603. // isolation: enum, inherit, initial
  5604. SetValue(*aRuleData->ValueForIsolation(), display->mIsolation,
  5605. conditions,
  5606. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  5607. parentDisplay->mIsolation, NS_STYLE_ISOLATION_AUTO);
  5608. // -moz-top-layer: enum, inherit, initial
  5609. SetValue(*aRuleData->ValueForTopLayer(), display->mTopLayer,
  5610. conditions,
  5611. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  5612. parentDisplay->mTopLayer, NS_STYLE_TOP_LAYER_NONE);
  5613. // Backup original display value for calculation of a hypothetical
  5614. // box (CSS2 10.6.4/10.6.5), in addition to getting our style data right later.
  5615. // See ReflowInput::CalculateHypotheticalBox
  5616. display->mOriginalDisplay = display->mDisplay;
  5617. // appearance: enum, inherit, initial
  5618. SetValue(*aRuleData->ValueForAppearance(),
  5619. display->mAppearance, conditions,
  5620. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  5621. parentDisplay->mAppearance,
  5622. NS_THEME_NONE);
  5623. // binding: url, none, inherit
  5624. const nsCSSValue* bindingValue = aRuleData->ValueForBinding();
  5625. if (eCSSUnit_URL == bindingValue->GetUnit()) {
  5626. mozilla::css::URLValue* url = bindingValue->GetURLStructValue();
  5627. NS_ASSERTION(url, "What's going on here?");
  5628. if (MOZ_LIKELY(url->GetURI())) {
  5629. display->mBinding = url;
  5630. } else {
  5631. display->mBinding = nullptr;
  5632. }
  5633. } else if (eCSSUnit_None == bindingValue->GetUnit() ||
  5634. eCSSUnit_Initial == bindingValue->GetUnit() ||
  5635. eCSSUnit_Unset == bindingValue->GetUnit()) {
  5636. display->mBinding = nullptr;
  5637. } else if (eCSSUnit_Inherit == bindingValue->GetUnit()) {
  5638. conditions.SetUncacheable();
  5639. display->mBinding = parentDisplay->mBinding;
  5640. }
  5641. // position: enum, inherit, initial
  5642. SetValue(*aRuleData->ValueForPosition(), display->mPosition, conditions,
  5643. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  5644. parentDisplay->mPosition,
  5645. NS_STYLE_POSITION_STATIC);
  5646. // If an element is put in the top layer, while it is not absolutely
  5647. // positioned, the position value should be computed to 'absolute' per
  5648. // the Fullscreen API spec.
  5649. if (display->mTopLayer != NS_STYLE_TOP_LAYER_NONE &&
  5650. !display->IsAbsolutelyPositionedStyle()) {
  5651. display->mPosition = NS_STYLE_POSITION_ABSOLUTE;
  5652. // We cannot cache this struct because otherwise it may be used as
  5653. // an aStartStruct for some other elements.
  5654. conditions.SetUncacheable();
  5655. }
  5656. // clear: enum, inherit, initial
  5657. SetValue(*aRuleData->ValueForClear(), display->mBreakType, conditions,
  5658. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  5659. parentDisplay->mBreakType,
  5660. StyleClear::None);
  5661. // temp fix for bug 24000
  5662. // Map 'auto' and 'avoid' to false, and 'always', 'left', and
  5663. // 'right' to true.
  5664. // "A conforming user agent may interpret the values 'left' and
  5665. // 'right' as 'always'." - CSS2.1, section 13.3.1
  5666. const nsCSSValue* breakBeforeValue = aRuleData->ValueForPageBreakBefore();
  5667. if (eCSSUnit_Enumerated == breakBeforeValue->GetUnit()) {
  5668. display->mBreakBefore =
  5669. (NS_STYLE_PAGE_BREAK_AVOID != breakBeforeValue->GetIntValue() &&
  5670. NS_STYLE_PAGE_BREAK_AUTO != breakBeforeValue->GetIntValue());
  5671. } else if (eCSSUnit_Initial == breakBeforeValue->GetUnit() ||
  5672. eCSSUnit_Unset == breakBeforeValue->GetUnit()) {
  5673. display->mBreakBefore = false;
  5674. } else if (eCSSUnit_Inherit == breakBeforeValue->GetUnit()) {
  5675. conditions.SetUncacheable();
  5676. display->mBreakBefore = parentDisplay->mBreakBefore;
  5677. }
  5678. const nsCSSValue* breakAfterValue = aRuleData->ValueForPageBreakAfter();
  5679. if (eCSSUnit_Enumerated == breakAfterValue->GetUnit()) {
  5680. display->mBreakAfter =
  5681. (NS_STYLE_PAGE_BREAK_AVOID != breakAfterValue->GetIntValue() &&
  5682. NS_STYLE_PAGE_BREAK_AUTO != breakAfterValue->GetIntValue());
  5683. } else if (eCSSUnit_Initial == breakAfterValue->GetUnit() ||
  5684. eCSSUnit_Unset == breakAfterValue->GetUnit()) {
  5685. display->mBreakAfter = false;
  5686. } else if (eCSSUnit_Inherit == breakAfterValue->GetUnit()) {
  5687. conditions.SetUncacheable();
  5688. display->mBreakAfter = parentDisplay->mBreakAfter;
  5689. }
  5690. // end temp fix
  5691. // page-break-inside: enum, inherit, initial
  5692. SetValue(*aRuleData->ValueForPageBreakInside(),
  5693. display->mBreakInside, conditions,
  5694. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  5695. parentDisplay->mBreakInside,
  5696. NS_STYLE_PAGE_BREAK_AUTO);
  5697. // touch-action: none, auto, enum, inherit, initial
  5698. SetValue(*aRuleData->ValueForTouchAction(), display->mTouchAction,
  5699. conditions,
  5700. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  5701. parentDisplay->mTouchAction,
  5702. /* initial */ NS_STYLE_TOUCH_ACTION_AUTO,
  5703. /* auto */ NS_STYLE_TOUCH_ACTION_AUTO,
  5704. /* none */ NS_STYLE_TOUCH_ACTION_NONE, Unused, Unused);
  5705. // float: enum, inherit, initial
  5706. SetValue(*aRuleData->ValueForFloat(),
  5707. display->mFloat, conditions,
  5708. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  5709. parentDisplay->mFloat,
  5710. StyleFloat::None);
  5711. // Save mFloat in mOriginalFloat in case we need it later
  5712. display->mOriginalFloat = display->mFloat;
  5713. // overflow-x: enum, inherit, initial
  5714. SetValue(*aRuleData->ValueForOverflowX(),
  5715. display->mOverflowX, conditions,
  5716. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  5717. parentDisplay->mOverflowX,
  5718. NS_STYLE_OVERFLOW_VISIBLE);
  5719. // overflow-y: enum, inherit, initial
  5720. SetValue(*aRuleData->ValueForOverflowY(),
  5721. display->mOverflowY, conditions,
  5722. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  5723. parentDisplay->mOverflowY,
  5724. NS_STYLE_OVERFLOW_VISIBLE);
  5725. // CSS3 overflow-x and overflow-y require some fixup as well in some
  5726. // cases. NS_STYLE_OVERFLOW_VISIBLE and NS_STYLE_OVERFLOW_CLIP are
  5727. // meaningful only when used in both dimensions.
  5728. if (display->mOverflowX != display->mOverflowY &&
  5729. (display->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE ||
  5730. display->mOverflowX == NS_STYLE_OVERFLOW_CLIP ||
  5731. display->mOverflowY == NS_STYLE_OVERFLOW_VISIBLE ||
  5732. display->mOverflowY == NS_STYLE_OVERFLOW_CLIP)) {
  5733. // We can't store in the rule tree since a more specific rule might
  5734. // change these conditions.
  5735. conditions.SetUncacheable();
  5736. // NS_STYLE_OVERFLOW_CLIP is a deprecated value, so if it's specified
  5737. // in only one dimension, convert it to NS_STYLE_OVERFLOW_HIDDEN.
  5738. if (display->mOverflowX == NS_STYLE_OVERFLOW_CLIP) {
  5739. display->mOverflowX = NS_STYLE_OVERFLOW_HIDDEN;
  5740. }
  5741. if (display->mOverflowY == NS_STYLE_OVERFLOW_CLIP) {
  5742. display->mOverflowY = NS_STYLE_OVERFLOW_HIDDEN;
  5743. }
  5744. // If 'visible' is specified but doesn't match the other dimension, it
  5745. // turns into 'auto'.
  5746. if (display->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE) {
  5747. display->mOverflowX = NS_STYLE_OVERFLOW_AUTO;
  5748. }
  5749. if (display->mOverflowY == NS_STYLE_OVERFLOW_VISIBLE) {
  5750. display->mOverflowY = NS_STYLE_OVERFLOW_AUTO;
  5751. }
  5752. }
  5753. // When 'contain: paint', update overflow from 'visible' to 'clip'.
  5754. if (display->IsContainPaint()) {
  5755. // XXX This actually sets overflow-[x|y] to -moz-hidden-unscrollable.
  5756. if (display->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE) {
  5757. // This uncacheability (and the one below) could be fixed by adding
  5758. // mOriginalOverflowX and mOriginalOverflowY fields, if necessary.
  5759. display->mOverflowX = NS_STYLE_OVERFLOW_CLIP;
  5760. conditions.SetUncacheable();
  5761. }
  5762. if (display->mOverflowY == NS_STYLE_OVERFLOW_VISIBLE) {
  5763. display->mOverflowY = NS_STYLE_OVERFLOW_CLIP;
  5764. conditions.SetUncacheable();
  5765. }
  5766. }
  5767. SetValue(*aRuleData->ValueForOverflowClipBox(), display->mOverflowClipBox,
  5768. conditions,
  5769. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  5770. parentDisplay->mOverflowClipBox,
  5771. NS_STYLE_OVERFLOW_CLIP_BOX_PADDING_BOX);
  5772. SetValue(*aRuleData->ValueForResize(), display->mResize, conditions,
  5773. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  5774. parentDisplay->mResize,
  5775. NS_STYLE_RESIZE_NONE);
  5776. if (display->mDisplay != StyleDisplay::None) {
  5777. // CSS2 9.7 specifies display type corrections dealing with 'float'
  5778. // and 'position'. Since generated content can't be floated or
  5779. // positioned, we can deal with it here.
  5780. nsIAtom* pseudo = aContext->GetPseudo();
  5781. if (pseudo && display->mDisplay == StyleDisplay::Contents) {
  5782. // We don't want to create frames for anonymous content using a parent
  5783. // frame that is for content above the root of the anon tree.
  5784. // (XXX what we really should check here is not GetPseudo() but if there's
  5785. // a 'content' property value that implies anon content but we can't
  5786. // check that here since that's a different struct(?))
  5787. // We might get display:contents to work for CSS_PSEUDO_ELEMENT_CONTAINS_ELEMENTS
  5788. // pseudos (:first-letter etc) in the future, but those have a lot of
  5789. // special handling in frame construction so they are also unsupported
  5790. // for now.
  5791. display->mOriginalDisplay = display->mDisplay = StyleDisplay::Inline;
  5792. conditions.SetUncacheable();
  5793. }
  5794. // Inherit a <fieldset> grid/flex display type into its anon content frame.
  5795. if (pseudo == nsCSSAnonBoxes::fieldsetContent) {
  5796. MOZ_ASSERT(display->mDisplay == StyleDisplay::Block,
  5797. "forms.css should have set 'display:block'");
  5798. switch (parentDisplay->mDisplay) {
  5799. case StyleDisplay::Grid:
  5800. case StyleDisplay::InlineGrid:
  5801. display->mDisplay = StyleDisplay::Grid;
  5802. conditions.SetUncacheable();
  5803. break;
  5804. case StyleDisplay::Flex:
  5805. case StyleDisplay::InlineFlex:
  5806. display->mDisplay = StyleDisplay::Flex;
  5807. conditions.SetUncacheable();
  5808. break;
  5809. default:
  5810. break; // Do nothing
  5811. }
  5812. }
  5813. if (nsCSSPseudoElements::firstLetter == pseudo) {
  5814. // a non-floating first-letter must be inline
  5815. // XXX this fix can go away once bug 103189 is fixed correctly
  5816. // Note that we reset mOriginalDisplay to enforce the invariant that it equals mDisplay if we're not positioned or floating.
  5817. display->mOriginalDisplay = display->mDisplay = StyleDisplay::Inline;
  5818. // We can't cache the data in the rule tree since if a more specific
  5819. // rule has 'float: left' we'll end up with the wrong 'display'
  5820. // property.
  5821. conditions.SetUncacheable();
  5822. }
  5823. if (display->IsAbsolutelyPositionedStyle()) {
  5824. // 1) if position is 'absolute' or 'fixed' then display must be
  5825. // block-level and float must be 'none'
  5826. EnsureBlockDisplay(display->mDisplay);
  5827. display->mFloat = StyleFloat::None;
  5828. // Note that it's OK to cache this struct in the ruletree
  5829. // because it's fine as-is for any style context that points to
  5830. // it directly, and any use of it as aStartStruct (e.g. if a
  5831. // more specific rule sets "position: static") will use
  5832. // mOriginalDisplay and mOriginalFloat, which we have carefully
  5833. // not changed.
  5834. } else if (display->mFloat != StyleFloat::None) {
  5835. // 2) if float is not none, and display is not none, then we must
  5836. // set a block-level 'display' type per CSS2.1 section 9.7.
  5837. EnsureBlockDisplay(display->mDisplay);
  5838. // Note that it's OK to cache this struct in the ruletree
  5839. // because it's fine as-is for any style context that points to
  5840. // it directly, and any use of it as aStartStruct (e.g. if a
  5841. // more specific rule sets "float: none") will use
  5842. // mOriginalDisplay, which we have carefully not changed.
  5843. }
  5844. if (display->IsContainPaint()) {
  5845. // An element with contain:paint or contain:layout needs to "be a
  5846. // formatting context". For the purposes of the "display" property, that
  5847. // just means we need to promote "display:inline" to "inline-block".
  5848. // XXX We may also need to promote ruby display vals; see bug 1179349.
  5849. // It's okay to cache this change in the rule tree for the same
  5850. // reasons as floats in the previous condition.
  5851. if (display->mDisplay == StyleDisplay::Inline) {
  5852. display->mDisplay = StyleDisplay::InlineBlock;
  5853. }
  5854. }
  5855. }
  5856. /* Convert the nsCSSValueList into an nsTArray<nsTransformFunction *>. */
  5857. const nsCSSValue* transformValue = aRuleData->ValueForTransform();
  5858. switch (transformValue->GetUnit()) {
  5859. case eCSSUnit_Null:
  5860. break;
  5861. case eCSSUnit_Initial:
  5862. case eCSSUnit_Unset:
  5863. case eCSSUnit_None:
  5864. display->mSpecifiedTransform = nullptr;
  5865. break;
  5866. case eCSSUnit_Inherit:
  5867. display->mSpecifiedTransform = parentDisplay->mSpecifiedTransform;
  5868. conditions.SetUncacheable();
  5869. break;
  5870. case eCSSUnit_SharedList: {
  5871. nsCSSValueSharedList* list = transformValue->GetSharedListValue();
  5872. nsCSSValueList* head = list->mHead;
  5873. MOZ_ASSERT(head, "transform list must have at least one item");
  5874. // can get a _None in here from transform animation
  5875. if (head->mValue.GetUnit() == eCSSUnit_None) {
  5876. MOZ_ASSERT(head->mNext == nullptr, "none must be alone");
  5877. display->mSpecifiedTransform = nullptr;
  5878. } else {
  5879. display->mSpecifiedTransform = list;
  5880. }
  5881. break;
  5882. }
  5883. default:
  5884. MOZ_ASSERT(false, "unrecognized transform unit");
  5885. }
  5886. /* Convert the nsCSSValueList into a will-change bitfield for fast lookup */
  5887. const nsCSSValue* willChangeValue = aRuleData->ValueForWillChange();
  5888. switch (willChangeValue->GetUnit()) {
  5889. case eCSSUnit_Null:
  5890. break;
  5891. case eCSSUnit_List:
  5892. case eCSSUnit_ListDep: {
  5893. display->mWillChange.Clear();
  5894. display->mWillChangeBitField = 0;
  5895. for (const nsCSSValueList* item = willChangeValue->GetListValue();
  5896. item; item = item->mNext)
  5897. {
  5898. if (item->mValue.UnitHasStringValue()) {
  5899. nsAutoString buffer;
  5900. item->mValue.GetStringValue(buffer);
  5901. display->mWillChange.AppendElement(buffer);
  5902. if (buffer.EqualsLiteral("transform")) {
  5903. display->mWillChangeBitField |= NS_STYLE_WILL_CHANGE_TRANSFORM;
  5904. }
  5905. if (buffer.EqualsLiteral("opacity")) {
  5906. display->mWillChangeBitField |= NS_STYLE_WILL_CHANGE_OPACITY;
  5907. }
  5908. if (buffer.EqualsLiteral("scroll-position")) {
  5909. display->mWillChangeBitField |= NS_STYLE_WILL_CHANGE_SCROLL;
  5910. }
  5911. nsCSSPropertyID prop =
  5912. nsCSSProps::LookupProperty(buffer, CSSEnabledState::eForAllContent);
  5913. if (prop != eCSSProperty_UNKNOWN &&
  5914. prop != eCSSPropertyExtra_variable) {
  5915. // If the property given is a shorthand, it indicates the expectation
  5916. // for all the longhands the shorthand expands to.
  5917. if (nsCSSProps::IsShorthand(prop)) {
  5918. for (const nsCSSPropertyID* shorthands =
  5919. nsCSSProps::SubpropertyEntryFor(prop);
  5920. *shorthands != eCSSProperty_UNKNOWN; ++shorthands) {
  5921. display->mWillChangeBitField |= GetWillChangeBitFieldFromPropFlags(*shorthands);
  5922. }
  5923. } else {
  5924. display->mWillChangeBitField |= GetWillChangeBitFieldFromPropFlags(prop);
  5925. }
  5926. }
  5927. }
  5928. }
  5929. break;
  5930. }
  5931. case eCSSUnit_Inherit:
  5932. display->mWillChange = parentDisplay->mWillChange;
  5933. display->mWillChangeBitField = parentDisplay->mWillChangeBitField;
  5934. conditions.SetUncacheable();
  5935. break;
  5936. case eCSSUnit_Initial:
  5937. case eCSSUnit_Unset:
  5938. case eCSSUnit_Auto:
  5939. display->mWillChange.Clear();
  5940. display->mWillChangeBitField = 0;
  5941. break;
  5942. default:
  5943. MOZ_ASSERT(false, "unrecognized will-change unit");
  5944. }
  5945. // vertical-align: enum, length, percent, calc, inherit
  5946. const nsCSSValue* verticalAlignValue = aRuleData->ValueForVerticalAlign();
  5947. if (!SetCoord(*verticalAlignValue, display->mVerticalAlign,
  5948. parentDisplay->mVerticalAlign,
  5949. SETCOORD_LPH | SETCOORD_ENUMERATED | SETCOORD_STORE_CALC,
  5950. aContext, mPresContext, conditions)) {
  5951. if (eCSSUnit_Initial == verticalAlignValue->GetUnit() ||
  5952. eCSSUnit_Unset == verticalAlignValue->GetUnit()) {
  5953. display->mVerticalAlign.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE,
  5954. eStyleUnit_Enumerated);
  5955. }
  5956. }
  5957. /* Convert -moz-transform-origin. */
  5958. const nsCSSValue* transformOriginValue =
  5959. aRuleData->ValueForTransformOrigin();
  5960. if (transformOriginValue->GetUnit() != eCSSUnit_Null) {
  5961. const nsCSSValue& valX =
  5962. transformOriginValue->GetUnit() == eCSSUnit_Triplet ?
  5963. transformOriginValue->GetTripletValue().mXValue : *transformOriginValue;
  5964. const nsCSSValue& valY =
  5965. transformOriginValue->GetUnit() == eCSSUnit_Triplet ?
  5966. transformOriginValue->GetTripletValue().mYValue : *transformOriginValue;
  5967. const nsCSSValue& valZ =
  5968. transformOriginValue->GetUnit() == eCSSUnit_Triplet ?
  5969. transformOriginValue->GetTripletValue().mZValue : *transformOriginValue;
  5970. mozilla::DebugOnly<bool> cX =
  5971. SetCoord(valX, display->mTransformOrigin[0],
  5972. parentDisplay->mTransformOrigin[0],
  5973. SETCOORD_LPH | SETCOORD_INITIAL_HALF |
  5974. SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC |
  5975. SETCOORD_UNSET_INITIAL,
  5976. aContext, mPresContext, conditions);
  5977. mozilla::DebugOnly<bool> cY =
  5978. SetCoord(valY, display->mTransformOrigin[1],
  5979. parentDisplay->mTransformOrigin[1],
  5980. SETCOORD_LPH | SETCOORD_INITIAL_HALF |
  5981. SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC |
  5982. SETCOORD_UNSET_INITIAL,
  5983. aContext, mPresContext, conditions);
  5984. if (valZ.GetUnit() == eCSSUnit_Null) {
  5985. // Null for the z component means a 0 translation, not
  5986. // unspecified, as we have already checked the triplet
  5987. // value for Null.
  5988. display->mTransformOrigin[2].SetCoordValue(0);
  5989. } else {
  5990. mozilla::DebugOnly<bool> cZ =
  5991. SetCoord(valZ, display->mTransformOrigin[2],
  5992. parentDisplay->mTransformOrigin[2],
  5993. SETCOORD_LH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC |
  5994. SETCOORD_UNSET_INITIAL,
  5995. aContext, mPresContext, conditions);
  5996. MOZ_ASSERT(cY == cZ, "changed one but not the other");
  5997. }
  5998. MOZ_ASSERT(cX == cY, "changed one but not the other");
  5999. NS_ASSERTION(cX, "Malformed -moz-transform-origin parse!");
  6000. }
  6001. const nsCSSValue* perspectiveOriginValue =
  6002. aRuleData->ValueForPerspectiveOrigin();
  6003. if (perspectiveOriginValue->GetUnit() != eCSSUnit_Null) {
  6004. mozilla::DebugOnly<bool> result =
  6005. SetPairCoords(*perspectiveOriginValue,
  6006. display->mPerspectiveOrigin[0],
  6007. display->mPerspectiveOrigin[1],
  6008. parentDisplay->mPerspectiveOrigin[0],
  6009. parentDisplay->mPerspectiveOrigin[1],
  6010. SETCOORD_LPH | SETCOORD_INITIAL_HALF |
  6011. SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC |
  6012. SETCOORD_UNSET_INITIAL,
  6013. aContext, mPresContext, conditions);
  6014. NS_ASSERTION(result, "Malformed -moz-perspective-origin parse!");
  6015. }
  6016. SetCoord(*aRuleData->ValueForPerspective(),
  6017. display->mChildPerspective, parentDisplay->mChildPerspective,
  6018. SETCOORD_LAH | SETCOORD_INITIAL_NONE | SETCOORD_NONE |
  6019. SETCOORD_UNSET_INITIAL,
  6020. aContext, mPresContext, conditions);
  6021. SetValue(*aRuleData->ValueForBackfaceVisibility(),
  6022. display->mBackfaceVisibility, conditions,
  6023. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  6024. parentDisplay->mBackfaceVisibility,
  6025. NS_STYLE_BACKFACE_VISIBILITY_VISIBLE);
  6026. // transform-style: enum, inherit, initial
  6027. SetValue(*aRuleData->ValueForTransformStyle(),
  6028. display->mTransformStyle, conditions,
  6029. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  6030. parentDisplay->mTransformStyle,
  6031. NS_STYLE_TRANSFORM_STYLE_FLAT);
  6032. // transform-box: enum, inherit, initial
  6033. SetValue(*aRuleData->ValueForTransformBox(),
  6034. display->mTransformBox, conditions,
  6035. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  6036. parentDisplay->mTransformBox,
  6037. NS_STYLE_TRANSFORM_BOX_BORDER_BOX);
  6038. // orient: enum, inherit, initial
  6039. SetValue(*aRuleData->ValueForOrient(),
  6040. display->mOrient, conditions,
  6041. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  6042. parentDisplay->mOrient,
  6043. StyleOrient::Inline);
  6044. // shape-outside: none | [ <basic-shape> || <shape-box> ] | <image>
  6045. const nsCSSValue* shapeOutsideValue = aRuleData->ValueForShapeOutside();
  6046. switch (shapeOutsideValue->GetUnit()) {
  6047. case eCSSUnit_Null:
  6048. break;
  6049. case eCSSUnit_None:
  6050. case eCSSUnit_Initial:
  6051. case eCSSUnit_Unset:
  6052. display->mShapeOutside = StyleShapeOutside();
  6053. break;
  6054. case eCSSUnit_Inherit:
  6055. conditions.SetUncacheable();
  6056. display->mShapeOutside = parentDisplay->mShapeOutside;
  6057. break;
  6058. case eCSSUnit_URL: {
  6059. display->mShapeOutside = StyleShapeOutside();
  6060. display->mShapeOutside.SetURL(shapeOutsideValue->GetURLStructValue());
  6061. break;
  6062. }
  6063. case eCSSUnit_Array: {
  6064. display->mShapeOutside = StyleShapeOutside();
  6065. SetStyleShapeSourceToCSSValue(&display->mShapeOutside, shapeOutsideValue,
  6066. aContext, mPresContext, conditions);
  6067. break;
  6068. }
  6069. default:
  6070. MOZ_ASSERT_UNREACHABLE("Unrecognized shape-outside unit!");
  6071. }
  6072. COMPUTE_END_RESET(Display, display)
  6073. }
  6074. const void*
  6075. nsRuleNode::ComputeVisibilityData(void* aStartStruct,
  6076. const nsRuleData* aRuleData,
  6077. nsStyleContext* aContext,
  6078. nsRuleNode* aHighestNode,
  6079. const RuleDetail aRuleDetail,
  6080. const RuleNodeCacheConditions aConditions)
  6081. {
  6082. COMPUTE_START_INHERITED(Visibility, visibility, parentVisibility)
  6083. // IMPORTANT: No properties in this struct have lengths in them. We
  6084. // depend on this since CalcLengthWith can call StyleVisibility()
  6085. // to get the language for resolving fonts!
  6086. // direction: enum, inherit, initial
  6087. SetValue(*aRuleData->ValueForDirection(), visibility->mDirection,
  6088. conditions,
  6089. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  6090. parentVisibility->mDirection,
  6091. (GET_BIDI_OPTION_DIRECTION(mPresContext->GetBidi())
  6092. == IBMBIDI_TEXTDIRECTION_RTL)
  6093. ? NS_STYLE_DIRECTION_RTL : NS_STYLE_DIRECTION_LTR);
  6094. // visibility: enum, inherit, initial
  6095. SetValue(*aRuleData->ValueForVisibility(), visibility->mVisible,
  6096. conditions,
  6097. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  6098. parentVisibility->mVisible,
  6099. NS_STYLE_VISIBILITY_VISIBLE);
  6100. // image-rendering: enum, inherit
  6101. SetValue(*aRuleData->ValueForImageRendering(),
  6102. visibility->mImageRendering, conditions,
  6103. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  6104. parentVisibility->mImageRendering,
  6105. NS_STYLE_IMAGE_RENDERING_AUTO);
  6106. // writing-mode: enum, inherit, initial
  6107. SetValue(*aRuleData->ValueForWritingMode(), visibility->mWritingMode,
  6108. conditions,
  6109. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  6110. parentVisibility->mWritingMode,
  6111. NS_STYLE_WRITING_MODE_HORIZONTAL_TB);
  6112. // text-orientation: enum, inherit, initial
  6113. SetValue(*aRuleData->ValueForTextOrientation(), visibility->mTextOrientation,
  6114. conditions,
  6115. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  6116. parentVisibility->mTextOrientation,
  6117. NS_STYLE_TEXT_ORIENTATION_MIXED);
  6118. // image-orientation: enum, inherit, initial
  6119. const nsCSSValue* orientation = aRuleData->ValueForImageOrientation();
  6120. if (orientation->GetUnit() == eCSSUnit_Inherit ||
  6121. orientation->GetUnit() == eCSSUnit_Unset) {
  6122. conditions.SetUncacheable();
  6123. visibility->mImageOrientation = parentVisibility->mImageOrientation;
  6124. } else if (orientation->GetUnit() == eCSSUnit_Initial) {
  6125. visibility->mImageOrientation = nsStyleImageOrientation();
  6126. } else if (orientation->IsAngularUnit()) {
  6127. double angle = orientation->GetAngleValueInRadians();
  6128. visibility->mImageOrientation =
  6129. nsStyleImageOrientation::CreateAsAngleAndFlip(angle, false);
  6130. } else if (orientation->GetUnit() == eCSSUnit_Array) {
  6131. const nsCSSValue::Array* array = orientation->GetArrayValue();
  6132. MOZ_ASSERT(array->Item(0).IsAngularUnit(),
  6133. "First image-orientation value is not an angle");
  6134. MOZ_ASSERT(array->Item(1).GetUnit() == eCSSUnit_Enumerated &&
  6135. array->Item(1).GetIntValue() == NS_STYLE_IMAGE_ORIENTATION_FLIP,
  6136. "Second image-orientation value is not 'flip'");
  6137. double angle = array->Item(0).GetAngleValueInRadians();
  6138. visibility->mImageOrientation =
  6139. nsStyleImageOrientation::CreateAsAngleAndFlip(angle, true);
  6140. } else if (orientation->GetUnit() == eCSSUnit_Enumerated) {
  6141. switch (orientation->GetIntValue()) {
  6142. case NS_STYLE_IMAGE_ORIENTATION_FLIP:
  6143. visibility->mImageOrientation = nsStyleImageOrientation::CreateAsFlip();
  6144. break;
  6145. case NS_STYLE_IMAGE_ORIENTATION_FROM_IMAGE:
  6146. visibility->mImageOrientation = nsStyleImageOrientation::CreateAsFromImage();
  6147. break;
  6148. default:
  6149. NS_NOTREACHED("Invalid image-orientation enumerated value");
  6150. }
  6151. } else {
  6152. MOZ_ASSERT(orientation->GetUnit() == eCSSUnit_Null, "Should be null unit");
  6153. }
  6154. SetValue(*aRuleData->ValueForColorAdjust(), visibility->mColorAdjust,
  6155. conditions,
  6156. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  6157. parentVisibility->mColorAdjust,
  6158. NS_STYLE_COLOR_ADJUST_ECONOMY);
  6159. COMPUTE_END_INHERITED(Visibility, visibility)
  6160. }
  6161. const void*
  6162. nsRuleNode::ComputeColorData(void* aStartStruct,
  6163. const nsRuleData* aRuleData,
  6164. nsStyleContext* aContext,
  6165. nsRuleNode* aHighestNode,
  6166. const RuleDetail aRuleDetail,
  6167. const RuleNodeCacheConditions aConditions)
  6168. {
  6169. COMPUTE_START_INHERITED(Color, color, parentColor)
  6170. // color: color, string, inherit
  6171. // Special case for currentColor. According to CSS3, setting color to 'currentColor'
  6172. // should behave as if it is inherited
  6173. const nsCSSValue* colorValue = aRuleData->ValueForColor();
  6174. if ((colorValue->GetUnit() == eCSSUnit_EnumColor &&
  6175. colorValue->GetIntValue() == NS_COLOR_CURRENTCOLOR) ||
  6176. colorValue->GetUnit() == eCSSUnit_Unset) {
  6177. color->mColor = parentColor->mColor;
  6178. conditions.SetUncacheable();
  6179. } else if (colorValue->GetUnit() == eCSSUnit_Initial) {
  6180. color->mColor = mPresContext->DefaultColor();
  6181. } else {
  6182. SetColor(*colorValue, parentColor->mColor, mPresContext, aContext,
  6183. color->mColor, conditions);
  6184. }
  6185. COMPUTE_END_INHERITED(Color, color)
  6186. }
  6187. // information about how to compute values for background-* properties
  6188. template <class SpecifiedValueItem, class ComputedValueItem>
  6189. struct BackgroundItemComputer {
  6190. };
  6191. template <>
  6192. struct BackgroundItemComputer<nsCSSValueList, uint8_t>
  6193. {
  6194. static void ComputeValue(nsStyleContext* aStyleContext,
  6195. const nsCSSValueList* aSpecifiedValue,
  6196. uint8_t& aComputedValue,
  6197. RuleNodeCacheConditions& aConditions)
  6198. {
  6199. SetValue(aSpecifiedValue->mValue, aComputedValue, aConditions,
  6200. SETVAL_ENUMERATED, uint8_t(0), 0);
  6201. }
  6202. };
  6203. template <>
  6204. struct BackgroundItemComputer<nsCSSValuePairList, nsStyleImageLayers::Repeat>
  6205. {
  6206. static void ComputeValue(nsStyleContext* aStyleContext,
  6207. const nsCSSValuePairList* aSpecifiedValue,
  6208. nsStyleImageLayers::Repeat& aComputedValue,
  6209. RuleNodeCacheConditions& aConditions)
  6210. {
  6211. NS_ASSERTION(aSpecifiedValue->mXValue.GetUnit() == eCSSUnit_Enumerated &&
  6212. (aSpecifiedValue->mYValue.GetUnit() == eCSSUnit_Enumerated ||
  6213. aSpecifiedValue->mYValue.GetUnit() == eCSSUnit_Null),
  6214. "Invalid unit");
  6215. bool hasContraction = true;
  6216. uint8_t value = aSpecifiedValue->mXValue.GetIntValue();
  6217. switch (value) {
  6218. case NS_STYLE_IMAGELAYER_REPEAT_REPEAT_X:
  6219. aComputedValue.mXRepeat = NS_STYLE_IMAGELAYER_REPEAT_REPEAT;
  6220. aComputedValue.mYRepeat = NS_STYLE_IMAGELAYER_REPEAT_NO_REPEAT;
  6221. break;
  6222. case NS_STYLE_IMAGELAYER_REPEAT_REPEAT_Y:
  6223. aComputedValue.mXRepeat = NS_STYLE_IMAGELAYER_REPEAT_NO_REPEAT;
  6224. aComputedValue.mYRepeat = NS_STYLE_IMAGELAYER_REPEAT_REPEAT;
  6225. break;
  6226. default:
  6227. NS_ASSERTION(value == NS_STYLE_IMAGELAYER_REPEAT_NO_REPEAT ||
  6228. value == NS_STYLE_IMAGELAYER_REPEAT_REPEAT ||
  6229. value == NS_STYLE_IMAGELAYER_REPEAT_SPACE ||
  6230. value == NS_STYLE_IMAGELAYER_REPEAT_ROUND, "Unexpected value");
  6231. aComputedValue.mXRepeat = value;
  6232. hasContraction = false;
  6233. break;
  6234. }
  6235. if (hasContraction) {
  6236. NS_ASSERTION(aSpecifiedValue->mYValue.GetUnit() == eCSSUnit_Null,
  6237. "Invalid unit.");
  6238. return;
  6239. }
  6240. switch (aSpecifiedValue->mYValue.GetUnit()) {
  6241. case eCSSUnit_Null:
  6242. aComputedValue.mYRepeat = aComputedValue.mXRepeat;
  6243. break;
  6244. case eCSSUnit_Enumerated:
  6245. value = aSpecifiedValue->mYValue.GetIntValue();
  6246. NS_ASSERTION(value == NS_STYLE_IMAGELAYER_REPEAT_NO_REPEAT ||
  6247. value == NS_STYLE_IMAGELAYER_REPEAT_REPEAT ||
  6248. value == NS_STYLE_IMAGELAYER_REPEAT_SPACE ||
  6249. value == NS_STYLE_IMAGELAYER_REPEAT_ROUND, "Unexpected value");
  6250. aComputedValue.mYRepeat = value;
  6251. break;
  6252. default:
  6253. NS_NOTREACHED("Unexpected CSS value");
  6254. break;
  6255. }
  6256. }
  6257. };
  6258. template <>
  6259. struct BackgroundItemComputer<nsCSSValueList, nsStyleImage>
  6260. {
  6261. static void ComputeValue(nsStyleContext* aStyleContext,
  6262. const nsCSSValueList* aSpecifiedValue,
  6263. nsStyleImage& aComputedValue,
  6264. RuleNodeCacheConditions& aConditions)
  6265. {
  6266. SetStyleImage(aStyleContext, aSpecifiedValue->mValue, aComputedValue,
  6267. aConditions);
  6268. }
  6269. };
  6270. template <>
  6271. struct BackgroundItemComputer<nsCSSValueList, RefPtr<css::URLValueData>>
  6272. {
  6273. static void ComputeValue(nsStyleContext* aStyleContext,
  6274. const nsCSSValueList* aSpecifiedValue,
  6275. RefPtr<css::URLValueData>& aComputedValue,
  6276. RuleNodeCacheConditions& aConditions)
  6277. {
  6278. switch (aSpecifiedValue->mValue.GetUnit()) {
  6279. case eCSSUnit_Null:
  6280. break;
  6281. case eCSSUnit_URL:
  6282. aComputedValue = aSpecifiedValue->mValue.GetURLStructValue();
  6283. break;
  6284. case eCSSUnit_Image:
  6285. aComputedValue = aSpecifiedValue->mValue.GetImageStructValue();
  6286. break;
  6287. default:
  6288. aComputedValue = nullptr;
  6289. break;
  6290. }
  6291. }
  6292. };
  6293. template <typename T>
  6294. struct BackgroundItemComputer<nsCSSValueList, T>
  6295. {
  6296. typedef typename EnableIf<IsEnum<T>::value, T>::Type ComputedType;
  6297. static void ComputeValue(nsStyleContext* aStyleContext,
  6298. const nsCSSValueList* aSpecifiedValue,
  6299. ComputedType& aComputedValue,
  6300. RuleNodeCacheConditions& aConditions)
  6301. {
  6302. aComputedValue =
  6303. static_cast<T>(aSpecifiedValue->mValue.GetIntValue());
  6304. }
  6305. };
  6306. /* Helper function for ComputePositionValue.
  6307. * This function computes a single PositionCoord from two nsCSSValue objects,
  6308. * which represent an edge and an offset from that edge.
  6309. */
  6310. static void
  6311. ComputePositionCoord(nsStyleContext* aStyleContext,
  6312. const nsCSSValue& aEdge,
  6313. const nsCSSValue& aOffset,
  6314. Position::Coord* aResult,
  6315. RuleNodeCacheConditions& aConditions)
  6316. {
  6317. if (eCSSUnit_Percent == aOffset.GetUnit()) {
  6318. aResult->mLength = 0;
  6319. aResult->mPercent = aOffset.GetPercentValue();
  6320. aResult->mHasPercent = true;
  6321. } else if (aOffset.IsLengthUnit()) {
  6322. aResult->mLength = CalcLength(aOffset, aStyleContext,
  6323. aStyleContext->PresContext(),
  6324. aConditions);
  6325. aResult->mPercent = 0.0f;
  6326. aResult->mHasPercent = false;
  6327. } else if (aOffset.IsCalcUnit()) {
  6328. LengthPercentPairCalcOps ops(aStyleContext,
  6329. aStyleContext->PresContext(),
  6330. aConditions);
  6331. nsRuleNode::ComputedCalc vals = ComputeCalc(aOffset, ops);
  6332. aResult->mLength = vals.mLength;
  6333. aResult->mPercent = vals.mPercent;
  6334. aResult->mHasPercent = ops.mHasPercent;
  6335. } else {
  6336. aResult->mLength = 0;
  6337. aResult->mPercent = 0.0f;
  6338. aResult->mHasPercent = false;
  6339. NS_ASSERTION(aOffset.GetUnit() == eCSSUnit_Null, "unexpected unit");
  6340. }
  6341. if (eCSSUnit_Enumerated == aEdge.GetUnit()) {
  6342. int sign;
  6343. if (aEdge.GetIntValue() & (NS_STYLE_IMAGELAYER_POSITION_BOTTOM |
  6344. NS_STYLE_IMAGELAYER_POSITION_RIGHT)) {
  6345. sign = -1;
  6346. } else {
  6347. sign = 1;
  6348. }
  6349. aResult->mPercent = GetFloatFromBoxPosition(aEdge.GetIntValue()) +
  6350. sign * aResult->mPercent;
  6351. aResult->mLength = sign * aResult->mLength;
  6352. aResult->mHasPercent = true;
  6353. } else {
  6354. NS_ASSERTION(eCSSUnit_Null == aEdge.GetUnit(), "unexpected unit");
  6355. }
  6356. }
  6357. /* Helper function to convert a CSS <position> specified value into its
  6358. * computed-style form. */
  6359. static void
  6360. ComputePositionValue(nsStyleContext* aStyleContext,
  6361. const nsCSSValue& aValue,
  6362. Position& aComputedValue,
  6363. RuleNodeCacheConditions& aConditions)
  6364. {
  6365. NS_ASSERTION(aValue.GetUnit() == eCSSUnit_Array,
  6366. "unexpected unit for CSS <position> value");
  6367. RefPtr<nsCSSValue::Array> positionArray = aValue.GetArrayValue();
  6368. NS_ASSERTION(positionArray->Count() == 4,
  6369. "unexpected number of values in CSS <position> value");
  6370. const nsCSSValue &xEdge = positionArray->Item(0);
  6371. const nsCSSValue &xOffset = positionArray->Item(1);
  6372. const nsCSSValue &yEdge = positionArray->Item(2);
  6373. const nsCSSValue &yOffset = positionArray->Item(3);
  6374. NS_ASSERTION((eCSSUnit_Enumerated == xEdge.GetUnit() ||
  6375. eCSSUnit_Null == xEdge.GetUnit()) &&
  6376. (eCSSUnit_Enumerated == yEdge.GetUnit() ||
  6377. eCSSUnit_Null == yEdge.GetUnit()) &&
  6378. eCSSUnit_Enumerated != xOffset.GetUnit() &&
  6379. eCSSUnit_Enumerated != yOffset.GetUnit(),
  6380. "Invalid background position");
  6381. ComputePositionCoord(aStyleContext, xEdge, xOffset,
  6382. &aComputedValue.mXPosition,
  6383. aConditions);
  6384. ComputePositionCoord(aStyleContext, yEdge, yOffset,
  6385. &aComputedValue.mYPosition,
  6386. aConditions);
  6387. }
  6388. /* Helper function to convert the -x or -y part of a CSS <position> specified
  6389. * value into its computed-style form. */
  6390. static void
  6391. ComputePositionCoordValue(nsStyleContext* aStyleContext,
  6392. const nsCSSValue& aValue,
  6393. Position::Coord& aComputedValue,
  6394. RuleNodeCacheConditions& aConditions)
  6395. {
  6396. NS_ASSERTION(aValue.GetUnit() == eCSSUnit_Array,
  6397. "unexpected unit for position coord value");
  6398. RefPtr<nsCSSValue::Array> positionArray = aValue.GetArrayValue();
  6399. NS_ASSERTION(positionArray->Count() == 2,
  6400. "unexpected number of values, expecting one edge and one offset");
  6401. const nsCSSValue &edge = positionArray->Item(0);
  6402. const nsCSSValue &offset = positionArray->Item(1);
  6403. NS_ASSERTION((eCSSUnit_Enumerated == edge.GetUnit() ||
  6404. eCSSUnit_Null == edge.GetUnit()) &&
  6405. eCSSUnit_Enumerated != offset.GetUnit(),
  6406. "Invalid background position");
  6407. ComputePositionCoord(aStyleContext, edge, offset,
  6408. &aComputedValue,
  6409. aConditions);
  6410. }
  6411. struct BackgroundSizeAxis {
  6412. nsCSSValue nsCSSValuePairList::* specified;
  6413. nsStyleImageLayers::Size::Dimension nsStyleImageLayers::Size::* result;
  6414. uint8_t nsStyleImageLayers::Size::* type;
  6415. };
  6416. static const BackgroundSizeAxis gBGSizeAxes[] = {
  6417. { &nsCSSValuePairList::mXValue,
  6418. &nsStyleImageLayers::Size::mWidth,
  6419. &nsStyleImageLayers::Size::mWidthType },
  6420. { &nsCSSValuePairList::mYValue,
  6421. &nsStyleImageLayers::Size::mHeight,
  6422. &nsStyleImageLayers::Size::mHeightType }
  6423. };
  6424. template <>
  6425. struct BackgroundItemComputer<nsCSSValuePairList, nsStyleImageLayers::Size>
  6426. {
  6427. static void ComputeValue(nsStyleContext* aStyleContext,
  6428. const nsCSSValuePairList* aSpecifiedValue,
  6429. nsStyleImageLayers::Size& aComputedValue,
  6430. RuleNodeCacheConditions& aConditions)
  6431. {
  6432. nsStyleImageLayers::Size &size = aComputedValue;
  6433. for (const BackgroundSizeAxis *axis = gBGSizeAxes,
  6434. *axis_end = ArrayEnd(gBGSizeAxes);
  6435. axis < axis_end; ++axis) {
  6436. const nsCSSValue &specified = aSpecifiedValue->*(axis->specified);
  6437. if (eCSSUnit_Auto == specified.GetUnit()) {
  6438. size.*(axis->type) = nsStyleImageLayers::Size::eAuto;
  6439. } else if (eCSSUnit_Enumerated == specified.GetUnit()) {
  6440. static_assert(nsStyleImageLayers::Size::eContain ==
  6441. NS_STYLE_IMAGELAYER_SIZE_CONTAIN &&
  6442. nsStyleImageLayers::Size::eCover ==
  6443. NS_STYLE_IMAGELAYER_SIZE_COVER,
  6444. "background size constants out of sync");
  6445. MOZ_ASSERT(specified.GetIntValue() == NS_STYLE_IMAGELAYER_SIZE_CONTAIN ||
  6446. specified.GetIntValue() == NS_STYLE_IMAGELAYER_SIZE_COVER,
  6447. "invalid enumerated value for size coordinate");
  6448. size.*(axis->type) = specified.GetIntValue();
  6449. } else if (eCSSUnit_Null == specified.GetUnit()) {
  6450. MOZ_ASSERT(axis == gBGSizeAxes + 1,
  6451. "null allowed only as height value, and only "
  6452. "for contain/cover/initial/inherit");
  6453. #ifdef DEBUG
  6454. {
  6455. const nsCSSValue &widthValue = aSpecifiedValue->mXValue;
  6456. MOZ_ASSERT(widthValue.GetUnit() != eCSSUnit_Inherit &&
  6457. widthValue.GetUnit() != eCSSUnit_Initial &&
  6458. widthValue.GetUnit() != eCSSUnit_Unset,
  6459. "initial/inherit/unset should already have been handled");
  6460. MOZ_ASSERT(widthValue.GetUnit() == eCSSUnit_Enumerated &&
  6461. (widthValue.GetIntValue() == NS_STYLE_IMAGELAYER_SIZE_CONTAIN ||
  6462. widthValue.GetIntValue() == NS_STYLE_IMAGELAYER_SIZE_COVER),
  6463. "null height value not corresponding to allowable "
  6464. "non-null width value");
  6465. }
  6466. #endif
  6467. size.*(axis->type) = size.mWidthType;
  6468. } else if (eCSSUnit_Percent == specified.GetUnit()) {
  6469. (size.*(axis->result)).mLength = 0;
  6470. (size.*(axis->result)).mPercent = specified.GetPercentValue();
  6471. (size.*(axis->result)).mHasPercent = true;
  6472. size.*(axis->type) = nsStyleImageLayers::Size::eLengthPercentage;
  6473. } else if (specified.IsLengthUnit()) {
  6474. (size.*(axis->result)).mLength =
  6475. CalcLength(specified, aStyleContext, aStyleContext->PresContext(),
  6476. aConditions);
  6477. (size.*(axis->result)).mPercent = 0.0f;
  6478. (size.*(axis->result)).mHasPercent = false;
  6479. size.*(axis->type) = nsStyleImageLayers::Size::eLengthPercentage;
  6480. } else {
  6481. MOZ_ASSERT(specified.IsCalcUnit(), "unexpected unit");
  6482. LengthPercentPairCalcOps ops(aStyleContext,
  6483. aStyleContext->PresContext(),
  6484. aConditions);
  6485. nsRuleNode::ComputedCalc vals = ComputeCalc(specified, ops);
  6486. (size.*(axis->result)).mLength = vals.mLength;
  6487. (size.*(axis->result)).mPercent = vals.mPercent;
  6488. (size.*(axis->result)).mHasPercent = ops.mHasPercent;
  6489. size.*(axis->type) = nsStyleImageLayers::Size::eLengthPercentage;
  6490. }
  6491. }
  6492. MOZ_ASSERT(size.mWidthType < nsStyleImageLayers::Size::eDimensionType_COUNT,
  6493. "bad width type");
  6494. MOZ_ASSERT(size.mHeightType < nsStyleImageLayers::Size::eDimensionType_COUNT,
  6495. "bad height type");
  6496. MOZ_ASSERT((size.mWidthType != nsStyleImageLayers::Size::eContain &&
  6497. size.mWidthType != nsStyleImageLayers::Size::eCover) ||
  6498. size.mWidthType == size.mHeightType,
  6499. "contain/cover apply to both dimensions or to neither");
  6500. }
  6501. };
  6502. template <class ComputedValueItem>
  6503. static void
  6504. SetImageLayerList(nsStyleContext* aStyleContext,
  6505. const nsCSSValue& aValue,
  6506. nsStyleAutoArray<nsStyleImageLayers::Layer>& aLayers,
  6507. const nsStyleAutoArray<nsStyleImageLayers::Layer>& aParentLayers,
  6508. ComputedValueItem nsStyleImageLayers::Layer::* aResultLocation,
  6509. ComputedValueItem aInitialValue,
  6510. uint32_t aParentItemCount,
  6511. uint32_t& aItemCount,
  6512. uint32_t& aMaxItemCount,
  6513. bool& aRebuild,
  6514. RuleNodeCacheConditions& aConditions)
  6515. {
  6516. switch (aValue.GetUnit()) {
  6517. case eCSSUnit_Null:
  6518. break;
  6519. case eCSSUnit_Inherit:
  6520. aRebuild = true;
  6521. aConditions.SetUncacheable();
  6522. aLayers.EnsureLengthAtLeast(aParentItemCount);
  6523. aItemCount = aParentItemCount;
  6524. for (uint32_t i = 0; i < aParentItemCount; ++i) {
  6525. aLayers[i].*aResultLocation = aParentLayers[i].*aResultLocation;
  6526. }
  6527. break;
  6528. case eCSSUnit_Initial:
  6529. case eCSSUnit_Unset:
  6530. aRebuild = true;
  6531. aItemCount = 1;
  6532. aLayers[0].*aResultLocation = aInitialValue;
  6533. break;
  6534. case eCSSUnit_List:
  6535. case eCSSUnit_ListDep: {
  6536. aRebuild = true;
  6537. aItemCount = 0;
  6538. const nsCSSValueList* item = aValue.GetListValue();
  6539. do {
  6540. NS_ASSERTION(item->mValue.GetUnit() != eCSSUnit_Null &&
  6541. item->mValue.GetUnit() != eCSSUnit_Inherit &&
  6542. item->mValue.GetUnit() != eCSSUnit_Initial &&
  6543. item->mValue.GetUnit() != eCSSUnit_Unset,
  6544. "unexpected unit");
  6545. ++aItemCount;
  6546. aLayers.EnsureLengthAtLeast(aItemCount);
  6547. BackgroundItemComputer<nsCSSValueList, ComputedValueItem>
  6548. ::ComputeValue(aStyleContext, item,
  6549. aLayers[aItemCount-1].*aResultLocation,
  6550. aConditions);
  6551. item = item->mNext;
  6552. } while (item);
  6553. break;
  6554. }
  6555. default:
  6556. MOZ_ASSERT(false, "unexpected unit");
  6557. }
  6558. if (aItemCount > aMaxItemCount) {
  6559. aMaxItemCount = aItemCount;
  6560. }
  6561. }
  6562. // The same as SetImageLayerList, but for values stored in
  6563. // layer.mPosition.*aResultLocation instead of layer.*aResultLocation.
  6564. // This code is duplicated because it would be annoying to make
  6565. // SetImageLayerList generic enough to handle both cases.
  6566. static void
  6567. SetImageLayerPositionCoordList(
  6568. nsStyleContext* aStyleContext,
  6569. const nsCSSValue& aValue,
  6570. nsStyleAutoArray<nsStyleImageLayers::Layer>& aLayers,
  6571. const nsStyleAutoArray<nsStyleImageLayers::Layer>& aParentLayers,
  6572. Position::Coord
  6573. Position::* aResultLocation,
  6574. Position::Coord aInitialValue,
  6575. uint32_t aParentItemCount,
  6576. uint32_t& aItemCount,
  6577. uint32_t& aMaxItemCount,
  6578. bool& aRebuild,
  6579. RuleNodeCacheConditions& aConditions)
  6580. {
  6581. switch (aValue.GetUnit()) {
  6582. case eCSSUnit_Null:
  6583. break;
  6584. case eCSSUnit_Inherit:
  6585. aRebuild = true;
  6586. aConditions.SetUncacheable();
  6587. aLayers.EnsureLengthAtLeast(aParentItemCount);
  6588. aItemCount = aParentItemCount;
  6589. for (uint32_t i = 0; i < aParentItemCount; ++i) {
  6590. aLayers[i].mPosition.*aResultLocation = aParentLayers[i].mPosition.*aResultLocation;
  6591. }
  6592. break;
  6593. case eCSSUnit_Initial:
  6594. case eCSSUnit_Unset:
  6595. aRebuild = true;
  6596. aItemCount = 1;
  6597. aLayers[0].mPosition.*aResultLocation = aInitialValue;
  6598. break;
  6599. case eCSSUnit_List:
  6600. case eCSSUnit_ListDep: {
  6601. aRebuild = true;
  6602. aItemCount = 0;
  6603. const nsCSSValueList* item = aValue.GetListValue();
  6604. do {
  6605. NS_ASSERTION(item->mValue.GetUnit() != eCSSUnit_Null &&
  6606. item->mValue.GetUnit() != eCSSUnit_Inherit &&
  6607. item->mValue.GetUnit() != eCSSUnit_Initial &&
  6608. item->mValue.GetUnit() != eCSSUnit_Unset,
  6609. "unexpected unit");
  6610. ++aItemCount;
  6611. aLayers.EnsureLengthAtLeast(aItemCount);
  6612. ComputePositionCoordValue(aStyleContext, item->mValue,
  6613. aLayers[aItemCount-1].mPosition.*aResultLocation,
  6614. aConditions);
  6615. item = item->mNext;
  6616. } while (item);
  6617. break;
  6618. }
  6619. default:
  6620. MOZ_ASSERT(false, "unexpected unit");
  6621. }
  6622. if (aItemCount > aMaxItemCount) {
  6623. aMaxItemCount = aItemCount;
  6624. }
  6625. }
  6626. template <class ComputedValueItem>
  6627. static void
  6628. SetImageLayerPairList(nsStyleContext* aStyleContext,
  6629. const nsCSSValue& aValue,
  6630. nsStyleAutoArray<nsStyleImageLayers::Layer>& aLayers,
  6631. const nsStyleAutoArray<nsStyleImageLayers::Layer>& aParentLayers,
  6632. ComputedValueItem nsStyleImageLayers::Layer::*
  6633. aResultLocation,
  6634. ComputedValueItem aInitialValue,
  6635. uint32_t aParentItemCount,
  6636. uint32_t& aItemCount,
  6637. uint32_t& aMaxItemCount,
  6638. bool& aRebuild,
  6639. RuleNodeCacheConditions& aConditions)
  6640. {
  6641. switch (aValue.GetUnit()) {
  6642. case eCSSUnit_Null:
  6643. break;
  6644. case eCSSUnit_Inherit:
  6645. aRebuild = true;
  6646. aConditions.SetUncacheable();
  6647. aLayers.EnsureLengthAtLeast(aParentItemCount);
  6648. aItemCount = aParentItemCount;
  6649. for (uint32_t i = 0; i < aParentItemCount; ++i) {
  6650. aLayers[i].*aResultLocation = aParentLayers[i].*aResultLocation;
  6651. }
  6652. break;
  6653. case eCSSUnit_Initial:
  6654. case eCSSUnit_Unset:
  6655. aRebuild = true;
  6656. aItemCount = 1;
  6657. aLayers[0].*aResultLocation = aInitialValue;
  6658. break;
  6659. case eCSSUnit_PairList:
  6660. case eCSSUnit_PairListDep: {
  6661. aRebuild = true;
  6662. aItemCount = 0;
  6663. const nsCSSValuePairList* item = aValue.GetPairListValue();
  6664. do {
  6665. NS_ASSERTION(item->mXValue.GetUnit() != eCSSUnit_Inherit &&
  6666. item->mXValue.GetUnit() != eCSSUnit_Initial &&
  6667. item->mXValue.GetUnit() != eCSSUnit_Unset &&
  6668. item->mYValue.GetUnit() != eCSSUnit_Inherit &&
  6669. item->mYValue.GetUnit() != eCSSUnit_Initial &&
  6670. item->mYValue.GetUnit() != eCSSUnit_Unset,
  6671. "unexpected unit");
  6672. ++aItemCount;
  6673. aLayers.EnsureLengthAtLeast(aItemCount);
  6674. BackgroundItemComputer<nsCSSValuePairList, ComputedValueItem>
  6675. ::ComputeValue(aStyleContext, item,
  6676. aLayers[aItemCount-1].*aResultLocation,
  6677. aConditions);
  6678. item = item->mNext;
  6679. } while (item);
  6680. break;
  6681. }
  6682. default:
  6683. MOZ_ASSERT(false, "unexpected unit");
  6684. }
  6685. if (aItemCount > aMaxItemCount) {
  6686. aMaxItemCount = aItemCount;
  6687. }
  6688. }
  6689. template <class ComputedValueItem>
  6690. static void
  6691. FillImageLayerList(
  6692. nsStyleAutoArray<nsStyleImageLayers::Layer>& aLayers,
  6693. ComputedValueItem nsStyleImageLayers::Layer::* aResultLocation,
  6694. uint32_t aItemCount, uint32_t aFillCount)
  6695. {
  6696. NS_PRECONDITION(aFillCount <= aLayers.Length(), "unexpected array length");
  6697. for (uint32_t sourceLayer = 0, destLayer = aItemCount;
  6698. destLayer < aFillCount;
  6699. ++sourceLayer, ++destLayer) {
  6700. aLayers[destLayer].*aResultLocation =
  6701. aLayers[sourceLayer].*aResultLocation;
  6702. }
  6703. }
  6704. // The same as FillImageLayerList, but for values stored in
  6705. // layer.mPosition.*aResultLocation instead of layer.*aResultLocation.
  6706. static void
  6707. FillImageLayerPositionCoordList(
  6708. nsStyleAutoArray<nsStyleImageLayers::Layer>& aLayers,
  6709. Position::Coord
  6710. Position::* aResultLocation,
  6711. uint32_t aItemCount, uint32_t aFillCount)
  6712. {
  6713. NS_PRECONDITION(aFillCount <= aLayers.Length(), "unexpected array length");
  6714. for (uint32_t sourceLayer = 0, destLayer = aItemCount;
  6715. destLayer < aFillCount;
  6716. ++sourceLayer, ++destLayer) {
  6717. aLayers[destLayer].mPosition.*aResultLocation =
  6718. aLayers[sourceLayer].mPosition.*aResultLocation;
  6719. }
  6720. }
  6721. /* static */
  6722. void
  6723. nsRuleNode::FillAllBackgroundLists(nsStyleImageLayers& aImage,
  6724. uint32_t aMaxItemCount)
  6725. {
  6726. // Delete any extra items. We need to keep layers in which any
  6727. // property was specified.
  6728. aImage.mLayers.TruncateLengthNonZero(aMaxItemCount);
  6729. uint32_t fillCount = aImage.mImageCount;
  6730. FillImageLayerList(aImage.mLayers,
  6731. &nsStyleImageLayers::Layer::mImage,
  6732. aImage.mImageCount, fillCount);
  6733. FillImageLayerList(aImage.mLayers,
  6734. &nsStyleImageLayers::Layer::mRepeat,
  6735. aImage.mRepeatCount, fillCount);
  6736. FillImageLayerList(aImage.mLayers,
  6737. &nsStyleImageLayers::Layer::mAttachment,
  6738. aImage.mAttachmentCount, fillCount);
  6739. FillImageLayerList(aImage.mLayers,
  6740. &nsStyleImageLayers::Layer::mClip,
  6741. aImage.mClipCount, fillCount);
  6742. FillImageLayerList(aImage.mLayers,
  6743. &nsStyleImageLayers::Layer::mBlendMode,
  6744. aImage.mBlendModeCount, fillCount);
  6745. FillImageLayerList(aImage.mLayers,
  6746. &nsStyleImageLayers::Layer::mOrigin,
  6747. aImage.mOriginCount, fillCount);
  6748. FillImageLayerPositionCoordList(aImage.mLayers,
  6749. &Position::mXPosition,
  6750. aImage.mPositionXCount, fillCount);
  6751. FillImageLayerPositionCoordList(aImage.mLayers,
  6752. &Position::mYPosition,
  6753. aImage.mPositionYCount, fillCount);
  6754. FillImageLayerList(aImage.mLayers,
  6755. &nsStyleImageLayers::Layer::mSize,
  6756. aImage.mSizeCount, fillCount);
  6757. }
  6758. const void*
  6759. nsRuleNode::ComputeBackgroundData(void* aStartStruct,
  6760. const nsRuleData* aRuleData,
  6761. nsStyleContext* aContext,
  6762. nsRuleNode* aHighestNode,
  6763. const RuleDetail aRuleDetail,
  6764. const RuleNodeCacheConditions aConditions)
  6765. {
  6766. COMPUTE_START_RESET(Background, bg, parentBG)
  6767. // background-color: color, string, inherit
  6768. const nsCSSValue* backColorValue = aRuleData->ValueForBackgroundColor();
  6769. if (eCSSUnit_Initial == backColorValue->GetUnit() ||
  6770. eCSSUnit_Unset == backColorValue->GetUnit()) {
  6771. bg->mBackgroundColor = NS_RGBA(0, 0, 0, 0);
  6772. } else if (!SetColor(*backColorValue, parentBG->mBackgroundColor,
  6773. mPresContext, aContext, bg->mBackgroundColor,
  6774. conditions)) {
  6775. NS_ASSERTION(eCSSUnit_Null == backColorValue->GetUnit(),
  6776. "unexpected color unit");
  6777. }
  6778. uint32_t maxItemCount = 1;
  6779. bool rebuild = false;
  6780. // background-image: url (stored as image), none, inherit [list]
  6781. nsStyleImage initialImage;
  6782. SetImageLayerList(aContext, *aRuleData->ValueForBackgroundImage(),
  6783. bg->mImage.mLayers,
  6784. parentBG->mImage.mLayers,
  6785. &nsStyleImageLayers::Layer::mImage,
  6786. initialImage, parentBG->mImage.mImageCount,
  6787. bg->mImage.mImageCount,
  6788. maxItemCount, rebuild, conditions);
  6789. // background-repeat: enum, inherit, initial [pair list]
  6790. nsStyleImageLayers::Repeat initialRepeat;
  6791. initialRepeat.SetInitialValues();
  6792. SetImageLayerPairList(aContext, *aRuleData->ValueForBackgroundRepeat(),
  6793. bg->mImage.mLayers,
  6794. parentBG->mImage.mLayers,
  6795. &nsStyleImageLayers::Layer::mRepeat,
  6796. initialRepeat, parentBG->mImage.mRepeatCount,
  6797. bg->mImage.mRepeatCount, maxItemCount, rebuild,
  6798. conditions);
  6799. // background-attachment: enum, inherit, initial [list]
  6800. SetImageLayerList(aContext, *aRuleData->ValueForBackgroundAttachment(),
  6801. bg->mImage.mLayers, parentBG->mImage.mLayers,
  6802. &nsStyleImageLayers::Layer::mAttachment,
  6803. uint8_t(NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL),
  6804. parentBG->mImage.mAttachmentCount,
  6805. bg->mImage.mAttachmentCount, maxItemCount, rebuild,
  6806. conditions);
  6807. // background-clip: enum, inherit, initial [list]
  6808. SetImageLayerList(aContext, *aRuleData->ValueForBackgroundClip(),
  6809. bg->mImage.mLayers,
  6810. parentBG->mImage.mLayers,
  6811. &nsStyleImageLayers::Layer::mClip,
  6812. StyleGeometryBox::Border,
  6813. parentBG->mImage.mClipCount,
  6814. bg->mImage.mClipCount, maxItemCount, rebuild, conditions);
  6815. // background-blend-mode: enum, inherit, initial [list]
  6816. SetImageLayerList(aContext, *aRuleData->ValueForBackgroundBlendMode(),
  6817. bg->mImage.mLayers,
  6818. parentBG->mImage.mLayers,
  6819. &nsStyleImageLayers::Layer::mBlendMode,
  6820. uint8_t(NS_STYLE_BLEND_NORMAL),
  6821. parentBG->mImage.mBlendModeCount,
  6822. bg->mImage.mBlendModeCount, maxItemCount, rebuild,
  6823. conditions);
  6824. // background-origin: enum, inherit, initial [list]
  6825. SetImageLayerList(aContext, *aRuleData->ValueForBackgroundOrigin(),
  6826. bg->mImage.mLayers,
  6827. parentBG->mImage.mLayers,
  6828. &nsStyleImageLayers::Layer::mOrigin,
  6829. StyleGeometryBox::Padding,
  6830. parentBG->mImage.mOriginCount,
  6831. bg->mImage.mOriginCount, maxItemCount, rebuild,
  6832. conditions);
  6833. // background-position-x/y: enum, length, percent (flags), inherit [list]
  6834. Position::Coord initialPositionCoord;
  6835. initialPositionCoord.mPercent = 0.0f;
  6836. initialPositionCoord.mLength = 0;
  6837. initialPositionCoord.mHasPercent = true;
  6838. SetImageLayerPositionCoordList(
  6839. aContext, *aRuleData->ValueForBackgroundPositionX(),
  6840. bg->mImage.mLayers,
  6841. parentBG->mImage.mLayers,
  6842. &Position::mXPosition,
  6843. initialPositionCoord, parentBG->mImage.mPositionXCount,
  6844. bg->mImage.mPositionXCount, maxItemCount, rebuild,
  6845. conditions);
  6846. SetImageLayerPositionCoordList(
  6847. aContext, *aRuleData->ValueForBackgroundPositionY(),
  6848. bg->mImage.mLayers,
  6849. parentBG->mImage.mLayers,
  6850. &Position::mYPosition,
  6851. initialPositionCoord, parentBG->mImage.mPositionYCount,
  6852. bg->mImage.mPositionYCount, maxItemCount, rebuild,
  6853. conditions);
  6854. // background-size: enum, length, auto, inherit, initial [pair list]
  6855. nsStyleImageLayers::Size initialSize;
  6856. initialSize.SetInitialValues();
  6857. SetImageLayerPairList(aContext, *aRuleData->ValueForBackgroundSize(),
  6858. bg->mImage.mLayers,
  6859. parentBG->mImage.mLayers,
  6860. &nsStyleImageLayers::Layer::mSize,
  6861. initialSize, parentBG->mImage.mSizeCount,
  6862. bg->mImage.mSizeCount, maxItemCount, rebuild,
  6863. conditions);
  6864. if (rebuild) {
  6865. FillAllBackgroundLists(bg->mImage, maxItemCount);
  6866. }
  6867. COMPUTE_END_RESET(Background, bg)
  6868. }
  6869. const void*
  6870. nsRuleNode::ComputeMarginData(void* aStartStruct,
  6871. const nsRuleData* aRuleData,
  6872. nsStyleContext* aContext,
  6873. nsRuleNode* aHighestNode,
  6874. const RuleDetail aRuleDetail,
  6875. const RuleNodeCacheConditions aConditions)
  6876. {
  6877. COMPUTE_START_RESET(Margin, margin, parentMargin)
  6878. // margin: length, percent, calc, inherit
  6879. const nsCSSPropertyID* subprops =
  6880. nsCSSProps::SubpropertyEntryFor(eCSSProperty_margin);
  6881. nsStyleCoord coord;
  6882. NS_FOR_CSS_SIDES(side) {
  6883. nsStyleCoord parentCoord = parentMargin->mMargin.Get(side);
  6884. if (SetCoord(*aRuleData->ValueFor(subprops[side]),
  6885. coord, parentCoord,
  6886. SETCOORD_LPAH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC |
  6887. SETCOORD_UNSET_INITIAL,
  6888. aContext, mPresContext, conditions)) {
  6889. margin->mMargin.Set(side, coord);
  6890. }
  6891. }
  6892. COMPUTE_END_RESET(Margin, margin)
  6893. }
  6894. static void
  6895. SetBorderImageRect(const nsCSSValue& aValue,
  6896. /** outparam */ nsCSSRect& aRect)
  6897. {
  6898. switch (aValue.GetUnit()) {
  6899. case eCSSUnit_Null:
  6900. aRect.Reset();
  6901. break;
  6902. case eCSSUnit_Rect:
  6903. aRect = aValue.GetRectValue();
  6904. break;
  6905. case eCSSUnit_Inherit:
  6906. case eCSSUnit_Initial:
  6907. case eCSSUnit_Unset:
  6908. aRect.SetAllSidesTo(aValue);
  6909. break;
  6910. default:
  6911. NS_ASSERTION(false, "Unexpected border image value for rect.");
  6912. }
  6913. }
  6914. static void
  6915. SetBorderImagePair(const nsCSSValue& aValue,
  6916. /** outparam */ nsCSSValuePair& aPair)
  6917. {
  6918. switch (aValue.GetUnit()) {
  6919. case eCSSUnit_Null:
  6920. aPair.Reset();
  6921. break;
  6922. case eCSSUnit_Pair:
  6923. aPair = aValue.GetPairValue();
  6924. break;
  6925. case eCSSUnit_Inherit:
  6926. case eCSSUnit_Initial:
  6927. case eCSSUnit_Unset:
  6928. aPair.SetBothValuesTo(aValue);
  6929. break;
  6930. default:
  6931. NS_ASSERTION(false, "Unexpected border image value for pair.");
  6932. }
  6933. }
  6934. static void
  6935. SetBorderImageSlice(const nsCSSValue& aValue,
  6936. /** outparam */ nsCSSValue& aSlice,
  6937. /** outparam */ nsCSSValue& aFill)
  6938. {
  6939. const nsCSSValueList* valueList;
  6940. switch (aValue.GetUnit()) {
  6941. case eCSSUnit_Null:
  6942. aSlice.Reset();
  6943. aFill.Reset();
  6944. break;
  6945. case eCSSUnit_List:
  6946. // Get slice dimensions.
  6947. valueList = aValue.GetListValue();
  6948. aSlice = valueList->mValue;
  6949. // Get "fill" keyword.
  6950. valueList = valueList->mNext;
  6951. if (valueList) {
  6952. aFill = valueList->mValue;
  6953. } else {
  6954. aFill.SetInitialValue();
  6955. }
  6956. break;
  6957. case eCSSUnit_Inherit:
  6958. case eCSSUnit_Initial:
  6959. case eCSSUnit_Unset:
  6960. aSlice = aValue;
  6961. aFill = aValue;
  6962. break;
  6963. default:
  6964. NS_ASSERTION(false, "Unexpected border image value for pair.");
  6965. }
  6966. }
  6967. const void*
  6968. nsRuleNode::ComputeBorderData(void* aStartStruct,
  6969. const nsRuleData* aRuleData,
  6970. nsStyleContext* aContext,
  6971. nsRuleNode* aHighestNode,
  6972. const RuleDetail aRuleDetail,
  6973. const RuleNodeCacheConditions aConditions)
  6974. {
  6975. COMPUTE_START_RESET(Border, border, parentBorder)
  6976. // box-decoration-break: enum, inherit, initial
  6977. SetValue(*aRuleData->ValueForBoxDecorationBreak(),
  6978. border->mBoxDecorationBreak, conditions,
  6979. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  6980. parentBorder->mBoxDecorationBreak,
  6981. StyleBoxDecorationBreak::Slice);
  6982. // border-width, border-*-width: length, enum, inherit
  6983. nsStyleCoord coord;
  6984. {
  6985. const nsCSSPropertyID* subprops =
  6986. nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_width);
  6987. NS_FOR_CSS_SIDES(side) {
  6988. const nsCSSValue& value = *aRuleData->ValueFor(subprops[side]);
  6989. NS_ASSERTION(eCSSUnit_Percent != value.GetUnit(),
  6990. "Percentage borders not implemented yet "
  6991. "If implementing, make sure to fix all consumers of "
  6992. "nsStyleBorder, the IsPercentageAwareChild method, "
  6993. "the nsAbsoluteContainingBlock::FrameDependsOnContainer "
  6994. "method, the "
  6995. "nsLineLayout::IsPercentageAwareReplacedElement method "
  6996. "and probably some other places");
  6997. if (eCSSUnit_Enumerated == value.GetUnit()) {
  6998. NS_ASSERTION(value.GetIntValue() == NS_STYLE_BORDER_WIDTH_THIN ||
  6999. value.GetIntValue() == NS_STYLE_BORDER_WIDTH_MEDIUM ||
  7000. value.GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK,
  7001. "Unexpected enum value");
  7002. border->SetBorderWidth(side,
  7003. (mPresContext->GetBorderWidthTable())[value.GetIntValue()]);
  7004. // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
  7005. } else if (SetCoord(value, coord, nsStyleCoord(),
  7006. SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
  7007. aContext, mPresContext, conditions)) {
  7008. NS_ASSERTION(coord.GetUnit() == eStyleUnit_Coord, "unexpected unit");
  7009. // clamp negative calc() to 0.
  7010. border->SetBorderWidth(side, std::max(coord.GetCoordValue(), 0));
  7011. } else if (eCSSUnit_Inherit == value.GetUnit()) {
  7012. conditions.SetUncacheable();
  7013. border->SetBorderWidth(side,
  7014. parentBorder->GetComputedBorder().Side(side));
  7015. } else if (eCSSUnit_Initial == value.GetUnit() ||
  7016. eCSSUnit_Unset == value.GetUnit()) {
  7017. border->SetBorderWidth(side,
  7018. (mPresContext->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM]);
  7019. } else {
  7020. NS_ASSERTION(eCSSUnit_Null == value.GetUnit(),
  7021. "missing case handling border width");
  7022. }
  7023. }
  7024. }
  7025. // border-style, border-*-style: enum, inherit
  7026. {
  7027. const nsCSSPropertyID* subprops =
  7028. nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_style);
  7029. NS_FOR_CSS_SIDES(side) {
  7030. const nsCSSValue& value = *aRuleData->ValueFor(subprops[side]);
  7031. nsCSSUnit unit = value.GetUnit();
  7032. MOZ_ASSERT(eCSSUnit_None != unit,
  7033. "'none' should be handled as enumerated value");
  7034. if (eCSSUnit_Enumerated == unit) {
  7035. border->SetBorderStyle(side, value.GetIntValue());
  7036. } else if (eCSSUnit_Initial == unit ||
  7037. eCSSUnit_Unset == unit) {
  7038. border->SetBorderStyle(side, NS_STYLE_BORDER_STYLE_NONE);
  7039. } else if (eCSSUnit_Inherit == unit) {
  7040. conditions.SetUncacheable();
  7041. border->SetBorderStyle(side, parentBorder->GetBorderStyle(side));
  7042. }
  7043. }
  7044. }
  7045. // -moz-border-*-colors: color, string, enum, none, inherit/initial
  7046. nscolor borderColor;
  7047. nscolor unused = NS_RGB(0,0,0);
  7048. static const nsCSSPropertyID borderColorsProps[] = {
  7049. eCSSProperty_border_top_colors,
  7050. eCSSProperty_border_right_colors,
  7051. eCSSProperty_border_bottom_colors,
  7052. eCSSProperty_border_left_colors
  7053. };
  7054. NS_FOR_CSS_SIDES(side) {
  7055. const nsCSSValue& value = *aRuleData->ValueFor(borderColorsProps[side]);
  7056. switch (value.GetUnit()) {
  7057. case eCSSUnit_Null:
  7058. break;
  7059. case eCSSUnit_Initial:
  7060. case eCSSUnit_Unset:
  7061. case eCSSUnit_None:
  7062. border->ClearBorderColors(side);
  7063. break;
  7064. case eCSSUnit_Inherit: {
  7065. conditions.SetUncacheable();
  7066. border->ClearBorderColors(side);
  7067. if (parentContext) {
  7068. nsBorderColors *parentColors;
  7069. parentBorder->GetCompositeColors(side, &parentColors);
  7070. if (parentColors) {
  7071. border->EnsureBorderColors();
  7072. border->mBorderColors[side] = parentColors->Clone();
  7073. }
  7074. }
  7075. break;
  7076. }
  7077. case eCSSUnit_List:
  7078. case eCSSUnit_ListDep: {
  7079. // Some composite border color information has been specified for this
  7080. // border side.
  7081. border->EnsureBorderColors();
  7082. border->ClearBorderColors(side);
  7083. const nsCSSValueList* list = value.GetListValue();
  7084. while (list) {
  7085. if (SetColor(list->mValue, unused, mPresContext,
  7086. aContext, borderColor, conditions)) {
  7087. border->AppendBorderColor(side, borderColor);
  7088. } else {
  7089. NS_NOTREACHED("unexpected item in -moz-border-*-colors list");
  7090. }
  7091. list = list->mNext;
  7092. }
  7093. break;
  7094. }
  7095. default:
  7096. MOZ_ASSERT(false, "unrecognized border color unit");
  7097. }
  7098. }
  7099. // border-color, border-*-color: color, string, enum, inherit
  7100. {
  7101. const nsCSSPropertyID* subprops =
  7102. nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_color);
  7103. NS_FOR_CSS_SIDES(side) {
  7104. SetComplexColor<eUnsetInitial>(*aRuleData->ValueFor(subprops[side]),
  7105. parentBorder->mBorderColor[side],
  7106. StyleComplexColor::CurrentColor(),
  7107. mPresContext,
  7108. border->mBorderColor[side], conditions);
  7109. }
  7110. }
  7111. // border-radius: length, percent, inherit
  7112. {
  7113. const nsCSSPropertyID* subprops =
  7114. nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_radius);
  7115. NS_FOR_CSS_FULL_CORNERS(corner) {
  7116. int cx = NS_FULL_TO_HALF_CORNER(corner, false);
  7117. int cy = NS_FULL_TO_HALF_CORNER(corner, true);
  7118. const nsCSSValue& radius = *aRuleData->ValueFor(subprops[corner]);
  7119. nsStyleCoord parentX = parentBorder->mBorderRadius.Get(cx);
  7120. nsStyleCoord parentY = parentBorder->mBorderRadius.Get(cy);
  7121. nsStyleCoord coordX, coordY;
  7122. if (SetPairCoords(radius, coordX, coordY, parentX, parentY,
  7123. SETCOORD_LPH | SETCOORD_INITIAL_ZERO |
  7124. SETCOORD_STORE_CALC | SETCOORD_UNSET_INITIAL,
  7125. aContext, mPresContext, conditions)) {
  7126. border->mBorderRadius.Set(cx, coordX);
  7127. border->mBorderRadius.Set(cy, coordY);
  7128. }
  7129. }
  7130. }
  7131. // float-edge: enum, inherit, initial
  7132. SetValue(*aRuleData->ValueForFloatEdge(),
  7133. border->mFloatEdge, conditions,
  7134. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  7135. parentBorder->mFloatEdge,
  7136. StyleFloatEdge::ContentBox);
  7137. // border-image-source
  7138. const nsCSSValue* borderImageSource = aRuleData->ValueForBorderImageSource();
  7139. if (borderImageSource->GetUnit() == eCSSUnit_Inherit) {
  7140. conditions.SetUncacheable();
  7141. border->mBorderImageSource = parentBorder->mBorderImageSource;
  7142. } else {
  7143. SetStyleImage(aContext,
  7144. *borderImageSource,
  7145. border->mBorderImageSource,
  7146. conditions);
  7147. }
  7148. nsCSSValue borderImageSliceValue;
  7149. nsCSSValue borderImageSliceFill;
  7150. SetBorderImageSlice(*aRuleData->ValueForBorderImageSlice(),
  7151. borderImageSliceValue, borderImageSliceFill);
  7152. // border-image-slice: fill
  7153. SetValue(borderImageSliceFill,
  7154. border->mBorderImageFill,
  7155. conditions,
  7156. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  7157. parentBorder->mBorderImageFill,
  7158. NS_STYLE_BORDER_IMAGE_SLICE_NOFILL);
  7159. nsCSSRect borderImageSlice;
  7160. SetBorderImageRect(borderImageSliceValue, borderImageSlice);
  7161. nsCSSRect borderImageWidth;
  7162. SetBorderImageRect(*aRuleData->ValueForBorderImageWidth(),
  7163. borderImageWidth);
  7164. nsCSSRect borderImageOutset;
  7165. SetBorderImageRect(*aRuleData->ValueForBorderImageOutset(),
  7166. borderImageOutset);
  7167. NS_FOR_CSS_SIDES (side) {
  7168. // border-image-slice
  7169. if (SetCoord(borderImageSlice.*(nsCSSRect::sides[side]), coord,
  7170. parentBorder->mBorderImageSlice.Get(side),
  7171. SETCOORD_FACTOR | SETCOORD_PERCENT |
  7172. SETCOORD_INHERIT | SETCOORD_INITIAL_HUNDRED_PCT |
  7173. SETCOORD_UNSET_INITIAL,
  7174. aContext, mPresContext, conditions)) {
  7175. border->mBorderImageSlice.Set(side, coord);
  7176. }
  7177. // border-image-width
  7178. // 'auto' here means "same as slice"
  7179. if (SetCoord(borderImageWidth.*(nsCSSRect::sides[side]), coord,
  7180. parentBorder->mBorderImageWidth.Get(side),
  7181. SETCOORD_LPAH | SETCOORD_FACTOR | SETCOORD_INITIAL_FACTOR_ONE |
  7182. SETCOORD_UNSET_INITIAL,
  7183. aContext, mPresContext, conditions)) {
  7184. border->mBorderImageWidth.Set(side, coord);
  7185. }
  7186. // border-image-outset
  7187. if (SetCoord(borderImageOutset.*(nsCSSRect::sides[side]), coord,
  7188. parentBorder->mBorderImageOutset.Get(side),
  7189. SETCOORD_LENGTH | SETCOORD_FACTOR |
  7190. SETCOORD_INHERIT | SETCOORD_INITIAL_FACTOR_ZERO |
  7191. SETCOORD_UNSET_INITIAL,
  7192. aContext, mPresContext, conditions)) {
  7193. border->mBorderImageOutset.Set(side, coord);
  7194. }
  7195. }
  7196. // border-image-repeat
  7197. nsCSSValuePair borderImageRepeat;
  7198. SetBorderImagePair(*aRuleData->ValueForBorderImageRepeat(),
  7199. borderImageRepeat);
  7200. SetValue(borderImageRepeat.mXValue,
  7201. border->mBorderImageRepeatH,
  7202. conditions,
  7203. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  7204. parentBorder->mBorderImageRepeatH,
  7205. NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH);
  7206. SetValue(borderImageRepeat.mYValue,
  7207. border->mBorderImageRepeatV,
  7208. conditions,
  7209. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  7210. parentBorder->mBorderImageRepeatV,
  7211. NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH);
  7212. COMPUTE_END_RESET(Border, border)
  7213. }
  7214. const void*
  7215. nsRuleNode::ComputePaddingData(void* aStartStruct,
  7216. const nsRuleData* aRuleData,
  7217. nsStyleContext* aContext,
  7218. nsRuleNode* aHighestNode,
  7219. const RuleDetail aRuleDetail,
  7220. const RuleNodeCacheConditions aConditions)
  7221. {
  7222. COMPUTE_START_RESET(Padding, padding, parentPadding)
  7223. // padding: length, percent, calc, inherit
  7224. const nsCSSPropertyID* subprops =
  7225. nsCSSProps::SubpropertyEntryFor(eCSSProperty_padding);
  7226. nsStyleCoord coord;
  7227. NS_FOR_CSS_SIDES(side) {
  7228. nsStyleCoord parentCoord = parentPadding->mPadding.Get(side);
  7229. if (SetCoord(*aRuleData->ValueFor(subprops[side]),
  7230. coord, parentCoord,
  7231. SETCOORD_LPH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC |
  7232. SETCOORD_UNSET_INITIAL,
  7233. aContext, mPresContext, conditions)) {
  7234. padding->mPadding.Set(side, coord);
  7235. }
  7236. }
  7237. COMPUTE_END_RESET(Padding, padding)
  7238. }
  7239. const void*
  7240. nsRuleNode::ComputeOutlineData(void* aStartStruct,
  7241. const nsRuleData* aRuleData,
  7242. nsStyleContext* aContext,
  7243. nsRuleNode* aHighestNode,
  7244. const RuleDetail aRuleDetail,
  7245. const RuleNodeCacheConditions aConditions)
  7246. {
  7247. COMPUTE_START_RESET(Outline, outline, parentOutline)
  7248. // outline-width: length, enum, inherit
  7249. const nsCSSValue* outlineWidthValue = aRuleData->ValueForOutlineWidth();
  7250. if (eCSSUnit_Initial == outlineWidthValue->GetUnit() ||
  7251. eCSSUnit_Unset == outlineWidthValue->GetUnit()) {
  7252. outline->mOutlineWidth =
  7253. nsStyleCoord(NS_STYLE_BORDER_WIDTH_MEDIUM, eStyleUnit_Enumerated);
  7254. } else {
  7255. SetCoord(*outlineWidthValue, outline->mOutlineWidth,
  7256. parentOutline->mOutlineWidth,
  7257. SETCOORD_LEH | SETCOORD_CALC_LENGTH_ONLY, aContext,
  7258. mPresContext, conditions);
  7259. }
  7260. // outline-offset: length, inherit
  7261. nsStyleCoord tempCoord;
  7262. const nsCSSValue* outlineOffsetValue = aRuleData->ValueForOutlineOffset();
  7263. if (SetCoord(*outlineOffsetValue, tempCoord,
  7264. nsStyleCoord(parentOutline->mOutlineOffset,
  7265. nsStyleCoord::CoordConstructor),
  7266. SETCOORD_LH | SETCOORD_INITIAL_ZERO | SETCOORD_CALC_LENGTH_ONLY |
  7267. SETCOORD_UNSET_INITIAL,
  7268. aContext, mPresContext, conditions)) {
  7269. outline->mOutlineOffset = tempCoord.GetCoordValue();
  7270. } else {
  7271. NS_ASSERTION(outlineOffsetValue->GetUnit() == eCSSUnit_Null,
  7272. "unexpected unit");
  7273. }
  7274. // outline-color: color, string, enum, inherit
  7275. SetComplexColor<eUnsetInitial>(*aRuleData->ValueForOutlineColor(),
  7276. parentOutline->mOutlineColor,
  7277. StyleComplexColor::CurrentColor(),
  7278. mPresContext,
  7279. outline->mOutlineColor, conditions);
  7280. // -moz-outline-radius: length, percent, inherit
  7281. {
  7282. const nsCSSPropertyID* subprops =
  7283. nsCSSProps::SubpropertyEntryFor(eCSSProperty__moz_outline_radius);
  7284. NS_FOR_CSS_FULL_CORNERS(corner) {
  7285. int cx = NS_FULL_TO_HALF_CORNER(corner, false);
  7286. int cy = NS_FULL_TO_HALF_CORNER(corner, true);
  7287. const nsCSSValue& radius = *aRuleData->ValueFor(subprops[corner]);
  7288. nsStyleCoord parentX = parentOutline->mOutlineRadius.Get(cx);
  7289. nsStyleCoord parentY = parentOutline->mOutlineRadius.Get(cy);
  7290. nsStyleCoord coordX, coordY;
  7291. if (SetPairCoords(radius, coordX, coordY, parentX, parentY,
  7292. SETCOORD_LPH | SETCOORD_INITIAL_ZERO |
  7293. SETCOORD_STORE_CALC | SETCOORD_UNSET_INITIAL,
  7294. aContext, mPresContext, conditions)) {
  7295. outline->mOutlineRadius.Set(cx, coordX);
  7296. outline->mOutlineRadius.Set(cy, coordY);
  7297. }
  7298. }
  7299. }
  7300. // outline-style: enum, inherit, initial
  7301. // cannot use SetValue because of SetOutlineStyle
  7302. const nsCSSValue* outlineStyleValue = aRuleData->ValueForOutlineStyle();
  7303. nsCSSUnit unit = outlineStyleValue->GetUnit();
  7304. MOZ_ASSERT(eCSSUnit_None != unit && eCSSUnit_Auto != unit,
  7305. "'none' and 'auto' should be handled as enumerated values");
  7306. if (eCSSUnit_Enumerated == unit) {
  7307. outline->mOutlineStyle = outlineStyleValue->GetIntValue();
  7308. } else if (eCSSUnit_Initial == unit ||
  7309. eCSSUnit_Unset == unit) {
  7310. outline->mOutlineStyle = NS_STYLE_BORDER_STYLE_NONE;
  7311. } else if (eCSSUnit_Inherit == unit) {
  7312. conditions.SetUncacheable();
  7313. outline->mOutlineStyle = parentOutline->mOutlineStyle;
  7314. }
  7315. outline->RecalcData();
  7316. COMPUTE_END_RESET(Outline, outline)
  7317. }
  7318. const void*
  7319. nsRuleNode::ComputeListData(void* aStartStruct,
  7320. const nsRuleData* aRuleData,
  7321. nsStyleContext* aContext,
  7322. nsRuleNode* aHighestNode,
  7323. const RuleDetail aRuleDetail,
  7324. const RuleNodeCacheConditions aConditions)
  7325. {
  7326. COMPUTE_START_INHERITED(List, list, parentList)
  7327. // quotes: inherit, initial, none, [string string]+
  7328. const nsCSSValue* quotesValue = aRuleData->ValueForQuotes();
  7329. switch (quotesValue->GetUnit()) {
  7330. case eCSSUnit_Null:
  7331. break;
  7332. case eCSSUnit_Inherit:
  7333. case eCSSUnit_Unset:
  7334. conditions.SetUncacheable();
  7335. list->SetQuotesInherit(parentList);
  7336. break;
  7337. case eCSSUnit_Initial:
  7338. list->SetQuotesInitial();
  7339. break;
  7340. case eCSSUnit_None:
  7341. list->SetQuotesNone();
  7342. break;
  7343. case eCSSUnit_PairList:
  7344. case eCSSUnit_PairListDep: {
  7345. const nsCSSValuePairList* ourQuotes = quotesValue->GetPairListValue();
  7346. nsStyleQuoteValues::QuotePairArray quotePairs;
  7347. quotePairs.SetLength(ListLength(ourQuotes));
  7348. size_t index = 0;
  7349. nsAutoString buffer;
  7350. while (ourQuotes) {
  7351. MOZ_ASSERT(ourQuotes->mXValue.GetUnit() == eCSSUnit_String &&
  7352. ourQuotes->mYValue.GetUnit() == eCSSUnit_String,
  7353. "improper list contents for quotes");
  7354. quotePairs[index].first = ourQuotes->mXValue.GetStringValue(buffer);
  7355. quotePairs[index].second = ourQuotes->mYValue.GetStringValue(buffer);
  7356. ++index;
  7357. ourQuotes = ourQuotes->mNext;
  7358. }
  7359. list->SetQuotes(Move(quotePairs));
  7360. break;
  7361. }
  7362. default:
  7363. MOZ_ASSERT(false, "unexpected value unit");
  7364. }
  7365. // list-style-type: string, none, inherit, initial
  7366. const nsCSSValue* typeValue = aRuleData->ValueForListStyleType();
  7367. switch (typeValue->GetUnit()) {
  7368. case eCSSUnit_Unset:
  7369. case eCSSUnit_Inherit: {
  7370. conditions.SetUncacheable();
  7371. list->SetCounterStyle(parentList->GetCounterStyle());
  7372. break;
  7373. }
  7374. case eCSSUnit_Initial:
  7375. list->SetListStyleType(NS_LITERAL_STRING("disc"), mPresContext);
  7376. break;
  7377. case eCSSUnit_Ident: {
  7378. nsString typeIdent;
  7379. typeValue->GetStringValue(typeIdent);
  7380. list->SetListStyleType(typeIdent, mPresContext);
  7381. break;
  7382. }
  7383. case eCSSUnit_String: {
  7384. nsString str;
  7385. typeValue->GetStringValue(str);
  7386. list->SetCounterStyle(new AnonymousCounterStyle(str));
  7387. break;
  7388. }
  7389. case eCSSUnit_Enumerated: {
  7390. // For compatibility with html attribute map.
  7391. // This branch should never be called for value from CSS.
  7392. int32_t intValue = typeValue->GetIntValue();
  7393. nsAutoString name;
  7394. switch (intValue) {
  7395. case NS_STYLE_LIST_STYLE_LOWER_ROMAN:
  7396. name.AssignLiteral(u"lower-roman");
  7397. break;
  7398. case NS_STYLE_LIST_STYLE_UPPER_ROMAN:
  7399. name.AssignLiteral(u"upper-roman");
  7400. break;
  7401. case NS_STYLE_LIST_STYLE_LOWER_ALPHA:
  7402. name.AssignLiteral(u"lower-alpha");
  7403. break;
  7404. case NS_STYLE_LIST_STYLE_UPPER_ALPHA:
  7405. name.AssignLiteral(u"upper-alpha");
  7406. break;
  7407. default:
  7408. CopyASCIItoUTF16(nsCSSProps::ValueToKeyword(
  7409. intValue, nsCSSProps::kListStyleKTable), name);
  7410. break;
  7411. }
  7412. list->SetListStyleType(name, mPresContext);
  7413. break;
  7414. }
  7415. case eCSSUnit_Symbols:
  7416. list->SetCounterStyle(new AnonymousCounterStyle(typeValue->GetArrayValue()));
  7417. break;
  7418. case eCSSUnit_Null:
  7419. break;
  7420. default:
  7421. NS_NOTREACHED("Unexpected value unit");
  7422. }
  7423. // list-style-image: url, none, inherit
  7424. const nsCSSValue* imageValue = aRuleData->ValueForListStyleImage();
  7425. if (eCSSUnit_Image == imageValue->GetUnit()) {
  7426. SetStyleImageRequest([&](nsStyleImageRequest* req) {
  7427. list->mListStyleImage = req;
  7428. }, mPresContext, *imageValue, nsStyleImageRequest::Mode(0));
  7429. } else if (eCSSUnit_None == imageValue->GetUnit() ||
  7430. eCSSUnit_Initial == imageValue->GetUnit()) {
  7431. list->mListStyleImage = nullptr;
  7432. } else if (eCSSUnit_Inherit == imageValue->GetUnit() ||
  7433. eCSSUnit_Unset == imageValue->GetUnit()) {
  7434. conditions.SetUncacheable();
  7435. list->mListStyleImage = parentList->mListStyleImage;
  7436. }
  7437. // list-style-position: enum, inherit, initial
  7438. SetValue(*aRuleData->ValueForListStylePosition(),
  7439. list->mListStylePosition, conditions,
  7440. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  7441. parentList->mListStylePosition,
  7442. NS_STYLE_LIST_STYLE_POSITION_OUTSIDE);
  7443. // image region property: length, auto, inherit
  7444. const nsCSSValue* imageRegionValue = aRuleData->ValueForImageRegion();
  7445. switch (imageRegionValue->GetUnit()) {
  7446. case eCSSUnit_Inherit:
  7447. case eCSSUnit_Unset:
  7448. conditions.SetUncacheable();
  7449. list->mImageRegion = parentList->mImageRegion;
  7450. break;
  7451. case eCSSUnit_Initial:
  7452. case eCSSUnit_Auto:
  7453. list->mImageRegion.SetRect(0,0,0,0);
  7454. break;
  7455. case eCSSUnit_Null:
  7456. break;
  7457. case eCSSUnit_Rect: {
  7458. const nsCSSRect& rgnRect = imageRegionValue->GetRectValue();
  7459. if (rgnRect.mTop.GetUnit() == eCSSUnit_Auto) {
  7460. list->mImageRegion.y = 0;
  7461. } else if (rgnRect.mTop.IsLengthUnit()) {
  7462. list->mImageRegion.y =
  7463. CalcLength(rgnRect.mTop, aContext, mPresContext, conditions);
  7464. }
  7465. if (rgnRect.mBottom.GetUnit() == eCSSUnit_Auto) {
  7466. list->mImageRegion.height = 0;
  7467. } else if (rgnRect.mBottom.IsLengthUnit()) {
  7468. list->mImageRegion.height =
  7469. CalcLength(rgnRect.mBottom, aContext, mPresContext,
  7470. conditions) - list->mImageRegion.y;
  7471. }
  7472. if (rgnRect.mLeft.GetUnit() == eCSSUnit_Auto) {
  7473. list->mImageRegion.x = 0;
  7474. } else if (rgnRect.mLeft.IsLengthUnit()) {
  7475. list->mImageRegion.x =
  7476. CalcLength(rgnRect.mLeft, aContext, mPresContext, conditions);
  7477. }
  7478. if (rgnRect.mRight.GetUnit() == eCSSUnit_Auto) {
  7479. list->mImageRegion.width = 0;
  7480. } else if (rgnRect.mRight.IsLengthUnit()) {
  7481. list->mImageRegion.width =
  7482. CalcLength(rgnRect.mRight, aContext, mPresContext,
  7483. conditions) - list->mImageRegion.x;
  7484. }
  7485. break;
  7486. }
  7487. default:
  7488. MOZ_ASSERT(false, "unrecognized image-region unit");
  7489. }
  7490. COMPUTE_END_INHERITED(List, list)
  7491. }
  7492. static void
  7493. SetGridTrackBreadth(const nsCSSValue& aValue,
  7494. nsStyleCoord& aResult,
  7495. nsStyleContext* aStyleContext,
  7496. nsPresContext* aPresContext,
  7497. RuleNodeCacheConditions& aConditions)
  7498. {
  7499. nsCSSUnit unit = aValue.GetUnit();
  7500. if (unit == eCSSUnit_FlexFraction) {
  7501. aResult.SetFlexFractionValue(aValue.GetFloatValue());
  7502. } else if (unit == eCSSUnit_Auto) {
  7503. aResult.SetAutoValue();
  7504. } else if (unit == eCSSUnit_None) {
  7505. // For fit-content().
  7506. aResult.SetNoneValue();
  7507. } else {
  7508. MOZ_ASSERT(unit != eCSSUnit_Inherit && unit != eCSSUnit_Unset,
  7509. "Unexpected value that would use dummyParentCoord");
  7510. const nsStyleCoord dummyParentCoord;
  7511. DebugOnly<bool> stored =
  7512. SetCoord(aValue, aResult, dummyParentCoord,
  7513. SETCOORD_LPE | SETCOORD_STORE_CALC,
  7514. aStyleContext, aPresContext, aConditions);
  7515. MOZ_ASSERT(stored, "invalid <track-size> value");
  7516. }
  7517. }
  7518. static void
  7519. SetGridTrackSize(const nsCSSValue& aValue,
  7520. nsStyleCoord& aResultMin,
  7521. nsStyleCoord& aResultMax,
  7522. nsStyleContext* aStyleContext,
  7523. nsPresContext* aPresContext,
  7524. RuleNodeCacheConditions& aConditions)
  7525. {
  7526. if (aValue.GetUnit() == eCSSUnit_Function) {
  7527. nsCSSValue::Array* func = aValue.GetArrayValue();
  7528. auto funcName = func->Item(0).GetKeywordValue();
  7529. if (funcName == eCSSKeyword_minmax) {
  7530. SetGridTrackBreadth(func->Item(1), aResultMin,
  7531. aStyleContext, aPresContext, aConditions);
  7532. SetGridTrackBreadth(func->Item(2), aResultMax,
  7533. aStyleContext, aPresContext, aConditions);
  7534. } else if (funcName == eCSSKeyword_fit_content) {
  7535. // We represent fit-content(L) as 'none' min-sizing and L max-sizing.
  7536. SetGridTrackBreadth(nsCSSValue(eCSSUnit_None), aResultMin,
  7537. aStyleContext, aPresContext, aConditions);
  7538. SetGridTrackBreadth(func->Item(1), aResultMax,
  7539. aStyleContext, aPresContext, aConditions);
  7540. } else {
  7541. NS_ERROR("Expected minmax() or fit-content(), got another function name");
  7542. }
  7543. } else {
  7544. // A single <track-breadth>,
  7545. // specifies identical min and max sizing functions.
  7546. SetGridTrackBreadth(aValue, aResultMin,
  7547. aStyleContext, aPresContext, aConditions);
  7548. aResultMax = aResultMin;
  7549. }
  7550. }
  7551. static void
  7552. SetGridAutoColumnsRows(const nsCSSValue& aValue,
  7553. nsStyleCoord& aResultMin,
  7554. nsStyleCoord& aResultMax,
  7555. const nsStyleCoord& aParentValueMin,
  7556. const nsStyleCoord& aParentValueMax,
  7557. nsStyleContext* aStyleContext,
  7558. nsPresContext* aPresContext,
  7559. RuleNodeCacheConditions& aConditions)
  7560. {
  7561. switch (aValue.GetUnit()) {
  7562. case eCSSUnit_Null:
  7563. break;
  7564. case eCSSUnit_Inherit:
  7565. aConditions.SetUncacheable();
  7566. aResultMin = aParentValueMin;
  7567. aResultMax = aParentValueMax;
  7568. break;
  7569. case eCSSUnit_Initial:
  7570. case eCSSUnit_Unset:
  7571. // The initial value is 'auto',
  7572. // which computes to 'minmax(auto, auto)'.
  7573. // (Explicitly-specified 'auto' values are handled in SetGridTrackSize.)
  7574. aResultMin.SetAutoValue();
  7575. aResultMax.SetAutoValue();
  7576. break;
  7577. default:
  7578. SetGridTrackSize(aValue, aResultMin, aResultMax,
  7579. aStyleContext, aPresContext, aConditions);
  7580. }
  7581. }
  7582. static void
  7583. AppendGridLineNames(const nsCSSValue& aValue,
  7584. nsTArray<nsString>& aNameList)
  7585. {
  7586. // Compute a <line-names> value
  7587. // Null unit means empty list, nothing more to do.
  7588. if (aValue.GetUnit() != eCSSUnit_Null) {
  7589. const nsCSSValueList* item = aValue.GetListValue();
  7590. do {
  7591. nsString* name = aNameList.AppendElement();
  7592. item->mValue.GetStringValue(*name);
  7593. item = item->mNext;
  7594. } while (item);
  7595. }
  7596. }
  7597. static void
  7598. SetGridTrackList(const nsCSSValue& aValue,
  7599. nsStyleGridTemplate& aResult,
  7600. const nsStyleGridTemplate& aParentValue,
  7601. nsStyleContext* aStyleContext,
  7602. nsPresContext* aPresContext,
  7603. RuleNodeCacheConditions& aConditions)
  7604. {
  7605. switch (aValue.GetUnit()) {
  7606. case eCSSUnit_Null:
  7607. break;
  7608. case eCSSUnit_Inherit:
  7609. aConditions.SetUncacheable();
  7610. aResult.mIsSubgrid = aParentValue.mIsSubgrid;
  7611. aResult.mLineNameLists = aParentValue.mLineNameLists;
  7612. aResult.mMinTrackSizingFunctions = aParentValue.mMinTrackSizingFunctions;
  7613. aResult.mMaxTrackSizingFunctions = aParentValue.mMaxTrackSizingFunctions;
  7614. aResult.mRepeatAutoLineNameListBefore = aParentValue.mRepeatAutoLineNameListBefore;
  7615. aResult.mRepeatAutoLineNameListAfter = aParentValue.mRepeatAutoLineNameListAfter;
  7616. aResult.mRepeatAutoIndex = aParentValue.mRepeatAutoIndex;
  7617. aResult.mIsAutoFill = aParentValue.mIsAutoFill;
  7618. break;
  7619. case eCSSUnit_Initial:
  7620. case eCSSUnit_Unset:
  7621. case eCSSUnit_None:
  7622. aResult.mIsSubgrid = false;
  7623. aResult.mLineNameLists.Clear();
  7624. aResult.mMinTrackSizingFunctions.Clear();
  7625. aResult.mMaxTrackSizingFunctions.Clear();
  7626. aResult.mRepeatAutoLineNameListBefore.Clear();
  7627. aResult.mRepeatAutoLineNameListAfter.Clear();
  7628. aResult.mRepeatAutoIndex = -1;
  7629. aResult.mIsAutoFill = false;
  7630. break;
  7631. default:
  7632. aResult.mLineNameLists.Clear();
  7633. aResult.mMinTrackSizingFunctions.Clear();
  7634. aResult.mMaxTrackSizingFunctions.Clear();
  7635. aResult.mRepeatAutoLineNameListBefore.Clear();
  7636. aResult.mRepeatAutoLineNameListAfter.Clear();
  7637. aResult.mRepeatAutoIndex = -1;
  7638. aResult.mIsAutoFill = false;
  7639. const nsCSSValueList* item = aValue.GetListValue();
  7640. if (item->mValue.GetUnit() == eCSSUnit_Enumerated &&
  7641. item->mValue.GetIntValue() == NS_STYLE_GRID_TEMPLATE_SUBGRID) {
  7642. // subgrid <line-name-list>?
  7643. aResult.mIsSubgrid = true;
  7644. item = item->mNext;
  7645. for (int32_t i = 0; item && i < nsStyleGridLine::kMaxLine; ++i) {
  7646. if (item->mValue.GetUnit() == eCSSUnit_Pair) {
  7647. // This is a 'auto-fill' <name-repeat> expression.
  7648. const nsCSSValuePair& pair = item->mValue.GetPairValue();
  7649. MOZ_ASSERT(aResult.mRepeatAutoIndex == -1,
  7650. "can only have one <name-repeat> with auto-fill");
  7651. aResult.mRepeatAutoIndex = i;
  7652. aResult.mIsAutoFill = true;
  7653. MOZ_ASSERT(pair.mXValue.GetIntValue() == NS_STYLE_GRID_REPEAT_AUTO_FILL,
  7654. "unexpected repeat() enum value for subgrid");
  7655. const nsCSSValueList* list = pair.mYValue.GetListValue();
  7656. AppendGridLineNames(list->mValue, aResult.mRepeatAutoLineNameListBefore);
  7657. } else {
  7658. AppendGridLineNames(item->mValue,
  7659. *aResult.mLineNameLists.AppendElement());
  7660. }
  7661. item = item->mNext;
  7662. }
  7663. } else {
  7664. // <track-list>
  7665. // The list is expected to have odd number of items, at least 3
  7666. // starting with a <line-names> (sub list of identifiers),
  7667. // and alternating between that and <track-size>.
  7668. aResult.mIsSubgrid = false;
  7669. for (int32_t line = 1; ; ++line) {
  7670. AppendGridLineNames(item->mValue,
  7671. *aResult.mLineNameLists.AppendElement());
  7672. item = item->mNext;
  7673. if (!item || line == nsStyleGridLine::kMaxLine) {
  7674. break;
  7675. }
  7676. if (item->mValue.GetUnit() == eCSSUnit_Pair) {
  7677. // This is a 'auto-fill' / 'auto-fit' <auto-repeat> expression.
  7678. const nsCSSValuePair& pair = item->mValue.GetPairValue();
  7679. MOZ_ASSERT(aResult.mRepeatAutoIndex == -1,
  7680. "can only have one <auto-repeat>");
  7681. aResult.mRepeatAutoIndex = line - 1;
  7682. switch (pair.mXValue.GetIntValue()) {
  7683. case NS_STYLE_GRID_REPEAT_AUTO_FILL:
  7684. aResult.mIsAutoFill = true;
  7685. break;
  7686. case NS_STYLE_GRID_REPEAT_AUTO_FIT:
  7687. aResult.mIsAutoFill = false;
  7688. break;
  7689. default:
  7690. MOZ_ASSERT_UNREACHABLE("unexpected repeat() enum value");
  7691. }
  7692. const nsCSSValueList* list = pair.mYValue.GetListValue();
  7693. AppendGridLineNames(list->mValue, aResult.mRepeatAutoLineNameListBefore);
  7694. list = list->mNext;
  7695. nsStyleCoord& min = *aResult.mMinTrackSizingFunctions.AppendElement();
  7696. nsStyleCoord& max = *aResult.mMaxTrackSizingFunctions.AppendElement();
  7697. SetGridTrackSize(list->mValue, min, max,
  7698. aStyleContext, aPresContext, aConditions);
  7699. list = list->mNext;
  7700. AppendGridLineNames(list->mValue, aResult.mRepeatAutoLineNameListAfter);
  7701. } else {
  7702. nsStyleCoord& min = *aResult.mMinTrackSizingFunctions.AppendElement();
  7703. nsStyleCoord& max = *aResult.mMaxTrackSizingFunctions.AppendElement();
  7704. SetGridTrackSize(item->mValue, min, max,
  7705. aStyleContext, aPresContext, aConditions);
  7706. }
  7707. item = item->mNext;
  7708. MOZ_ASSERT(item, "Expected a eCSSUnit_List of odd length");
  7709. }
  7710. MOZ_ASSERT(!aResult.mMinTrackSizingFunctions.IsEmpty() &&
  7711. aResult.mMinTrackSizingFunctions.Length() ==
  7712. aResult.mMaxTrackSizingFunctions.Length() &&
  7713. aResult.mMinTrackSizingFunctions.Length() + 1 ==
  7714. aResult.mLineNameLists.Length(),
  7715. "Inconstistent array lengths for nsStyleGridTemplate");
  7716. }
  7717. }
  7718. }
  7719. static void
  7720. SetGridTemplateAreas(const nsCSSValue& aValue,
  7721. RefPtr<css::GridTemplateAreasValue>* aResult,
  7722. css::GridTemplateAreasValue* aParentValue,
  7723. RuleNodeCacheConditions& aConditions)
  7724. {
  7725. switch (aValue.GetUnit()) {
  7726. case eCSSUnit_Null:
  7727. break;
  7728. case eCSSUnit_Inherit:
  7729. aConditions.SetUncacheable();
  7730. *aResult = aParentValue;
  7731. break;
  7732. case eCSSUnit_Initial:
  7733. case eCSSUnit_Unset:
  7734. case eCSSUnit_None:
  7735. *aResult = nullptr;
  7736. break;
  7737. default:
  7738. *aResult = aValue.GetGridTemplateAreas();
  7739. }
  7740. }
  7741. static void
  7742. SetGridLine(const nsCSSValue& aValue,
  7743. nsStyleGridLine& aResult,
  7744. const nsStyleGridLine& aParentValue,
  7745. RuleNodeCacheConditions& aConditions)
  7746. {
  7747. switch (aValue.GetUnit()) {
  7748. case eCSSUnit_Null:
  7749. break;
  7750. case eCSSUnit_Inherit:
  7751. aConditions.SetUncacheable();
  7752. aResult = aParentValue;
  7753. break;
  7754. case eCSSUnit_Initial:
  7755. case eCSSUnit_Unset:
  7756. case eCSSUnit_Auto:
  7757. aResult.SetAuto();
  7758. break;
  7759. default:
  7760. aResult.SetAuto(); // Reset any existing value.
  7761. const nsCSSValueList* item = aValue.GetListValue();
  7762. do {
  7763. if (item->mValue.GetUnit() == eCSSUnit_Enumerated) {
  7764. aResult.mHasSpan = true;
  7765. } else if (item->mValue.GetUnit() == eCSSUnit_Integer) {
  7766. aResult.mInteger = clamped(item->mValue.GetIntValue(),
  7767. nsStyleGridLine::kMinLine,
  7768. nsStyleGridLine::kMaxLine);
  7769. } else if (item->mValue.GetUnit() == eCSSUnit_Ident) {
  7770. item->mValue.GetStringValue(aResult.mLineName);
  7771. } else {
  7772. NS_ASSERTION(false, "Unexpected unit");
  7773. }
  7774. item = item->mNext;
  7775. } while (item);
  7776. MOZ_ASSERT(!aResult.IsAuto(),
  7777. "should have set something away from default value");
  7778. }
  7779. }
  7780. const void*
  7781. nsRuleNode::ComputePositionData(void* aStartStruct,
  7782. const nsRuleData* aRuleData,
  7783. nsStyleContext* aContext,
  7784. nsRuleNode* aHighestNode,
  7785. const RuleDetail aRuleDetail,
  7786. const RuleNodeCacheConditions aConditions)
  7787. {
  7788. COMPUTE_START_RESET(Position, pos, parentPos)
  7789. // box offsets: length, percent, calc, auto, inherit
  7790. static const nsCSSPropertyID offsetProps[] = {
  7791. eCSSProperty_top,
  7792. eCSSProperty_right,
  7793. eCSSProperty_bottom,
  7794. eCSSProperty_left
  7795. };
  7796. nsStyleCoord coord;
  7797. NS_FOR_CSS_SIDES(side) {
  7798. nsStyleCoord parentCoord = parentPos->mOffset.Get(side);
  7799. if (SetCoord(*aRuleData->ValueFor(offsetProps[side]),
  7800. coord, parentCoord,
  7801. SETCOORD_LPAH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC |
  7802. SETCOORD_UNSET_INITIAL,
  7803. aContext, mPresContext, conditions)) {
  7804. pos->mOffset.Set(side, coord);
  7805. }
  7806. }
  7807. // We allow the enumerated box size property values -moz-min-content, etc. to
  7808. // be specified on both the {,min-,max-}width properties and the
  7809. // {,min-,max-}height properties, regardless of the writing mode. This is
  7810. // because the writing mode is not determined until here, at computed value
  7811. // time. Since we do not support layout behavior of these keywords on the
  7812. // block-axis properties, we turn them into unset if we find them in
  7813. // that case.
  7814. WritingMode wm(aContext);
  7815. bool vertical = wm.IsVertical();
  7816. const nsCSSValue* width = aRuleData->ValueForWidth();
  7817. if (width->GetUnit() == eCSSUnit_Enumerated) {
  7818. conditions.SetWritingModeDependency(wm.GetBits());
  7819. }
  7820. SetCoord(width->GetUnit() == eCSSUnit_Enumerated && vertical ?
  7821. nsCSSValue(eCSSUnit_Unset) : *width,
  7822. pos->mWidth, parentPos->mWidth,
  7823. SETCOORD_LPAEH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC |
  7824. SETCOORD_UNSET_INITIAL,
  7825. aContext, mPresContext, conditions);
  7826. const nsCSSValue* minWidth = aRuleData->ValueForMinWidth();
  7827. if (minWidth->GetUnit() == eCSSUnit_Enumerated) {
  7828. conditions.SetWritingModeDependency(wm.GetBits());
  7829. }
  7830. SetCoord(minWidth->GetUnit() == eCSSUnit_Enumerated && vertical ?
  7831. nsCSSValue(eCSSUnit_Unset) : *minWidth,
  7832. pos->mMinWidth, parentPos->mMinWidth,
  7833. SETCOORD_LPAEH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC |
  7834. SETCOORD_UNSET_INITIAL,
  7835. aContext, mPresContext, conditions);
  7836. const nsCSSValue* maxWidth = aRuleData->ValueForMaxWidth();
  7837. if (maxWidth->GetUnit() == eCSSUnit_Enumerated) {
  7838. conditions.SetWritingModeDependency(wm.GetBits());
  7839. }
  7840. SetCoord(maxWidth->GetUnit() == eCSSUnit_Enumerated && vertical ?
  7841. nsCSSValue(eCSSUnit_Unset) : *maxWidth,
  7842. pos->mMaxWidth, parentPos->mMaxWidth,
  7843. SETCOORD_LPOEH | SETCOORD_INITIAL_NONE | SETCOORD_STORE_CALC |
  7844. SETCOORD_UNSET_INITIAL,
  7845. aContext, mPresContext, conditions);
  7846. const nsCSSValue* height = aRuleData->ValueForHeight();
  7847. if (height->GetUnit() == eCSSUnit_Enumerated) {
  7848. conditions.SetWritingModeDependency(wm.GetBits());
  7849. }
  7850. SetCoord(height->GetUnit() == eCSSUnit_Enumerated && !vertical ?
  7851. nsCSSValue(eCSSUnit_Unset) : *height,
  7852. pos->mHeight, parentPos->mHeight,
  7853. SETCOORD_LPAEH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC |
  7854. SETCOORD_UNSET_INITIAL,
  7855. aContext, mPresContext, conditions);
  7856. const nsCSSValue* minHeight = aRuleData->ValueForMinHeight();
  7857. if (minHeight->GetUnit() == eCSSUnit_Enumerated) {
  7858. conditions.SetWritingModeDependency(wm.GetBits());
  7859. }
  7860. SetCoord(minHeight->GetUnit() == eCSSUnit_Enumerated && !vertical ?
  7861. nsCSSValue(eCSSUnit_Unset) : *minHeight,
  7862. pos->mMinHeight, parentPos->mMinHeight,
  7863. SETCOORD_LPAEH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC |
  7864. SETCOORD_UNSET_INITIAL,
  7865. aContext, mPresContext, conditions);
  7866. const nsCSSValue* maxHeight = aRuleData->ValueForMaxHeight();
  7867. if (maxHeight->GetUnit() == eCSSUnit_Enumerated) {
  7868. conditions.SetWritingModeDependency(wm.GetBits());
  7869. }
  7870. SetCoord(maxHeight->GetUnit() == eCSSUnit_Enumerated && !vertical ?
  7871. nsCSSValue(eCSSUnit_Unset) : *maxHeight,
  7872. pos->mMaxHeight, parentPos->mMaxHeight,
  7873. SETCOORD_LPOEH | SETCOORD_INITIAL_NONE | SETCOORD_STORE_CALC |
  7874. SETCOORD_UNSET_INITIAL,
  7875. aContext, mPresContext, conditions);
  7876. // aspect-ratio: float, initial
  7877. SetFactor(*aRuleData->ValueForAspectRatio(),
  7878. pos->mAspectRatio, conditions,
  7879. parentPos->mAspectRatio, 0.0f,
  7880. SETFCT_UNSET_INITIAL | SETFCT_POSITIVE | SETFCT_NONE);
  7881. // box-sizing: enum, inherit, initial
  7882. SetValue(*aRuleData->ValueForBoxSizing(),
  7883. pos->mBoxSizing, conditions,
  7884. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  7885. parentPos->mBoxSizing,
  7886. StyleBoxSizing::Content);
  7887. // align-content: enum, inherit, initial
  7888. SetValue(*aRuleData->ValueForAlignContent(),
  7889. pos->mAlignContent, conditions,
  7890. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  7891. parentPos->mAlignContent,
  7892. NS_STYLE_ALIGN_NORMAL);
  7893. // align-items: enum, inherit, initial
  7894. SetValue(*aRuleData->ValueForAlignItems(),
  7895. pos->mAlignItems, conditions,
  7896. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  7897. parentPos->mAlignItems,
  7898. NS_STYLE_ALIGN_NORMAL);
  7899. // align-self: enum, inherit, initial
  7900. SetValue(*aRuleData->ValueForAlignSelf(),
  7901. pos->mAlignSelf, conditions,
  7902. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  7903. parentPos->mAlignSelf,
  7904. NS_STYLE_ALIGN_AUTO);
  7905. // justify-content: enum, inherit, initial
  7906. SetValue(*aRuleData->ValueForJustifyContent(),
  7907. pos->mJustifyContent, conditions,
  7908. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  7909. parentPos->mJustifyContent,
  7910. NS_STYLE_JUSTIFY_NORMAL);
  7911. // justify-items: enum, inherit, initial
  7912. const auto& justifyItemsValue = *aRuleData->ValueForJustifyItems();
  7913. if (MOZ_UNLIKELY(justifyItemsValue.GetUnit() == eCSSUnit_Inherit)) {
  7914. if (MOZ_LIKELY(parentContext)) {
  7915. pos->mJustifyItems =
  7916. parentPos->ComputedJustifyItems(parentContext->GetParent());
  7917. } else {
  7918. pos->mJustifyItems = NS_STYLE_JUSTIFY_NORMAL;
  7919. }
  7920. conditions.SetUncacheable();
  7921. } else {
  7922. SetValue(justifyItemsValue,
  7923. pos->mJustifyItems, conditions,
  7924. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  7925. parentPos->mJustifyItems, // unused, we handle 'inherit' above
  7926. NS_STYLE_JUSTIFY_AUTO);
  7927. }
  7928. // justify-self: enum, inherit, initial
  7929. SetValue(*aRuleData->ValueForJustifySelf(),
  7930. pos->mJustifySelf, conditions,
  7931. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  7932. parentPos->mJustifySelf,
  7933. NS_STYLE_JUSTIFY_AUTO);
  7934. // flex-basis: auto, length, percent, enum, calc, inherit, initial
  7935. // (Note: The flags here should match those used for 'width' property above.)
  7936. SetCoord(*aRuleData->ValueForFlexBasis(), pos->mFlexBasis, parentPos->mFlexBasis,
  7937. SETCOORD_LPAEH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC |
  7938. SETCOORD_UNSET_INITIAL,
  7939. aContext, mPresContext, conditions);
  7940. // flex-direction: enum, inherit, initial
  7941. SetValue(*aRuleData->ValueForFlexDirection(),
  7942. pos->mFlexDirection, conditions,
  7943. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  7944. parentPos->mFlexDirection,
  7945. NS_STYLE_FLEX_DIRECTION_ROW);
  7946. // flex-grow: float, inherit, initial
  7947. SetFactor(*aRuleData->ValueForFlexGrow(),
  7948. pos->mFlexGrow, conditions,
  7949. parentPos->mFlexGrow, 0.0f,
  7950. SETFCT_UNSET_INITIAL);
  7951. // flex-shrink: float, inherit, initial
  7952. SetFactor(*aRuleData->ValueForFlexShrink(),
  7953. pos->mFlexShrink, conditions,
  7954. parentPos->mFlexShrink, 1.0f,
  7955. SETFCT_UNSET_INITIAL);
  7956. // flex-wrap: enum, inherit, initial
  7957. SetValue(*aRuleData->ValueForFlexWrap(),
  7958. pos->mFlexWrap, conditions,
  7959. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  7960. parentPos->mFlexWrap,
  7961. NS_STYLE_FLEX_WRAP_NOWRAP);
  7962. // order: integer, inherit, initial
  7963. SetValue(*aRuleData->ValueForOrder(),
  7964. pos->mOrder, conditions,
  7965. SETVAL_INTEGER | SETVAL_UNSET_INITIAL,
  7966. parentPos->mOrder,
  7967. NS_STYLE_ORDER_INITIAL);
  7968. // object-fit: enum, inherit, initial
  7969. SetValue(*aRuleData->ValueForObjectFit(),
  7970. pos->mObjectFit, conditions,
  7971. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  7972. parentPos->mObjectFit,
  7973. NS_STYLE_OBJECT_FIT_FILL);
  7974. // object-position
  7975. const nsCSSValue& objectPosition = *aRuleData->ValueForObjectPosition();
  7976. switch (objectPosition.GetUnit()) {
  7977. case eCSSUnit_Null:
  7978. break;
  7979. case eCSSUnit_Inherit:
  7980. conditions.SetUncacheable();
  7981. pos->mObjectPosition = parentPos->mObjectPosition;
  7982. break;
  7983. case eCSSUnit_Initial:
  7984. case eCSSUnit_Unset:
  7985. pos->mObjectPosition.SetInitialPercentValues(0.5f);
  7986. break;
  7987. default:
  7988. ComputePositionValue(aContext, objectPosition,
  7989. pos->mObjectPosition, conditions);
  7990. }
  7991. // grid-auto-flow
  7992. const nsCSSValue& gridAutoFlow = *aRuleData->ValueForGridAutoFlow();
  7993. switch (gridAutoFlow.GetUnit()) {
  7994. case eCSSUnit_Null:
  7995. break;
  7996. case eCSSUnit_Inherit:
  7997. conditions.SetUncacheable();
  7998. pos->mGridAutoFlow = parentPos->mGridAutoFlow;
  7999. break;
  8000. case eCSSUnit_Initial:
  8001. case eCSSUnit_Unset:
  8002. pos->mGridAutoFlow = NS_STYLE_GRID_AUTO_FLOW_ROW;
  8003. break;
  8004. default:
  8005. NS_ASSERTION(gridAutoFlow.GetUnit() == eCSSUnit_Enumerated,
  8006. "Unexpected unit");
  8007. pos->mGridAutoFlow = gridAutoFlow.GetIntValue();
  8008. }
  8009. // grid-auto-columns
  8010. SetGridAutoColumnsRows(*aRuleData->ValueForGridAutoColumns(),
  8011. pos->mGridAutoColumnsMin,
  8012. pos->mGridAutoColumnsMax,
  8013. parentPos->mGridAutoColumnsMin,
  8014. parentPos->mGridAutoColumnsMax,
  8015. aContext, mPresContext, conditions);
  8016. // grid-auto-rows
  8017. SetGridAutoColumnsRows(*aRuleData->ValueForGridAutoRows(),
  8018. pos->mGridAutoRowsMin,
  8019. pos->mGridAutoRowsMax,
  8020. parentPos->mGridAutoRowsMin,
  8021. parentPos->mGridAutoRowsMax,
  8022. aContext, mPresContext, conditions);
  8023. // grid-template-columns
  8024. SetGridTrackList(*aRuleData->ValueForGridTemplateColumns(),
  8025. pos->mGridTemplateColumns, parentPos->mGridTemplateColumns,
  8026. aContext, mPresContext, conditions);
  8027. // grid-template-rows
  8028. SetGridTrackList(*aRuleData->ValueForGridTemplateRows(),
  8029. pos->mGridTemplateRows, parentPos->mGridTemplateRows,
  8030. aContext, mPresContext, conditions);
  8031. // grid-tempate-areas
  8032. SetGridTemplateAreas(*aRuleData->ValueForGridTemplateAreas(),
  8033. &pos->mGridTemplateAreas,
  8034. parentPos->mGridTemplateAreas,
  8035. conditions);
  8036. // grid-column-start
  8037. SetGridLine(*aRuleData->ValueForGridColumnStart(),
  8038. pos->mGridColumnStart,
  8039. parentPos->mGridColumnStart,
  8040. conditions);
  8041. // grid-column-end
  8042. SetGridLine(*aRuleData->ValueForGridColumnEnd(),
  8043. pos->mGridColumnEnd,
  8044. parentPos->mGridColumnEnd,
  8045. conditions);
  8046. // grid-row-start
  8047. SetGridLine(*aRuleData->ValueForGridRowStart(),
  8048. pos->mGridRowStart,
  8049. parentPos->mGridRowStart,
  8050. conditions);
  8051. // grid-row-end
  8052. SetGridLine(*aRuleData->ValueForGridRowEnd(),
  8053. pos->mGridRowEnd,
  8054. parentPos->mGridRowEnd,
  8055. conditions);
  8056. // grid-column-gap
  8057. if (SetCoord(*aRuleData->ValueForGridColumnGap(),
  8058. pos->mGridColumnGap, parentPos->mGridColumnGap,
  8059. SETCOORD_LPH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC |
  8060. SETCOORD_CALC_CLAMP_NONNEGATIVE | SETCOORD_UNSET_INITIAL,
  8061. aContext, mPresContext, conditions)) {
  8062. } else {
  8063. MOZ_ASSERT(aRuleData->ValueForGridColumnGap()->GetUnit() == eCSSUnit_Null,
  8064. "unexpected unit");
  8065. }
  8066. // grid-row-gap
  8067. if (SetCoord(*aRuleData->ValueForGridRowGap(),
  8068. pos->mGridRowGap, parentPos->mGridRowGap,
  8069. SETCOORD_LPH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC |
  8070. SETCOORD_CALC_CLAMP_NONNEGATIVE | SETCOORD_UNSET_INITIAL,
  8071. aContext, mPresContext, conditions)) {
  8072. } else {
  8073. MOZ_ASSERT(aRuleData->ValueForGridRowGap()->GetUnit() == eCSSUnit_Null,
  8074. "unexpected unit");
  8075. }
  8076. // z-index
  8077. const nsCSSValue* zIndexValue = aRuleData->ValueForZIndex();
  8078. if (! SetCoord(*zIndexValue, pos->mZIndex, parentPos->mZIndex,
  8079. SETCOORD_IA | SETCOORD_INITIAL_AUTO | SETCOORD_UNSET_INITIAL,
  8080. aContext, nullptr, conditions)) {
  8081. if (eCSSUnit_Inherit == zIndexValue->GetUnit()) {
  8082. // handle inherit, because it's ok to inherit 'auto' here
  8083. conditions.SetUncacheable();
  8084. pos->mZIndex = parentPos->mZIndex;
  8085. }
  8086. }
  8087. COMPUTE_END_RESET(Position, pos)
  8088. }
  8089. const void*
  8090. nsRuleNode::ComputeTableData(void* aStartStruct,
  8091. const nsRuleData* aRuleData,
  8092. nsStyleContext* aContext,
  8093. nsRuleNode* aHighestNode,
  8094. const RuleDetail aRuleDetail,
  8095. const RuleNodeCacheConditions aConditions)
  8096. {
  8097. COMPUTE_START_RESET(Table, table, parentTable)
  8098. // table-layout: enum, inherit, initial
  8099. SetValue(*aRuleData->ValueForTableLayout(),
  8100. table->mLayoutStrategy, conditions,
  8101. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  8102. parentTable->mLayoutStrategy,
  8103. NS_STYLE_TABLE_LAYOUT_AUTO);
  8104. // span: pixels (not a real CSS prop)
  8105. const nsCSSValue* spanValue = aRuleData->ValueForSpan();
  8106. if (eCSSUnit_Enumerated == spanValue->GetUnit() ||
  8107. eCSSUnit_Integer == spanValue->GetUnit()) {
  8108. table->mSpan = spanValue->GetIntValue();
  8109. }
  8110. COMPUTE_END_RESET(Table, table)
  8111. }
  8112. const void*
  8113. nsRuleNode::ComputeTableBorderData(void* aStartStruct,
  8114. const nsRuleData* aRuleData,
  8115. nsStyleContext* aContext,
  8116. nsRuleNode* aHighestNode,
  8117. const RuleDetail aRuleDetail,
  8118. const RuleNodeCacheConditions aConditions)
  8119. {
  8120. COMPUTE_START_INHERITED(TableBorder, table, parentTable)
  8121. // border-collapse: enum, inherit, initial
  8122. SetValue(*aRuleData->ValueForBorderCollapse(), table->mBorderCollapse,
  8123. conditions,
  8124. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  8125. parentTable->mBorderCollapse,
  8126. NS_STYLE_BORDER_SEPARATE);
  8127. const nsCSSValue* borderSpacingValue = aRuleData->ValueForBorderSpacing();
  8128. // border-spacing: pair(length), inherit
  8129. if (borderSpacingValue->GetUnit() != eCSSUnit_Null) {
  8130. nsStyleCoord parentCol(parentTable->mBorderSpacingCol,
  8131. nsStyleCoord::CoordConstructor);
  8132. nsStyleCoord parentRow(parentTable->mBorderSpacingRow,
  8133. nsStyleCoord::CoordConstructor);
  8134. nsStyleCoord coordCol, coordRow;
  8135. #ifdef DEBUG
  8136. bool result =
  8137. #endif
  8138. SetPairCoords(*borderSpacingValue,
  8139. coordCol, coordRow, parentCol, parentRow,
  8140. SETCOORD_LH | SETCOORD_INITIAL_ZERO |
  8141. SETCOORD_CALC_LENGTH_ONLY |
  8142. SETCOORD_CALC_CLAMP_NONNEGATIVE | SETCOORD_UNSET_INHERIT,
  8143. aContext, mPresContext, conditions);
  8144. NS_ASSERTION(result, "malformed table border value");
  8145. table->mBorderSpacingCol = coordCol.GetCoordValue();
  8146. table->mBorderSpacingRow = coordRow.GetCoordValue();
  8147. }
  8148. // caption-side: enum, inherit, initial
  8149. SetValue(*aRuleData->ValueForCaptionSide(),
  8150. table->mCaptionSide, conditions,
  8151. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  8152. parentTable->mCaptionSide,
  8153. NS_STYLE_CAPTION_SIDE_TOP);
  8154. // empty-cells: enum, inherit, initial
  8155. SetValue(*aRuleData->ValueForEmptyCells(),
  8156. table->mEmptyCells, conditions,
  8157. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  8158. parentTable->mEmptyCells,
  8159. NS_STYLE_TABLE_EMPTY_CELLS_SHOW);
  8160. COMPUTE_END_INHERITED(TableBorder, table)
  8161. }
  8162. const void*
  8163. nsRuleNode::ComputeContentData(void* aStartStruct,
  8164. const nsRuleData* aRuleData,
  8165. nsStyleContext* aContext,
  8166. nsRuleNode* aHighestNode,
  8167. const RuleDetail aRuleDetail,
  8168. const RuleNodeCacheConditions aConditions)
  8169. {
  8170. uint32_t count;
  8171. nsAutoString buffer;
  8172. COMPUTE_START_RESET(Content, content, parentContent)
  8173. // content: [string, url, counter, attr, enum]+, normal, none, inherit
  8174. const nsCSSValue* contentValue = aRuleData->ValueForContent();
  8175. switch (contentValue->GetUnit()) {
  8176. case eCSSUnit_Null:
  8177. break;
  8178. case eCSSUnit_Normal:
  8179. case eCSSUnit_None:
  8180. case eCSSUnit_Initial:
  8181. case eCSSUnit_Unset:
  8182. // "normal", "none", "initial" and "unset" all mean no content
  8183. content->AllocateContents(0);
  8184. break;
  8185. case eCSSUnit_Inherit:
  8186. conditions.SetUncacheable();
  8187. count = parentContent->ContentCount();
  8188. content->AllocateContents(count);
  8189. while (0 < count--) {
  8190. content->ContentAt(count) = parentContent->ContentAt(count);
  8191. }
  8192. break;
  8193. case eCSSUnit_Enumerated: {
  8194. MOZ_ASSERT(contentValue->GetIntValue() == NS_STYLE_CONTENT_ALT_CONTENT,
  8195. "unrecognized solitary content keyword");
  8196. content->AllocateContents(1);
  8197. nsStyleContentData& data = content->ContentAt(0);
  8198. data.mType = eStyleContentType_AltContent;
  8199. data.mContent.mString = nullptr;
  8200. break;
  8201. }
  8202. case eCSSUnit_List:
  8203. case eCSSUnit_ListDep: {
  8204. const nsCSSValueList* contentValueList = contentValue->GetListValue();
  8205. count = 0;
  8206. while (contentValueList) {
  8207. count++;
  8208. contentValueList = contentValueList->mNext;
  8209. }
  8210. content->AllocateContents(count);
  8211. const nsAutoString nullStr;
  8212. count = 0;
  8213. contentValueList = contentValue->GetListValue();
  8214. while (contentValueList) {
  8215. const nsCSSValue& value = contentValueList->mValue;
  8216. nsCSSUnit unit = value.GetUnit();
  8217. nsStyleContentType type;
  8218. nsStyleContentData &data = content->ContentAt(count++);
  8219. switch (unit) {
  8220. case eCSSUnit_String: type = eStyleContentType_String; break;
  8221. case eCSSUnit_Image: type = eStyleContentType_Image; break;
  8222. case eCSSUnit_Attr: type = eStyleContentType_Attr; break;
  8223. case eCSSUnit_Counter: type = eStyleContentType_Counter; break;
  8224. case eCSSUnit_Counters: type = eStyleContentType_Counters; break;
  8225. case eCSSUnit_Enumerated:
  8226. switch (value.GetIntValue()) {
  8227. case NS_STYLE_CONTENT_OPEN_QUOTE:
  8228. type = eStyleContentType_OpenQuote; break;
  8229. case NS_STYLE_CONTENT_CLOSE_QUOTE:
  8230. type = eStyleContentType_CloseQuote; break;
  8231. case NS_STYLE_CONTENT_NO_OPEN_QUOTE:
  8232. type = eStyleContentType_NoOpenQuote; break;
  8233. case NS_STYLE_CONTENT_NO_CLOSE_QUOTE:
  8234. type = eStyleContentType_NoCloseQuote; break;
  8235. default:
  8236. NS_ERROR("bad content value");
  8237. type = eStyleContentType_Uninitialized;
  8238. }
  8239. break;
  8240. default:
  8241. NS_ERROR("bad content type");
  8242. type = eStyleContentType_Uninitialized;
  8243. }
  8244. data.mType = type;
  8245. if (type == eStyleContentType_Image) {
  8246. SetImageRequest([&](imgRequestProxy* req) {
  8247. data.SetImage(req);
  8248. }, mPresContext, value);
  8249. } else if (type <= eStyleContentType_Attr) {
  8250. value.GetStringValue(buffer);
  8251. data.mContent.mString = NS_strdup(buffer.get());
  8252. } else if (type <= eStyleContentType_Counters) {
  8253. data.mContent.mCounters = value.GetArrayValue();
  8254. data.mContent.mCounters->AddRef();
  8255. } else {
  8256. data.mContent.mString = nullptr;
  8257. }
  8258. contentValueList = contentValueList->mNext;
  8259. }
  8260. break;
  8261. }
  8262. default:
  8263. MOZ_ASSERT(false, "unrecognized content unit");
  8264. }
  8265. // counter-increment: [string [int]]+, none, inherit
  8266. const nsCSSValue* counterIncrementValue =
  8267. aRuleData->ValueForCounterIncrement();
  8268. switch (counterIncrementValue->GetUnit()) {
  8269. case eCSSUnit_Null:
  8270. break;
  8271. case eCSSUnit_None:
  8272. case eCSSUnit_Initial:
  8273. case eCSSUnit_Unset:
  8274. content->AllocateCounterIncrements(0);
  8275. break;
  8276. case eCSSUnit_Inherit:
  8277. conditions.SetUncacheable();
  8278. count = parentContent->CounterIncrementCount();
  8279. content->AllocateCounterIncrements(count);
  8280. while (count--) {
  8281. const nsStyleCounterData& data = parentContent->CounterIncrementAt(count);
  8282. content->SetCounterIncrementAt(count, data.mCounter, data.mValue);
  8283. }
  8284. break;
  8285. case eCSSUnit_PairList:
  8286. case eCSSUnit_PairListDep: {
  8287. const nsCSSValuePairList* ourIncrement =
  8288. counterIncrementValue->GetPairListValue();
  8289. MOZ_ASSERT(ourIncrement->mXValue.GetUnit() == eCSSUnit_Ident,
  8290. "unexpected value unit");
  8291. count = ListLength(ourIncrement);
  8292. content->AllocateCounterIncrements(count);
  8293. count = 0;
  8294. for (const nsCSSValuePairList* p = ourIncrement; p; p = p->mNext, count++) {
  8295. int32_t increment;
  8296. if (p->mYValue.GetUnit() == eCSSUnit_Integer) {
  8297. increment = p->mYValue.GetIntValue();
  8298. } else {
  8299. increment = 1;
  8300. }
  8301. p->mXValue.GetStringValue(buffer);
  8302. content->SetCounterIncrementAt(count, buffer, increment);
  8303. }
  8304. break;
  8305. }
  8306. default:
  8307. MOZ_ASSERT(false, "unexpected value unit");
  8308. }
  8309. // counter-reset: [string [int]]+, none, inherit
  8310. const nsCSSValue* counterResetValue = aRuleData->ValueForCounterReset();
  8311. switch (counterResetValue->GetUnit()) {
  8312. case eCSSUnit_Null:
  8313. break;
  8314. case eCSSUnit_None:
  8315. case eCSSUnit_Initial:
  8316. case eCSSUnit_Unset:
  8317. content->AllocateCounterResets(0);
  8318. break;
  8319. case eCSSUnit_Inherit:
  8320. conditions.SetUncacheable();
  8321. count = parentContent->CounterResetCount();
  8322. content->AllocateCounterResets(count);
  8323. while (0 < count--) {
  8324. const nsStyleCounterData& data = parentContent->CounterResetAt(count);
  8325. content->SetCounterResetAt(count, data.mCounter, data.mValue);
  8326. }
  8327. break;
  8328. case eCSSUnit_PairList:
  8329. case eCSSUnit_PairListDep: {
  8330. const nsCSSValuePairList* ourReset =
  8331. counterResetValue->GetPairListValue();
  8332. MOZ_ASSERT(ourReset->mXValue.GetUnit() == eCSSUnit_Ident,
  8333. "unexpected value unit");
  8334. count = ListLength(ourReset);
  8335. content->AllocateCounterResets(count);
  8336. count = 0;
  8337. for (const nsCSSValuePairList* p = ourReset; p; p = p->mNext, count++) {
  8338. int32_t reset;
  8339. if (p->mYValue.GetUnit() == eCSSUnit_Integer) {
  8340. reset = p->mYValue.GetIntValue();
  8341. } else {
  8342. reset = 0;
  8343. }
  8344. p->mXValue.GetStringValue(buffer);
  8345. content->SetCounterResetAt(count, buffer, reset);
  8346. }
  8347. break;
  8348. }
  8349. default:
  8350. MOZ_ASSERT(false, "unexpected value unit");
  8351. }
  8352. // If we ended up with an image, track it.
  8353. for (uint32_t i = 0; i < content->ContentCount(); ++i) {
  8354. if ((content->ContentAt(i).mType == eStyleContentType_Image) &&
  8355. content->ContentAt(i).mContent.mImage) {
  8356. content->ContentAt(i).TrackImage(
  8357. aContext->PresContext()->Document()->ImageTracker());
  8358. }
  8359. }
  8360. COMPUTE_END_RESET(Content, content)
  8361. }
  8362. const void*
  8363. nsRuleNode::ComputeXULData(void* aStartStruct,
  8364. const nsRuleData* aRuleData,
  8365. nsStyleContext* aContext,
  8366. nsRuleNode* aHighestNode,
  8367. const RuleDetail aRuleDetail,
  8368. const RuleNodeCacheConditions aConditions)
  8369. {
  8370. COMPUTE_START_RESET(XUL, xul, parentXUL)
  8371. // box-align: enum, inherit, initial
  8372. SetValue(*aRuleData->ValueForBoxAlign(),
  8373. xul->mBoxAlign, conditions,
  8374. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  8375. parentXUL->mBoxAlign,
  8376. StyleBoxAlign::Stretch);
  8377. // box-direction: enum, inherit, initial
  8378. SetValue(*aRuleData->ValueForBoxDirection(),
  8379. xul->mBoxDirection, conditions,
  8380. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  8381. parentXUL->mBoxDirection,
  8382. StyleBoxDirection::Normal);
  8383. // box-flex: factor, inherit
  8384. SetFactor(*aRuleData->ValueForBoxFlex(),
  8385. xul->mBoxFlex, conditions,
  8386. parentXUL->mBoxFlex, 0.0f,
  8387. SETFCT_UNSET_INITIAL);
  8388. // box-orient: enum, inherit, initial
  8389. SetValue(*aRuleData->ValueForBoxOrient(),
  8390. xul->mBoxOrient, conditions,
  8391. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  8392. parentXUL->mBoxOrient,
  8393. StyleBoxOrient::Horizontal);
  8394. // box-pack: enum, inherit, initial
  8395. SetValue(*aRuleData->ValueForBoxPack(),
  8396. xul->mBoxPack, conditions,
  8397. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  8398. parentXUL->mBoxPack,
  8399. StyleBoxPack::Start);
  8400. // box-ordinal-group: integer, inherit, initial
  8401. SetValue(*aRuleData->ValueForBoxOrdinalGroup(),
  8402. xul->mBoxOrdinal, conditions,
  8403. SETVAL_INTEGER | SETVAL_UNSET_INITIAL,
  8404. parentXUL->mBoxOrdinal, 1);
  8405. const nsCSSValue* stackSizingValue = aRuleData->ValueForStackSizing();
  8406. if (eCSSUnit_Inherit == stackSizingValue->GetUnit()) {
  8407. conditions.SetUncacheable();
  8408. xul->mStretchStack = parentXUL->mStretchStack;
  8409. } else if (eCSSUnit_Initial == stackSizingValue->GetUnit() ||
  8410. eCSSUnit_Unset == stackSizingValue->GetUnit()) {
  8411. xul->mStretchStack = true;
  8412. } else if (eCSSUnit_Enumerated == stackSizingValue->GetUnit()) {
  8413. xul->mStretchStack = stackSizingValue->GetIntValue() ==
  8414. NS_STYLE_STACK_SIZING_STRETCH_TO_FIT;
  8415. }
  8416. COMPUTE_END_RESET(XUL, xul)
  8417. }
  8418. const void*
  8419. nsRuleNode::ComputeColumnData(void* aStartStruct,
  8420. const nsRuleData* aRuleData,
  8421. nsStyleContext* aContext,
  8422. nsRuleNode* aHighestNode,
  8423. const RuleDetail aRuleDetail,
  8424. const RuleNodeCacheConditions aConditions)
  8425. {
  8426. COMPUTE_START_RESET(Column, column, parent)
  8427. // column-width: length, auto, inherit
  8428. SetCoord(*aRuleData->ValueForColumnWidth(),
  8429. column->mColumnWidth, parent->mColumnWidth,
  8430. SETCOORD_LAH | SETCOORD_INITIAL_AUTO |
  8431. SETCOORD_CALC_LENGTH_ONLY | SETCOORD_CALC_CLAMP_NONNEGATIVE |
  8432. SETCOORD_UNSET_INITIAL,
  8433. aContext, mPresContext, conditions);
  8434. // column-gap: length, inherit, normal
  8435. SetCoord(*aRuleData->ValueForColumnGap(),
  8436. column->mColumnGap, parent->mColumnGap,
  8437. SETCOORD_LH | SETCOORD_NORMAL | SETCOORD_INITIAL_NORMAL |
  8438. SETCOORD_CALC_LENGTH_ONLY | SETCOORD_UNSET_INITIAL,
  8439. aContext, mPresContext, conditions);
  8440. // clamp negative calc() to 0
  8441. if (column->mColumnGap.GetUnit() == eStyleUnit_Coord) {
  8442. column->mColumnGap.SetCoordValue(
  8443. std::max(column->mColumnGap.GetCoordValue(), 0));
  8444. }
  8445. // column-count: auto, integer, inherit
  8446. const nsCSSValue* columnCountValue = aRuleData->ValueForColumnCount();
  8447. if (eCSSUnit_Auto == columnCountValue->GetUnit() ||
  8448. eCSSUnit_Initial == columnCountValue->GetUnit() ||
  8449. eCSSUnit_Unset == columnCountValue->GetUnit()) {
  8450. column->mColumnCount = NS_STYLE_COLUMN_COUNT_AUTO;
  8451. } else if (eCSSUnit_Integer == columnCountValue->GetUnit()) {
  8452. column->mColumnCount = columnCountValue->GetIntValue();
  8453. // Max kMaxColumnCount columns - wallpaper for bug 345583.
  8454. column->mColumnCount = std::min(column->mColumnCount,
  8455. nsStyleColumn::kMaxColumnCount);
  8456. } else if (eCSSUnit_Inherit == columnCountValue->GetUnit()) {
  8457. conditions.SetUncacheable();
  8458. column->mColumnCount = parent->mColumnCount;
  8459. }
  8460. // column-rule-width: length, enum, inherit
  8461. const nsCSSValue& widthValue = *aRuleData->ValueForColumnRuleWidth();
  8462. if (eCSSUnit_Initial == widthValue.GetUnit() ||
  8463. eCSSUnit_Unset == widthValue.GetUnit()) {
  8464. column->SetColumnRuleWidth(
  8465. (mPresContext->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM]);
  8466. } else if (eCSSUnit_Enumerated == widthValue.GetUnit()) {
  8467. NS_ASSERTION(widthValue.GetIntValue() == NS_STYLE_BORDER_WIDTH_THIN ||
  8468. widthValue.GetIntValue() == NS_STYLE_BORDER_WIDTH_MEDIUM ||
  8469. widthValue.GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK,
  8470. "Unexpected enum value");
  8471. column->SetColumnRuleWidth(
  8472. (mPresContext->GetBorderWidthTable())[widthValue.GetIntValue()]);
  8473. } else if (eCSSUnit_Inherit == widthValue.GetUnit()) {
  8474. column->SetColumnRuleWidth(parent->GetComputedColumnRuleWidth());
  8475. conditions.SetUncacheable();
  8476. } else if (widthValue.IsLengthUnit() || widthValue.IsCalcUnit()) {
  8477. nscoord len =
  8478. CalcLength(widthValue, aContext, mPresContext, conditions);
  8479. if (len < 0) {
  8480. // FIXME: This is untested (by test_value_storage.html) for
  8481. // column-rule-width since it gets covered up by the border
  8482. // rounding code.
  8483. NS_ASSERTION(widthValue.IsCalcUnit(),
  8484. "parser should have rejected negative length");
  8485. len = 0;
  8486. }
  8487. column->SetColumnRuleWidth(len);
  8488. }
  8489. // column-rule-style: enum, inherit
  8490. const nsCSSValue& styleValue = *aRuleData->ValueForColumnRuleStyle();
  8491. MOZ_ASSERT(eCSSUnit_None != styleValue.GetUnit(),
  8492. "'none' should be handled as enumerated value");
  8493. if (eCSSUnit_Enumerated == styleValue.GetUnit()) {
  8494. column->mColumnRuleStyle = styleValue.GetIntValue();
  8495. } else if (eCSSUnit_Initial == styleValue.GetUnit() ||
  8496. eCSSUnit_Unset == styleValue.GetUnit()) {
  8497. column->mColumnRuleStyle = NS_STYLE_BORDER_STYLE_NONE;
  8498. } else if (eCSSUnit_Inherit == styleValue.GetUnit()) {
  8499. conditions.SetUncacheable();
  8500. column->mColumnRuleStyle = parent->mColumnRuleStyle;
  8501. }
  8502. // column-rule-color: color, inherit
  8503. SetComplexColor<eUnsetInitial>(*aRuleData->ValueForColumnRuleColor(),
  8504. parent->mColumnRuleColor,
  8505. StyleComplexColor::CurrentColor(),
  8506. mPresContext,
  8507. column->mColumnRuleColor, conditions);
  8508. // column-fill: enum
  8509. SetValue(*aRuleData->ValueForColumnFill(),
  8510. column->mColumnFill, conditions,
  8511. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  8512. parent->mColumnFill,
  8513. NS_STYLE_COLUMN_FILL_BALANCE);
  8514. COMPUTE_END_RESET(Column, column)
  8515. }
  8516. static void
  8517. SetSVGPaint(const nsCSSValue& aValue, const nsStyleSVGPaint& parentPaint,
  8518. nsPresContext* aPresContext, nsStyleContext *aContext,
  8519. nsStyleSVGPaint& aResult, nsStyleSVGPaintType aInitialPaintType,
  8520. RuleNodeCacheConditions& aConditions)
  8521. {
  8522. MOZ_ASSERT(aInitialPaintType == eStyleSVGPaintType_None ||
  8523. aInitialPaintType == eStyleSVGPaintType_Color,
  8524. "SetSVGPaint only supports initial values being either 'black' "
  8525. "(represented by eStyleSVGPaintType_Color) or none (by "
  8526. "eStyleSVGPaintType_None)");
  8527. nscolor color;
  8528. if (aValue.GetUnit() == eCSSUnit_Inherit ||
  8529. aValue.GetUnit() == eCSSUnit_Unset) {
  8530. aResult = parentPaint;
  8531. aConditions.SetUncacheable();
  8532. } else if (aValue.GetUnit() == eCSSUnit_None) {
  8533. aResult.SetNone();
  8534. } else if (aValue.GetUnit() == eCSSUnit_Initial) {
  8535. if (aInitialPaintType == eStyleSVGPaintType_None) {
  8536. aResult.SetNone();
  8537. } else {
  8538. aResult.SetColor(NS_RGB(0, 0, 0));
  8539. }
  8540. } else if (SetColor(aValue, NS_RGB(0, 0, 0), aPresContext, aContext,
  8541. color, aConditions)) {
  8542. aResult.SetColor(color);
  8543. } else if (aValue.GetUnit() == eCSSUnit_Pair) {
  8544. const nsCSSValuePair& pair = aValue.GetPairValue();
  8545. nscolor fallback;
  8546. if (pair.mYValue.GetUnit() == eCSSUnit_None) {
  8547. fallback = NS_RGBA(0, 0, 0, 0);
  8548. } else {
  8549. MOZ_ASSERT(pair.mYValue.GetUnit() != eCSSUnit_Inherit,
  8550. "cannot inherit fallback colour");
  8551. SetColor(pair.mYValue, NS_RGB(0, 0, 0), aPresContext, aContext,
  8552. fallback, aConditions);
  8553. }
  8554. if (pair.mXValue.GetUnit() == eCSSUnit_URL) {
  8555. aResult.SetPaintServer(pair.mXValue.GetURLStructValue(), fallback);
  8556. } else if (pair.mXValue.GetUnit() == eCSSUnit_Enumerated) {
  8557. switch (pair.mXValue.GetIntValue()) {
  8558. case NS_COLOR_CONTEXT_FILL:
  8559. aResult.SetContextValue(eStyleSVGPaintType_ContextFill, fallback);
  8560. break;
  8561. case NS_COLOR_CONTEXT_STROKE:
  8562. aResult.SetContextValue(eStyleSVGPaintType_ContextStroke, fallback);
  8563. break;
  8564. default:
  8565. NS_NOTREACHED("unknown keyword as paint server value");
  8566. }
  8567. } else {
  8568. NS_NOTREACHED("malformed paint server value");
  8569. }
  8570. } else {
  8571. MOZ_ASSERT(aValue.GetUnit() == eCSSUnit_Null,
  8572. "malformed paint server value");
  8573. }
  8574. }
  8575. static void
  8576. SetSVGOpacity(const nsCSSValue& aValue,
  8577. float& aOpacityField, nsStyleSVGOpacitySource& aOpacityTypeField,
  8578. RuleNodeCacheConditions& aConditions,
  8579. float aParentOpacity, nsStyleSVGOpacitySource aParentOpacityType)
  8580. {
  8581. if (eCSSUnit_Enumerated == aValue.GetUnit()) {
  8582. switch (aValue.GetIntValue()) {
  8583. case NS_STYLE_CONTEXT_FILL_OPACITY:
  8584. aOpacityTypeField = eStyleSVGOpacitySource_ContextFillOpacity;
  8585. break;
  8586. case NS_STYLE_CONTEXT_STROKE_OPACITY:
  8587. aOpacityTypeField = eStyleSVGOpacitySource_ContextStrokeOpacity;
  8588. break;
  8589. default:
  8590. NS_NOTREACHED("SetSVGOpacity: Unknown keyword");
  8591. }
  8592. // Fall back on fully opaque
  8593. aOpacityField = 1.0f;
  8594. } else if (eCSSUnit_Inherit == aValue.GetUnit() ||
  8595. eCSSUnit_Unset == aValue.GetUnit()) {
  8596. aConditions.SetUncacheable();
  8597. aOpacityField = aParentOpacity;
  8598. aOpacityTypeField = aParentOpacityType;
  8599. } else if (eCSSUnit_Null != aValue.GetUnit()) {
  8600. SetFactor(aValue, aOpacityField, aConditions,
  8601. aParentOpacity, 1.0f, SETFCT_OPACITY);
  8602. aOpacityTypeField = eStyleSVGOpacitySource_Normal;
  8603. }
  8604. }
  8605. /* static */
  8606. void
  8607. nsRuleNode::FillAllMaskLists(nsStyleImageLayers& aMask,
  8608. uint32_t aMaxItemCount)
  8609. {
  8610. // Delete any extra items. We need to keep layers in which any
  8611. // property was specified.
  8612. aMask.mLayers.TruncateLengthNonZero(aMaxItemCount);
  8613. uint32_t fillCount = aMask.mImageCount;
  8614. FillImageLayerList(aMask.mLayers,
  8615. &nsStyleImageLayers::Layer::mImage,
  8616. aMask.mImageCount, fillCount);
  8617. FillImageLayerList(aMask.mLayers,
  8618. &nsStyleImageLayers::Layer::mSourceURI,
  8619. aMask.mImageCount, fillCount);
  8620. FillImageLayerList(aMask.mLayers,
  8621. &nsStyleImageLayers::Layer::mRepeat,
  8622. aMask.mRepeatCount, fillCount);
  8623. FillImageLayerList(aMask.mLayers,
  8624. &nsStyleImageLayers::Layer::mClip,
  8625. aMask.mClipCount, fillCount);
  8626. FillImageLayerList(aMask.mLayers,
  8627. &nsStyleImageLayers::Layer::mOrigin,
  8628. aMask.mOriginCount, fillCount);
  8629. FillImageLayerPositionCoordList(aMask.mLayers,
  8630. &Position::mXPosition,
  8631. aMask.mPositionXCount, fillCount);
  8632. FillImageLayerPositionCoordList(aMask.mLayers,
  8633. &Position::mYPosition,
  8634. aMask.mPositionYCount, fillCount);
  8635. FillImageLayerList(aMask.mLayers,
  8636. &nsStyleImageLayers::Layer::mSize,
  8637. aMask.mSizeCount, fillCount);
  8638. FillImageLayerList(aMask.mLayers,
  8639. &nsStyleImageLayers::Layer::mMaskMode,
  8640. aMask.mMaskModeCount, fillCount);
  8641. FillImageLayerList(aMask.mLayers,
  8642. &nsStyleImageLayers::Layer::mComposite,
  8643. aMask.mCompositeCount, fillCount);
  8644. }
  8645. const void*
  8646. nsRuleNode::ComputeSVGData(void* aStartStruct,
  8647. const nsRuleData* aRuleData,
  8648. nsStyleContext* aContext,
  8649. nsRuleNode* aHighestNode,
  8650. const RuleDetail aRuleDetail,
  8651. const RuleNodeCacheConditions aConditions)
  8652. {
  8653. COMPUTE_START_INHERITED(SVG, svg, parentSVG)
  8654. // clip-rule: enum, inherit, initial
  8655. SetValue(*aRuleData->ValueForClipRule(),
  8656. svg->mClipRule, conditions,
  8657. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  8658. parentSVG->mClipRule,
  8659. StyleFillRule::Nonzero);
  8660. // color-interpolation: enum, inherit, initial
  8661. SetValue(*aRuleData->ValueForColorInterpolation(),
  8662. svg->mColorInterpolation, conditions,
  8663. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  8664. parentSVG->mColorInterpolation,
  8665. NS_STYLE_COLOR_INTERPOLATION_SRGB);
  8666. // color-interpolation-filters: enum, inherit, initial
  8667. SetValue(*aRuleData->ValueForColorInterpolationFilters(),
  8668. svg->mColorInterpolationFilters, conditions,
  8669. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  8670. parentSVG->mColorInterpolationFilters,
  8671. NS_STYLE_COLOR_INTERPOLATION_LINEARRGB);
  8672. // fill:
  8673. SetSVGPaint(*aRuleData->ValueForFill(),
  8674. parentSVG->mFill, mPresContext, aContext,
  8675. svg->mFill, eStyleSVGPaintType_Color, conditions);
  8676. // fill-opacity: factor, inherit, initial,
  8677. // context-fill-opacity, context-stroke-opacity
  8678. nsStyleSVGOpacitySource contextFillOpacity = svg->FillOpacitySource();
  8679. SetSVGOpacity(*aRuleData->ValueForFillOpacity(),
  8680. svg->mFillOpacity, contextFillOpacity, conditions,
  8681. parentSVG->mFillOpacity, parentSVG->FillOpacitySource());
  8682. svg->SetFillOpacitySource(contextFillOpacity);
  8683. // fill-rule: enum, inherit, initial
  8684. SetValue(*aRuleData->ValueForFillRule(),
  8685. svg->mFillRule, conditions,
  8686. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  8687. parentSVG->mFillRule,
  8688. StyleFillRule::Nonzero);
  8689. // marker-end: url, none, inherit
  8690. const nsCSSValue* markerEndValue = aRuleData->ValueForMarkerEnd();
  8691. if (eCSSUnit_URL == markerEndValue->GetUnit()) {
  8692. svg->mMarkerEnd = markerEndValue->GetURLStructValue();
  8693. } else if (eCSSUnit_None == markerEndValue->GetUnit() ||
  8694. eCSSUnit_Initial == markerEndValue->GetUnit()) {
  8695. svg->mMarkerEnd = nullptr;
  8696. } else if (eCSSUnit_Inherit == markerEndValue->GetUnit() ||
  8697. eCSSUnit_Unset == markerEndValue->GetUnit()) {
  8698. conditions.SetUncacheable();
  8699. svg->mMarkerEnd = parentSVG->mMarkerEnd;
  8700. }
  8701. // marker-mid: url, none, inherit
  8702. const nsCSSValue* markerMidValue = aRuleData->ValueForMarkerMid();
  8703. if (eCSSUnit_URL == markerMidValue->GetUnit()) {
  8704. svg->mMarkerMid = markerMidValue->GetURLStructValue();
  8705. } else if (eCSSUnit_None == markerMidValue->GetUnit() ||
  8706. eCSSUnit_Initial == markerMidValue->GetUnit()) {
  8707. svg->mMarkerMid = nullptr;
  8708. } else if (eCSSUnit_Inherit == markerMidValue->GetUnit() ||
  8709. eCSSUnit_Unset == markerMidValue->GetUnit()) {
  8710. conditions.SetUncacheable();
  8711. svg->mMarkerMid = parentSVG->mMarkerMid;
  8712. }
  8713. // marker-start: url, none, inherit
  8714. const nsCSSValue* markerStartValue = aRuleData->ValueForMarkerStart();
  8715. if (eCSSUnit_URL == markerStartValue->GetUnit()) {
  8716. svg->mMarkerStart = markerStartValue->GetURLStructValue();
  8717. } else if (eCSSUnit_None == markerStartValue->GetUnit() ||
  8718. eCSSUnit_Initial == markerStartValue->GetUnit()) {
  8719. svg->mMarkerStart = nullptr;
  8720. } else if (eCSSUnit_Inherit == markerStartValue->GetUnit() ||
  8721. eCSSUnit_Unset == markerStartValue->GetUnit()) {
  8722. conditions.SetUncacheable();
  8723. svg->mMarkerStart = parentSVG->mMarkerStart;
  8724. }
  8725. // paint-order: enum (bit field), inherit, initial
  8726. const nsCSSValue* paintOrderValue = aRuleData->ValueForPaintOrder();
  8727. switch (paintOrderValue->GetUnit()) {
  8728. case eCSSUnit_Null:
  8729. break;
  8730. case eCSSUnit_Enumerated:
  8731. static_assert
  8732. (NS_STYLE_PAINT_ORDER_BITWIDTH * NS_STYLE_PAINT_ORDER_LAST_VALUE <= 8,
  8733. "SVGStyleStruct::mPaintOrder not big enough");
  8734. svg->mPaintOrder = static_cast<uint8_t>(paintOrderValue->GetIntValue());
  8735. break;
  8736. case eCSSUnit_Inherit:
  8737. case eCSSUnit_Unset:
  8738. conditions.SetUncacheable();
  8739. svg->mPaintOrder = parentSVG->mPaintOrder;
  8740. break;
  8741. case eCSSUnit_Initial:
  8742. svg->mPaintOrder = NS_STYLE_PAINT_ORDER_NORMAL;
  8743. break;
  8744. default:
  8745. NS_NOTREACHED("unexpected unit");
  8746. }
  8747. // shape-rendering: enum, inherit
  8748. SetValue(*aRuleData->ValueForShapeRendering(),
  8749. svg->mShapeRendering, conditions,
  8750. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  8751. parentSVG->mShapeRendering,
  8752. NS_STYLE_SHAPE_RENDERING_AUTO);
  8753. // stroke:
  8754. SetSVGPaint(*aRuleData->ValueForStroke(),
  8755. parentSVG->mStroke, mPresContext, aContext,
  8756. svg->mStroke, eStyleSVGPaintType_None, conditions);
  8757. // stroke-dasharray: <dasharray>, none, inherit, context-value
  8758. const nsCSSValue* strokeDasharrayValue = aRuleData->ValueForStrokeDasharray();
  8759. switch (strokeDasharrayValue->GetUnit()) {
  8760. case eCSSUnit_Null:
  8761. break;
  8762. case eCSSUnit_Inherit:
  8763. case eCSSUnit_Unset:
  8764. conditions.SetUncacheable();
  8765. svg->SetStrokeDasharrayFromObject(parentSVG->StrokeDasharrayFromObject());
  8766. svg->mStrokeDasharray = parentSVG->mStrokeDasharray;
  8767. break;
  8768. case eCSSUnit_Enumerated:
  8769. MOZ_ASSERT(strokeDasharrayValue->GetIntValue() ==
  8770. NS_STYLE_STROKE_PROP_CONTEXT_VALUE,
  8771. "Unknown keyword for stroke-dasharray");
  8772. svg->SetStrokeDasharrayFromObject(true);
  8773. svg->mStrokeDasharray.Clear();
  8774. break;
  8775. case eCSSUnit_Initial:
  8776. case eCSSUnit_None:
  8777. svg->SetStrokeDasharrayFromObject(false);
  8778. svg->mStrokeDasharray.Clear();
  8779. break;
  8780. case eCSSUnit_List:
  8781. case eCSSUnit_ListDep: {
  8782. svg->SetStrokeDasharrayFromObject(false);
  8783. svg->mStrokeDasharray.Clear();
  8784. // count number of values
  8785. const nsCSSValueList *value = strokeDasharrayValue->GetListValue();
  8786. uint32_t strokeDasharrayLength = ListLength(value);
  8787. MOZ_ASSERT(strokeDasharrayLength != 0, "no dasharray items");
  8788. svg->mStrokeDasharray.SetLength(strokeDasharrayLength);
  8789. uint32_t i = 0;
  8790. while (nullptr != value) {
  8791. SetCoord(value->mValue,
  8792. svg->mStrokeDasharray[i++], nsStyleCoord(),
  8793. SETCOORD_LP | SETCOORD_FACTOR,
  8794. aContext, mPresContext, conditions);
  8795. value = value->mNext;
  8796. }
  8797. break;
  8798. }
  8799. default:
  8800. MOZ_ASSERT(false, "unrecognized dasharray unit");
  8801. }
  8802. // stroke-dashoffset: <dashoffset>, inherit
  8803. const nsCSSValue *strokeDashoffsetValue =
  8804. aRuleData->ValueForStrokeDashoffset();
  8805. svg->SetStrokeDashoffsetFromObject(
  8806. strokeDashoffsetValue->GetUnit() == eCSSUnit_Enumerated &&
  8807. strokeDashoffsetValue->GetIntValue() == NS_STYLE_STROKE_PROP_CONTEXT_VALUE);
  8808. if (svg->StrokeDashoffsetFromObject()) {
  8809. svg->mStrokeDashoffset.SetCoordValue(0);
  8810. } else if (strokeDashoffsetValue->IsCalcUnit()) {
  8811. LengthPercentNumberCalcOps ops(aContext, mPresContext, conditions);
  8812. RealNumberComputedCalc obj = css::ComputeCalc(*strokeDashoffsetValue, ops);
  8813. if (obj.mIsNumber) {
  8814. svg->mStrokeDashoffset.SetFactorValue(obj.mLength);
  8815. } else {
  8816. nsStyleCoord::Calc* calcObj = new nsStyleCoord::Calc;
  8817. calcObj->mLength = NSToCoordRoundWithClamp(obj.mLength);
  8818. calcObj->mPercent = obj.mPercent;
  8819. calcObj->mHasPercent = ops.mHasPercent;
  8820. svg->mStrokeDashoffset.SetCalcValue(calcObj);
  8821. }
  8822. } else {
  8823. SetCoord(*aRuleData->ValueForStrokeDashoffset(),
  8824. svg->mStrokeDashoffset, parentSVG->mStrokeDashoffset,
  8825. SETCOORD_LPH | SETCOORD_FACTOR | SETCOORD_INITIAL_ZERO |
  8826. SETCOORD_UNSET_INHERIT,
  8827. aContext, mPresContext, conditions);
  8828. }
  8829. // stroke-linecap: enum, inherit, initial
  8830. SetValue(*aRuleData->ValueForStrokeLinecap(),
  8831. svg->mStrokeLinecap, conditions,
  8832. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  8833. parentSVG->mStrokeLinecap,
  8834. NS_STYLE_STROKE_LINECAP_BUTT);
  8835. // stroke-linejoin: enum, inherit, initial
  8836. SetValue(*aRuleData->ValueForStrokeLinejoin(),
  8837. svg->mStrokeLinejoin, conditions,
  8838. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  8839. parentSVG->mStrokeLinejoin,
  8840. NS_STYLE_STROKE_LINEJOIN_MITER);
  8841. // stroke-miterlimit: <miterlimit>, inherit
  8842. SetFactor(*aRuleData->ValueForStrokeMiterlimit(),
  8843. svg->mStrokeMiterlimit,
  8844. conditions,
  8845. parentSVG->mStrokeMiterlimit, 4.0f,
  8846. SETFCT_UNSET_INHERIT);
  8847. // stroke-opacity:
  8848. nsStyleSVGOpacitySource contextStrokeOpacity = svg->StrokeOpacitySource();
  8849. SetSVGOpacity(*aRuleData->ValueForStrokeOpacity(),
  8850. svg->mStrokeOpacity, contextStrokeOpacity, conditions,
  8851. parentSVG->mStrokeOpacity, parentSVG->StrokeOpacitySource());
  8852. svg->SetStrokeOpacitySource(contextStrokeOpacity);
  8853. // stroke-width:
  8854. const nsCSSValue* strokeWidthValue = aRuleData->ValueForStrokeWidth();
  8855. switch (strokeWidthValue->GetUnit()) {
  8856. case eCSSUnit_Enumerated:
  8857. MOZ_ASSERT(strokeWidthValue->GetIntValue() ==
  8858. NS_STYLE_STROKE_PROP_CONTEXT_VALUE,
  8859. "Unrecognized keyword for stroke-width");
  8860. svg->SetStrokeWidthFromObject(true);
  8861. svg->mStrokeWidth.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1));
  8862. break;
  8863. case eCSSUnit_Initial:
  8864. svg->SetStrokeWidthFromObject(false);
  8865. svg->mStrokeWidth.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1));
  8866. break;
  8867. default:
  8868. svg->SetStrokeWidthFromObject(false);
  8869. SetCoord(*strokeWidthValue,
  8870. svg->mStrokeWidth, parentSVG->mStrokeWidth,
  8871. SETCOORD_LPH | SETCOORD_FACTOR | SETCOORD_UNSET_INHERIT,
  8872. aContext, mPresContext, conditions);
  8873. }
  8874. // text-anchor: enum, inherit, initial
  8875. SetValue(*aRuleData->ValueForTextAnchor(),
  8876. svg->mTextAnchor, conditions,
  8877. SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
  8878. parentSVG->mTextAnchor,
  8879. NS_STYLE_TEXT_ANCHOR_START);
  8880. COMPUTE_END_INHERITED(SVG, svg)
  8881. }
  8882. static already_AddRefed<StyleBasicShape>
  8883. GetStyleBasicShapeFromCSSValue(const nsCSSValue& aValue,
  8884. nsStyleContext* aStyleContext,
  8885. nsPresContext* aPresContext,
  8886. RuleNodeCacheConditions& aConditions)
  8887. {
  8888. RefPtr<StyleBasicShape> basicShape;
  8889. nsCSSValue::Array* shapeFunction = aValue.GetArrayValue();
  8890. nsCSSKeyword functionName =
  8891. (nsCSSKeyword)shapeFunction->Item(0).GetIntValue();
  8892. if (functionName == eCSSKeyword_polygon) {
  8893. MOZ_ASSERT(!basicShape, "did not expect value");
  8894. basicShape = new StyleBasicShape(StyleBasicShapeType::Polygon);
  8895. MOZ_ASSERT(shapeFunction->Count() > 1,
  8896. "polygon has wrong number of arguments");
  8897. size_t j = 1;
  8898. if (shapeFunction->Item(j).GetUnit() == eCSSUnit_Enumerated) {
  8899. StyleFillRule rule;
  8900. SetEnumValueHelper::SetEnumeratedValue(rule, shapeFunction->Item(j));
  8901. basicShape->SetFillRule(rule);
  8902. ++j;
  8903. }
  8904. const int32_t mask = SETCOORD_PERCENT | SETCOORD_LENGTH |
  8905. SETCOORD_STORE_CALC;
  8906. const nsCSSValuePairList* curPair =
  8907. shapeFunction->Item(j).GetPairListValue();
  8908. nsTArray<nsStyleCoord>& coordinates = basicShape->Coordinates();
  8909. while (curPair) {
  8910. nsStyleCoord xCoord, yCoord;
  8911. DebugOnly<bool> didSetCoordX = SetCoord(curPair->mXValue, xCoord,
  8912. nsStyleCoord(), mask,
  8913. aStyleContext, aPresContext,
  8914. aConditions);
  8915. coordinates.AppendElement(xCoord);
  8916. MOZ_ASSERT(didSetCoordX, "unexpected x coordinate unit");
  8917. DebugOnly<bool> didSetCoordY = SetCoord(curPair->mYValue, yCoord,
  8918. nsStyleCoord(), mask,
  8919. aStyleContext, aPresContext,
  8920. aConditions);
  8921. coordinates.AppendElement(yCoord);
  8922. MOZ_ASSERT(didSetCoordY, "unexpected y coordinate unit");
  8923. curPair = curPair->mNext;
  8924. }
  8925. } else if (functionName == eCSSKeyword_circle ||
  8926. functionName == eCSSKeyword_ellipse) {
  8927. StyleBasicShapeType type = functionName == eCSSKeyword_circle ?
  8928. StyleBasicShapeType::Circle :
  8929. StyleBasicShapeType::Ellipse;
  8930. MOZ_ASSERT(!basicShape, "did not expect value");
  8931. basicShape = new StyleBasicShape(type);
  8932. const int32_t mask = SETCOORD_PERCENT | SETCOORD_LENGTH |
  8933. SETCOORD_STORE_CALC | SETCOORD_ENUMERATED;
  8934. size_t count = type == StyleBasicShapeType::Circle ? 2 : 3;
  8935. MOZ_ASSERT(shapeFunction->Count() == count + 1,
  8936. "unexpected arguments count");
  8937. MOZ_ASSERT(type == StyleBasicShapeType::Circle ||
  8938. (shapeFunction->Item(1).GetUnit() == eCSSUnit_Null) ==
  8939. (shapeFunction->Item(2).GetUnit() == eCSSUnit_Null),
  8940. "ellipse should have two radii or none");
  8941. for (size_t j = 1; j < count; ++j) {
  8942. const nsCSSValue& val = shapeFunction->Item(j);
  8943. nsStyleCoord radius;
  8944. if (val.GetUnit() != eCSSUnit_Null) {
  8945. DebugOnly<bool> didSetRadius = SetCoord(val, radius,
  8946. nsStyleCoord(), mask,
  8947. aStyleContext,
  8948. aPresContext,
  8949. aConditions);
  8950. MOZ_ASSERT(didSetRadius, "unexpected radius unit");
  8951. } else {
  8952. radius.SetIntValue(NS_RADIUS_CLOSEST_SIDE, eStyleUnit_Enumerated);
  8953. }
  8954. basicShape->Coordinates().AppendElement(radius);
  8955. }
  8956. const nsCSSValue& positionVal = shapeFunction->Item(count);
  8957. if (positionVal.GetUnit() == eCSSUnit_Array) {
  8958. ComputePositionValue(aStyleContext, positionVal,
  8959. basicShape->GetPosition(),
  8960. aConditions);
  8961. } else {
  8962. MOZ_ASSERT(positionVal.GetUnit() == eCSSUnit_Null,
  8963. "expected no value");
  8964. }
  8965. } else if (functionName == eCSSKeyword_inset) {
  8966. MOZ_ASSERT(!basicShape, "did not expect value");
  8967. basicShape = new StyleBasicShape(StyleBasicShapeType::Inset);
  8968. MOZ_ASSERT(shapeFunction->Count() == 6,
  8969. "inset function has wrong number of arguments");
  8970. MOZ_ASSERT(shapeFunction->Item(1).GetUnit() != eCSSUnit_Null,
  8971. "no shape arguments defined");
  8972. const int32_t mask = SETCOORD_PERCENT | SETCOORD_LENGTH |
  8973. SETCOORD_STORE_CALC;
  8974. nsTArray<nsStyleCoord>& coords = basicShape->Coordinates();
  8975. for (size_t j = 1; j <= 4; ++j) {
  8976. const nsCSSValue& val = shapeFunction->Item(j);
  8977. nsStyleCoord inset;
  8978. // Fill missing values to get 4 at the end.
  8979. if (val.GetUnit() == eCSSUnit_Null) {
  8980. if (j == 4) {
  8981. inset = coords[1];
  8982. } else {
  8983. MOZ_ASSERT(j != 1, "first argument not specified");
  8984. inset = coords[0];
  8985. }
  8986. } else {
  8987. DebugOnly<bool> didSetInset = SetCoord(val, inset,
  8988. nsStyleCoord(), mask,
  8989. aStyleContext, aPresContext,
  8990. aConditions);
  8991. MOZ_ASSERT(didSetInset, "unexpected inset unit");
  8992. }
  8993. coords.AppendElement(inset);
  8994. }
  8995. nsStyleCorners& insetRadius = basicShape->GetRadius();
  8996. if (shapeFunction->Item(5).GetUnit() == eCSSUnit_Array) {
  8997. nsCSSValue::Array* radiiArray = shapeFunction->Item(5).GetArrayValue();
  8998. NS_FOR_CSS_FULL_CORNERS(corner) {
  8999. int cx = NS_FULL_TO_HALF_CORNER(corner, false);
  9000. int cy = NS_FULL_TO_HALF_CORNER(corner, true);
  9001. const nsCSSValue& radius = radiiArray->Item(corner);
  9002. nsStyleCoord coordX, coordY;
  9003. DebugOnly<bool> didSetRadii = SetPairCoords(radius, coordX, coordY,
  9004. nsStyleCoord(),
  9005. nsStyleCoord(), mask,
  9006. aStyleContext,
  9007. aPresContext,
  9008. aConditions);
  9009. MOZ_ASSERT(didSetRadii, "unexpected radius unit");
  9010. insetRadius.Set(cx, coordX);
  9011. insetRadius.Set(cy, coordY);
  9012. }
  9013. } else {
  9014. MOZ_ASSERT(shapeFunction->Item(5).GetUnit() == eCSSUnit_Null,
  9015. "unexpected value");
  9016. // Initialize border-radius
  9017. nsStyleCoord zero;
  9018. zero.SetCoordValue(0);
  9019. NS_FOR_CSS_HALF_CORNERS(j) {
  9020. insetRadius.Set(j, zero);
  9021. }
  9022. }
  9023. } else {
  9024. NS_NOTREACHED("unexpected basic shape function");
  9025. }
  9026. return basicShape.forget();
  9027. }
  9028. template<typename ReferenceBox>
  9029. static void
  9030. SetStyleShapeSourceToCSSValue(
  9031. StyleShapeSource<ReferenceBox>* aShapeSource,
  9032. const nsCSSValue* aValue,
  9033. nsStyleContext* aStyleContext,
  9034. nsPresContext* aPresContext,
  9035. RuleNodeCacheConditions& aConditions)
  9036. {
  9037. MOZ_ASSERT(aValue->GetUnit() == eCSSUnit_Array,
  9038. "expected a basic shape or reference box");
  9039. const nsCSSValue::Array* array = aValue->GetArrayValue();
  9040. MOZ_ASSERT(array->Count() == 1 || array->Count() == 2,
  9041. "Expect one or both of a shape function and a reference box");
  9042. ReferenceBox referenceBox = ReferenceBox::NoBox;
  9043. RefPtr<StyleBasicShape> basicShape;
  9044. for (size_t i = 0; i < array->Count(); ++i) {
  9045. const nsCSSValue& item = array->Item(i);
  9046. if (item.GetUnit() == eCSSUnit_Enumerated) {
  9047. referenceBox = static_cast<ReferenceBox>(item.GetIntValue());
  9048. } else if (item.GetUnit() == eCSSUnit_Function) {
  9049. basicShape = GetStyleBasicShapeFromCSSValue(item, aStyleContext,
  9050. aPresContext, aConditions);
  9051. } else {
  9052. MOZ_ASSERT_UNREACHABLE("Unexpected unit!");
  9053. return;
  9054. }
  9055. }
  9056. if (basicShape) {
  9057. aShapeSource->SetBasicShape(basicShape, referenceBox);
  9058. } else {
  9059. aShapeSource->SetReferenceBox(referenceBox);
  9060. }
  9061. }
  9062. // Returns true if the nsStyleFilter was successfully set using the nsCSSValue.
  9063. static bool
  9064. SetStyleFilterToCSSValue(nsStyleFilter* aStyleFilter,
  9065. const nsCSSValue& aValue,
  9066. nsStyleContext* aStyleContext,
  9067. nsPresContext* aPresContext,
  9068. RuleNodeCacheConditions& aConditions)
  9069. {
  9070. nsCSSUnit unit = aValue.GetUnit();
  9071. if (unit == eCSSUnit_URL) {
  9072. return aStyleFilter->SetURL(aValue.GetURLStructValue());
  9073. }
  9074. MOZ_ASSERT(unit == eCSSUnit_Function, "expected a filter function");
  9075. nsCSSValue::Array* filterFunction = aValue.GetArrayValue();
  9076. nsCSSKeyword functionName =
  9077. (nsCSSKeyword)filterFunction->Item(0).GetIntValue();
  9078. int32_t type;
  9079. DebugOnly<bool> foundKeyword =
  9080. nsCSSProps::FindKeyword(functionName,
  9081. nsCSSProps::kFilterFunctionKTable,
  9082. type);
  9083. MOZ_ASSERT(foundKeyword, "unknown filter type");
  9084. if (type == NS_STYLE_FILTER_DROP_SHADOW) {
  9085. RefPtr<nsCSSShadowArray> shadowArray = GetShadowData(
  9086. filterFunction->Item(1).GetListValue(),
  9087. aStyleContext,
  9088. false,
  9089. aPresContext,
  9090. aConditions);
  9091. aStyleFilter->SetDropShadow(shadowArray);
  9092. return true;
  9093. }
  9094. int32_t mask = SETCOORD_PERCENT | SETCOORD_FACTOR;
  9095. if (type == NS_STYLE_FILTER_BLUR) {
  9096. mask = SETCOORD_LENGTH |
  9097. SETCOORD_CALC_LENGTH_ONLY |
  9098. SETCOORD_CALC_CLAMP_NONNEGATIVE;
  9099. } else if (type == NS_STYLE_FILTER_HUE_ROTATE) {
  9100. mask = SETCOORD_ANGLE;
  9101. }
  9102. MOZ_ASSERT(filterFunction->Count() == 2,
  9103. "all filter functions should have exactly one argument");
  9104. nsCSSValue& arg = filterFunction->Item(1);
  9105. nsStyleCoord filterParameter;
  9106. DebugOnly<bool> didSetCoord = SetCoord(arg, filterParameter,
  9107. nsStyleCoord(), mask,
  9108. aStyleContext, aPresContext,
  9109. aConditions);
  9110. aStyleFilter->SetFilterParameter(filterParameter, type);
  9111. MOZ_ASSERT(didSetCoord, "unexpected unit");
  9112. return true;
  9113. }
  9114. const void*
  9115. nsRuleNode::ComputeSVGResetData(void* aStartStruct,
  9116. const nsRuleData* aRuleData,
  9117. nsStyleContext* aContext,
  9118. nsRuleNode* aHighestNode,
  9119. const RuleDetail aRuleDetail,
  9120. const RuleNodeCacheConditions aConditions)
  9121. {
  9122. COMPUTE_START_RESET(SVGReset, svgReset, parentSVGReset)
  9123. // stop-color:
  9124. const nsCSSValue* stopColorValue = aRuleData->ValueForStopColor();
  9125. if (eCSSUnit_Initial == stopColorValue->GetUnit() ||
  9126. eCSSUnit_Unset == stopColorValue->GetUnit()) {
  9127. svgReset->mStopColor = NS_RGB(0, 0, 0);
  9128. } else {
  9129. SetColor(*stopColorValue, parentSVGReset->mStopColor,
  9130. mPresContext, aContext, svgReset->mStopColor, conditions);
  9131. }
  9132. // flood-color:
  9133. const nsCSSValue* floodColorValue = aRuleData->ValueForFloodColor();
  9134. if (eCSSUnit_Initial == floodColorValue->GetUnit() ||
  9135. eCSSUnit_Unset == floodColorValue->GetUnit()) {
  9136. svgReset->mFloodColor = NS_RGB(0, 0, 0);
  9137. } else {
  9138. SetColor(*floodColorValue, parentSVGReset->mFloodColor,
  9139. mPresContext, aContext, svgReset->mFloodColor, conditions);
  9140. }
  9141. // lighting-color:
  9142. const nsCSSValue* lightingColorValue = aRuleData->ValueForLightingColor();
  9143. if (eCSSUnit_Initial == lightingColorValue->GetUnit() ||
  9144. eCSSUnit_Unset == lightingColorValue->GetUnit()) {
  9145. svgReset->mLightingColor = NS_RGB(255, 255, 255);
  9146. } else {
  9147. SetColor(*lightingColorValue, parentSVGReset->mLightingColor,
  9148. mPresContext, aContext, svgReset->mLightingColor,
  9149. conditions);
  9150. }
  9151. // clip-path: url, <basic-shape> || <geometry-box>, none, inherit
  9152. const nsCSSValue* clipPathValue = aRuleData->ValueForClipPath();
  9153. switch (clipPathValue->GetUnit()) {
  9154. case eCSSUnit_Null:
  9155. break;
  9156. case eCSSUnit_None:
  9157. case eCSSUnit_Initial:
  9158. case eCSSUnit_Unset:
  9159. svgReset->mClipPath = StyleClipPath();
  9160. break;
  9161. case eCSSUnit_Inherit:
  9162. conditions.SetUncacheable();
  9163. svgReset->mClipPath = parentSVGReset->mClipPath;
  9164. break;
  9165. case eCSSUnit_URL: {
  9166. svgReset->mClipPath = StyleClipPath();
  9167. svgReset->mClipPath.SetURL(clipPathValue->GetURLStructValue());
  9168. break;
  9169. }
  9170. case eCSSUnit_Array: {
  9171. svgReset->mClipPath = StyleClipPath();
  9172. SetStyleShapeSourceToCSSValue(&svgReset->mClipPath, clipPathValue, aContext,
  9173. mPresContext, conditions);
  9174. break;
  9175. }
  9176. default:
  9177. NS_NOTREACHED("unexpected unit");
  9178. }
  9179. // stop-opacity:
  9180. SetFactor(*aRuleData->ValueForStopOpacity(),
  9181. svgReset->mStopOpacity, conditions,
  9182. parentSVGReset->mStopOpacity, 1.0f,
  9183. SETFCT_OPACITY | SETFCT_UNSET_INITIAL);
  9184. // flood-opacity:
  9185. SetFactor(*aRuleData->ValueForFloodOpacity(),
  9186. svgReset->mFloodOpacity, conditions,
  9187. parentSVGReset->mFloodOpacity, 1.0f,
  9188. SETFCT_OPACITY | SETFCT_UNSET_INITIAL);
  9189. // dominant-baseline: enum, inherit, initial
  9190. SetValue(*aRuleData->ValueForDominantBaseline(),
  9191. svgReset->mDominantBaseline,
  9192. conditions,
  9193. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  9194. parentSVGReset->mDominantBaseline,
  9195. NS_STYLE_DOMINANT_BASELINE_AUTO);
  9196. // vector-effect: enum, inherit, initial
  9197. SetValue(*aRuleData->ValueForVectorEffect(),
  9198. svgReset->mVectorEffect,
  9199. conditions,
  9200. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  9201. parentSVGReset->mVectorEffect,
  9202. NS_STYLE_VECTOR_EFFECT_NONE);
  9203. // mask-type: enum, inherit, initial
  9204. SetValue(*aRuleData->ValueForMaskType(),
  9205. svgReset->mMaskType,
  9206. conditions,
  9207. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  9208. parentSVGReset->mMaskType,
  9209. NS_STYLE_MASK_TYPE_LUMINANCE);
  9210. uint32_t maxItemCount = 1;
  9211. bool rebuild = false;
  9212. // mask-image: none | <url> | <image-list> | <element-reference> | <gradient>
  9213. nsStyleImage initialImage;
  9214. SetImageLayerList(aContext, *aRuleData->ValueForMaskImage(),
  9215. svgReset->mMask.mLayers,
  9216. parentSVGReset->mMask.mLayers,
  9217. &nsStyleImageLayers::Layer::mImage,
  9218. initialImage, parentSVGReset->mMask.mImageCount,
  9219. svgReset->mMask.mImageCount,
  9220. maxItemCount, rebuild, conditions);
  9221. SetImageLayerList(aContext, *aRuleData->ValueForMaskImage(),
  9222. svgReset->mMask.mLayers,
  9223. parentSVGReset->mMask.mLayers,
  9224. &nsStyleImageLayers::Layer::mSourceURI,
  9225. RefPtr<css::URLValueData>(),
  9226. parentSVGReset->mMask.mImageCount,
  9227. svgReset->mMask.mImageCount,
  9228. maxItemCount, rebuild, conditions);
  9229. // mask-repeat: enum, inherit, initial [pair list]
  9230. nsStyleImageLayers::Repeat initialRepeat;
  9231. initialRepeat.SetInitialValues();
  9232. SetImageLayerPairList(aContext, *aRuleData->ValueForMaskRepeat(),
  9233. svgReset->mMask.mLayers,
  9234. parentSVGReset->mMask.mLayers,
  9235. &nsStyleImageLayers::Layer::mRepeat,
  9236. initialRepeat, parentSVGReset->mMask.mRepeatCount,
  9237. svgReset->mMask.mRepeatCount, maxItemCount, rebuild,
  9238. conditions);
  9239. // mask-clip: enum, inherit, initial [list]
  9240. SetImageLayerList(aContext, *aRuleData->ValueForMaskClip(),
  9241. svgReset->mMask.mLayers,
  9242. parentSVGReset->mMask.mLayers,
  9243. &nsStyleImageLayers::Layer::mClip,
  9244. StyleGeometryBox::Border,
  9245. parentSVGReset->mMask.mClipCount,
  9246. svgReset->mMask.mClipCount, maxItemCount, rebuild,
  9247. conditions);
  9248. // mask-origin: enum, inherit, initial [list]
  9249. SetImageLayerList(aContext, *aRuleData->ValueForMaskOrigin(),
  9250. svgReset->mMask.mLayers,
  9251. parentSVGReset->mMask.mLayers,
  9252. &nsStyleImageLayers::Layer::mOrigin,
  9253. StyleGeometryBox::Border,
  9254. parentSVGReset->mMask.mOriginCount,
  9255. svgReset->mMask.mOriginCount, maxItemCount, rebuild,
  9256. conditions);
  9257. // mask-position-x/y: enum, length, percent (flags), inherit [list]
  9258. Position::Coord initialPositionCoord;
  9259. initialPositionCoord.mPercent = 0.0f;
  9260. initialPositionCoord.mLength = 0;
  9261. initialPositionCoord.mHasPercent = true;
  9262. SetImageLayerPositionCoordList(
  9263. aContext, *aRuleData->ValueForMaskPositionX(),
  9264. svgReset->mMask.mLayers,
  9265. parentSVGReset->mMask.mLayers,
  9266. &Position::mXPosition,
  9267. initialPositionCoord, parentSVGReset->mMask.mPositionXCount,
  9268. svgReset->mMask.mPositionXCount, maxItemCount, rebuild,
  9269. conditions);
  9270. SetImageLayerPositionCoordList(
  9271. aContext, *aRuleData->ValueForMaskPositionY(),
  9272. svgReset->mMask.mLayers,
  9273. parentSVGReset->mMask.mLayers,
  9274. &Position::mYPosition,
  9275. initialPositionCoord, parentSVGReset->mMask.mPositionYCount,
  9276. svgReset->mMask.mPositionYCount, maxItemCount, rebuild,
  9277. conditions);
  9278. // mask-size: enum, length, auto, inherit, initial [pair list]
  9279. nsStyleImageLayers::Size initialSize;
  9280. initialSize.SetInitialValues();
  9281. SetImageLayerPairList(aContext, *aRuleData->ValueForMaskSize(),
  9282. svgReset->mMask.mLayers,
  9283. parentSVGReset->mMask.mLayers,
  9284. &nsStyleImageLayers::Layer::mSize,
  9285. initialSize, parentSVGReset->mMask.mSizeCount,
  9286. svgReset->mMask.mSizeCount, maxItemCount, rebuild,
  9287. conditions);
  9288. // mask-mode: enum, inherit, initial [list]
  9289. SetImageLayerList(aContext, *aRuleData->ValueForMaskMode(),
  9290. svgReset->mMask.mLayers,
  9291. parentSVGReset->mMask.mLayers,
  9292. &nsStyleImageLayers::Layer::mMaskMode,
  9293. uint8_t(NS_STYLE_MASK_MODE_MATCH_SOURCE),
  9294. parentSVGReset->mMask.mMaskModeCount,
  9295. svgReset->mMask.mMaskModeCount, maxItemCount, rebuild, conditions);
  9296. // mask-composite: enum, inherit, initial [list]
  9297. SetImageLayerList(aContext, *aRuleData->ValueForMaskComposite(),
  9298. svgReset->mMask.mLayers,
  9299. parentSVGReset->mMask.mLayers,
  9300. &nsStyleImageLayers::Layer::mComposite,
  9301. uint8_t(NS_STYLE_MASK_COMPOSITE_ADD),
  9302. parentSVGReset->mMask.mCompositeCount,
  9303. svgReset->mMask.mCompositeCount, maxItemCount, rebuild, conditions);
  9304. if (rebuild) {
  9305. FillAllBackgroundLists(svgReset->mMask, maxItemCount);
  9306. }
  9307. COMPUTE_END_RESET(SVGReset, svgReset)
  9308. }
  9309. const void*
  9310. nsRuleNode::ComputeVariablesData(void* aStartStruct,
  9311. const nsRuleData* aRuleData,
  9312. nsStyleContext* aContext,
  9313. nsRuleNode* aHighestNode,
  9314. const RuleDetail aRuleDetail,
  9315. const RuleNodeCacheConditions aConditions)
  9316. {
  9317. COMPUTE_START_INHERITED(Variables, variables, parentVariables)
  9318. MOZ_ASSERT(aRuleData->mVariables,
  9319. "shouldn't be in ComputeVariablesData if there were no variable "
  9320. "declarations specified");
  9321. CSSVariableResolver resolver(&variables->mVariables);
  9322. resolver.Resolve(&parentVariables->mVariables,
  9323. aRuleData->mVariables);
  9324. conditions.SetUncacheable();
  9325. COMPUTE_END_INHERITED(Variables, variables)
  9326. }
  9327. const void*
  9328. nsRuleNode::ComputeEffectsData(void* aStartStruct,
  9329. const nsRuleData* aRuleData,
  9330. nsStyleContext* aContext,
  9331. nsRuleNode* aHighestNode,
  9332. const RuleDetail aRuleDetail,
  9333. const RuleNodeCacheConditions aConditions)
  9334. {
  9335. COMPUTE_START_RESET(Effects, effects, parentEffects)
  9336. // filter: url, none, inherit
  9337. const nsCSSValue* filterValue = aRuleData->ValueForFilter();
  9338. switch (filterValue->GetUnit()) {
  9339. case eCSSUnit_Null:
  9340. break;
  9341. case eCSSUnit_None:
  9342. case eCSSUnit_Initial:
  9343. case eCSSUnit_Unset:
  9344. effects->mFilters.Clear();
  9345. break;
  9346. case eCSSUnit_Inherit:
  9347. conditions.SetUncacheable();
  9348. effects->mFilters = parentEffects->mFilters;
  9349. break;
  9350. case eCSSUnit_List:
  9351. case eCSSUnit_ListDep: {
  9352. effects->mFilters.Clear();
  9353. const nsCSSValueList* cur = filterValue->GetListValue();
  9354. while (cur) {
  9355. nsStyleFilter styleFilter;
  9356. if (!SetStyleFilterToCSSValue(&styleFilter, cur->mValue, aContext,
  9357. mPresContext, conditions)) {
  9358. effects->mFilters.Clear();
  9359. break;
  9360. }
  9361. MOZ_ASSERT(styleFilter.GetType() != NS_STYLE_FILTER_NONE,
  9362. "filter should be set");
  9363. effects->mFilters.AppendElement(styleFilter);
  9364. cur = cur->mNext;
  9365. }
  9366. break;
  9367. }
  9368. default:
  9369. NS_NOTREACHED("unexpected unit");
  9370. }
  9371. // box-shadow: none, list, inherit, initial
  9372. const nsCSSValue* boxShadowValue = aRuleData->ValueForBoxShadow();
  9373. switch (boxShadowValue->GetUnit()) {
  9374. case eCSSUnit_Null:
  9375. break;
  9376. case eCSSUnit_Initial:
  9377. case eCSSUnit_Unset:
  9378. case eCSSUnit_None:
  9379. effects->mBoxShadow = nullptr;
  9380. break;
  9381. case eCSSUnit_Inherit:
  9382. effects->mBoxShadow = parentEffects->mBoxShadow;
  9383. conditions.SetUncacheable();
  9384. break;
  9385. case eCSSUnit_List:
  9386. case eCSSUnit_ListDep:
  9387. effects->mBoxShadow = GetShadowData(boxShadowValue->GetListValue(),
  9388. aContext, true, mPresContext, conditions);
  9389. break;
  9390. default:
  9391. MOZ_ASSERT(false, "unrecognized shadow unit");
  9392. }
  9393. // clip property: length, auto, inherit
  9394. const nsCSSValue* clipValue = aRuleData->ValueForClip();
  9395. switch (clipValue->GetUnit()) {
  9396. case eCSSUnit_Inherit:
  9397. conditions.SetUncacheable();
  9398. effects->mClipFlags = parentEffects->mClipFlags;
  9399. effects->mClip = parentEffects->mClip;
  9400. break;
  9401. case eCSSUnit_Initial:
  9402. case eCSSUnit_Unset:
  9403. case eCSSUnit_Auto:
  9404. effects->mClipFlags = NS_STYLE_CLIP_AUTO;
  9405. effects->mClip.SetRect(0,0,0,0);
  9406. break;
  9407. case eCSSUnit_Null:
  9408. break;
  9409. case eCSSUnit_Rect: {
  9410. const nsCSSRect& clipRect = clipValue->GetRectValue();
  9411. effects->mClipFlags = NS_STYLE_CLIP_RECT;
  9412. if (clipRect.mTop.GetUnit() == eCSSUnit_Auto) {
  9413. effects->mClip.y = 0;
  9414. effects->mClipFlags |= NS_STYLE_CLIP_TOP_AUTO;
  9415. } else if (clipRect.mTop.IsLengthUnit()) {
  9416. effects->mClip.y = CalcLength(clipRect.mTop, aContext,
  9417. mPresContext, conditions);
  9418. }
  9419. if (clipRect.mBottom.GetUnit() == eCSSUnit_Auto) {
  9420. // Setting to NS_MAXSIZE for the 'auto' case ensures that
  9421. // the clip rect is nonempty. It is important that mClip be
  9422. // nonempty if the actual clip rect could be nonempty.
  9423. effects->mClip.height = NS_MAXSIZE;
  9424. effects->mClipFlags |= NS_STYLE_CLIP_BOTTOM_AUTO;
  9425. } else if (clipRect.mBottom.IsLengthUnit()) {
  9426. effects->mClip.height = CalcLength(clipRect.mBottom, aContext,
  9427. mPresContext, conditions) -
  9428. effects->mClip.y;
  9429. }
  9430. if (clipRect.mLeft.GetUnit() == eCSSUnit_Auto) {
  9431. effects->mClip.x = 0;
  9432. effects->mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO;
  9433. } else if (clipRect.mLeft.IsLengthUnit()) {
  9434. effects->mClip.x = CalcLength(clipRect.mLeft, aContext,
  9435. mPresContext, conditions);
  9436. }
  9437. if (clipRect.mRight.GetUnit() == eCSSUnit_Auto) {
  9438. // Setting to NS_MAXSIZE for the 'auto' case ensures that
  9439. // the clip rect is nonempty. It is important that mClip be
  9440. // nonempty if the actual clip rect could be nonempty.
  9441. effects->mClip.width = NS_MAXSIZE;
  9442. effects->mClipFlags |= NS_STYLE_CLIP_RIGHT_AUTO;
  9443. } else if (clipRect.mRight.IsLengthUnit()) {
  9444. effects->mClip.width = CalcLength(clipRect.mRight, aContext,
  9445. mPresContext, conditions) -
  9446. effects->mClip.x;
  9447. }
  9448. break;
  9449. }
  9450. default:
  9451. MOZ_ASSERT(false, "unrecognized clip unit");
  9452. }
  9453. // opacity: factor, inherit, initial
  9454. SetFactor(*aRuleData->ValueForOpacity(), effects->mOpacity, conditions,
  9455. parentEffects->mOpacity, 1.0f,
  9456. SETFCT_OPACITY | SETFCT_UNSET_INITIAL);
  9457. // mix-blend-mode: enum, inherit, initial
  9458. SetValue(*aRuleData->ValueForMixBlendMode(), effects->mMixBlendMode,
  9459. conditions,
  9460. SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
  9461. parentEffects->mMixBlendMode, NS_STYLE_BLEND_NORMAL);
  9462. COMPUTE_END_RESET(Effects, effects)
  9463. }
  9464. const void*
  9465. nsRuleNode::GetStyleData(nsStyleStructID aSID,
  9466. nsStyleContext* aContext,
  9467. bool aComputeData)
  9468. {
  9469. NS_ASSERTION(IsUsedDirectly(),
  9470. "if we ever call this on rule nodes that aren't used "
  9471. "directly, we should adjust handling of mDependentBits "
  9472. "in some way.");
  9473. MOZ_ASSERT(!aContext->GetCachedStyleData(aSID),
  9474. "style context should not have cached data for struct");
  9475. const void *data;
  9476. // Never use cached data for animated style inside a pseudo-element;
  9477. // see comment on cacheability in AnimValuesStyleRule::MapRuleInfoInto.
  9478. if (!(HasAnimationData() && ParentHasPseudoElementData(aContext))) {
  9479. data = mStyleData.GetStyleData(aSID, aContext, aComputeData);
  9480. if (MOZ_LIKELY(data != nullptr)) {
  9481. // For inherited structs, mark the struct (which will be set on
  9482. // the context by our caller) as not being owned by the context.
  9483. if (!nsCachedStyleData::IsReset(aSID)) {
  9484. aContext->AddStyleBit(nsCachedStyleData::GetBitForSID(aSID));
  9485. } else if (HasAnimationData()) {
  9486. // If we have animation data, the struct should be cached on the style
  9487. // context so that we can peek the struct.
  9488. // See comment in AnimValuesStyleRule::MapRuleInfoInto.
  9489. StoreStyleOnContext(aContext, aSID, const_cast<void*>(data));
  9490. }
  9491. return data; // We have a fully specified struct. Just return it.
  9492. }
  9493. }
  9494. if (MOZ_UNLIKELY(!aComputeData)) {
  9495. return nullptr;
  9496. }
  9497. // Nothing is cached. We'll have to delve further and examine our rules.
  9498. data = WalkRuleTree(aSID, aContext);
  9499. MOZ_ASSERT(data, "should have aborted on out-of-memory");
  9500. return data;
  9501. }
  9502. void
  9503. nsRuleNode::GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
  9504. nsCSSValue* aValue)
  9505. {
  9506. for (nsRuleNode* node = this; node; node = node->GetParent()) {
  9507. nsIStyleRule* rule = node->GetRule();
  9508. if (!rule) {
  9509. continue;
  9510. }
  9511. if (rule->GetDiscretelyAnimatedCSSValue(aProperty, aValue)) {
  9512. return;
  9513. }
  9514. }
  9515. }
  9516. /* static */ bool
  9517. nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext* aStyleContext,
  9518. uint32_t ruleTypeMask,
  9519. bool aAuthorColorsAllowed)
  9520. {
  9521. #ifdef MOZ_STYLO
  9522. if (aStyleContext->StyleSource().IsServoComputedValues()) {
  9523. NS_WARNING("stylo: nsRuleNode::HasAuthorSpecifiedRules not implemented");
  9524. return true;
  9525. }
  9526. #endif
  9527. uint32_t inheritBits = 0;
  9528. if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) {
  9529. inheritBits |= NS_STYLE_INHERIT_BIT(Background);
  9530. }
  9531. if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER) {
  9532. inheritBits |= NS_STYLE_INHERIT_BIT(Border);
  9533. }
  9534. if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING) {
  9535. inheritBits |= NS_STYLE_INHERIT_BIT(Padding);
  9536. }
  9537. if (ruleTypeMask & NS_AUTHOR_SPECIFIED_TEXT_SHADOW) {
  9538. inheritBits |= NS_STYLE_INHERIT_BIT(Text);
  9539. }
  9540. // properties in the SIDS, whether or not we care about them
  9541. size_t nprops = 0,
  9542. backgroundOffset, borderOffset, paddingOffset, textShadowOffset;
  9543. // We put the reset properties the start of the nsCSSValue array....
  9544. if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) {
  9545. backgroundOffset = nprops;
  9546. nprops += nsCSSProps::PropertyCountInStruct(eStyleStruct_Background);
  9547. }
  9548. if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER) {
  9549. borderOffset = nprops;
  9550. nprops += nsCSSProps::PropertyCountInStruct(eStyleStruct_Border);
  9551. }
  9552. if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING) {
  9553. paddingOffset = nprops;
  9554. nprops += nsCSSProps::PropertyCountInStruct(eStyleStruct_Padding);
  9555. }
  9556. // ...and the inherited properties at the end of the array.
  9557. size_t inheritedOffset = nprops;
  9558. if (ruleTypeMask & NS_AUTHOR_SPECIFIED_TEXT_SHADOW) {
  9559. textShadowOffset = nprops;
  9560. nprops += nsCSSProps::PropertyCountInStruct(eStyleStruct_Text);
  9561. }
  9562. void* dataStorage = alloca(nprops * sizeof(nsCSSValue));
  9563. AutoCSSValueArray dataArray(dataStorage, nprops);
  9564. /* We're relying on the use of |aStyleContext| not mutating it! */
  9565. nsRuleData ruleData(inheritBits, dataArray.get(),
  9566. aStyleContext->PresContext(), aStyleContext);
  9567. if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) {
  9568. ruleData.mValueOffsets[eStyleStruct_Background] = backgroundOffset;
  9569. }
  9570. if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER) {
  9571. ruleData.mValueOffsets[eStyleStruct_Border] = borderOffset;
  9572. }
  9573. if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING) {
  9574. ruleData.mValueOffsets[eStyleStruct_Padding] = paddingOffset;
  9575. }
  9576. if (ruleTypeMask & NS_AUTHOR_SPECIFIED_TEXT_SHADOW) {
  9577. ruleData.mValueOffsets[eStyleStruct_Text] = textShadowOffset;
  9578. }
  9579. static const nsCSSPropertyID backgroundValues[] = {
  9580. eCSSProperty_background_color,
  9581. eCSSProperty_background_image,
  9582. };
  9583. static const nsCSSPropertyID borderValues[] = {
  9584. eCSSProperty_border_top_color,
  9585. eCSSProperty_border_top_style,
  9586. eCSSProperty_border_top_width,
  9587. eCSSProperty_border_right_color,
  9588. eCSSProperty_border_right_style,
  9589. eCSSProperty_border_right_width,
  9590. eCSSProperty_border_bottom_color,
  9591. eCSSProperty_border_bottom_style,
  9592. eCSSProperty_border_bottom_width,
  9593. eCSSProperty_border_left_color,
  9594. eCSSProperty_border_left_style,
  9595. eCSSProperty_border_left_width,
  9596. eCSSProperty_border_top_left_radius,
  9597. eCSSProperty_border_top_right_radius,
  9598. eCSSProperty_border_bottom_right_radius,
  9599. eCSSProperty_border_bottom_left_radius,
  9600. };
  9601. static const nsCSSPropertyID paddingValues[] = {
  9602. eCSSProperty_padding_top,
  9603. eCSSProperty_padding_right,
  9604. eCSSProperty_padding_bottom,
  9605. eCSSProperty_padding_left,
  9606. };
  9607. static const nsCSSPropertyID textShadowValues[] = {
  9608. eCSSProperty_text_shadow
  9609. };
  9610. // Number of properties we care about
  9611. size_t nValues = 0;
  9612. nsCSSValue* values[MOZ_ARRAY_LENGTH(backgroundValues) +
  9613. MOZ_ARRAY_LENGTH(borderValues) +
  9614. MOZ_ARRAY_LENGTH(paddingValues) +
  9615. MOZ_ARRAY_LENGTH(textShadowValues)];
  9616. nsCSSPropertyID properties[MOZ_ARRAY_LENGTH(backgroundValues) +
  9617. MOZ_ARRAY_LENGTH(borderValues) +
  9618. MOZ_ARRAY_LENGTH(paddingValues) +
  9619. MOZ_ARRAY_LENGTH(textShadowValues)];
  9620. if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) {
  9621. for (uint32_t i = 0, i_end = ArrayLength(backgroundValues);
  9622. i < i_end; ++i) {
  9623. properties[nValues] = backgroundValues[i];
  9624. values[nValues++] = ruleData.ValueFor(backgroundValues[i]);
  9625. }
  9626. }
  9627. if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER) {
  9628. for (uint32_t i = 0, i_end = ArrayLength(borderValues);
  9629. i < i_end; ++i) {
  9630. properties[nValues] = borderValues[i];
  9631. values[nValues++] = ruleData.ValueFor(borderValues[i]);
  9632. }
  9633. }
  9634. if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING) {
  9635. for (uint32_t i = 0, i_end = ArrayLength(paddingValues);
  9636. i < i_end; ++i) {
  9637. properties[nValues] = paddingValues[i];
  9638. values[nValues++] = ruleData.ValueFor(paddingValues[i]);
  9639. }
  9640. }
  9641. if (ruleTypeMask & NS_AUTHOR_SPECIFIED_TEXT_SHADOW) {
  9642. for (uint32_t i = 0, i_end = ArrayLength(textShadowValues);
  9643. i < i_end; ++i) {
  9644. properties[nValues] = textShadowValues[i];
  9645. values[nValues++] = ruleData.ValueFor(textShadowValues[i]);
  9646. }
  9647. }
  9648. nsStyleContext* styleContext = aStyleContext;
  9649. // We need to be careful not to count styles covered up by user-important or
  9650. // UA-important declarations. But we do want to catch explicit inherit
  9651. // styling in those and check our parent style context to see whether we have
  9652. // user styling for those properties. Note that we don't care here about
  9653. // inheritance due to lack of a specified value, since all the properties we
  9654. // care about are reset properties.
  9655. bool haveExplicitUAInherit;
  9656. do {
  9657. haveExplicitUAInherit = false;
  9658. for (nsRuleNode* ruleNode = styleContext->RuleNode(); ruleNode;
  9659. ruleNode = ruleNode->GetParent()) {
  9660. nsIStyleRule *rule = ruleNode->GetRule();
  9661. if (rule) {
  9662. ruleData.mLevel = ruleNode->GetLevel();
  9663. ruleData.mIsImportantRule = ruleNode->IsImportantRule();
  9664. rule->MapRuleInfoInto(&ruleData);
  9665. if (ruleData.mLevel == SheetType::Agent ||
  9666. ruleData.mLevel == SheetType::User) {
  9667. // This is a rule whose effect we want to ignore, so if any of
  9668. // the properties we care about were set, set them to the dummy
  9669. // value that they'll never otherwise get.
  9670. for (uint32_t i = 0; i < nValues; ++i) {
  9671. nsCSSUnit unit = values[i]->GetUnit();
  9672. if (unit != eCSSUnit_Null &&
  9673. unit != eCSSUnit_Dummy &&
  9674. unit != eCSSUnit_DummyInherit) {
  9675. if (unit == eCSSUnit_Inherit ||
  9676. (i >= inheritedOffset && unit == eCSSUnit_Unset)) {
  9677. haveExplicitUAInherit = true;
  9678. values[i]->SetDummyInheritValue();
  9679. } else {
  9680. values[i]->SetDummyValue();
  9681. }
  9682. }
  9683. }
  9684. } else {
  9685. // If any of the values we care about was set by the above rule,
  9686. // we have author style.
  9687. for (uint32_t i = 0; i < nValues; ++i) {
  9688. if (values[i]->GetUnit() != eCSSUnit_Null &&
  9689. values[i]->GetUnit() != eCSSUnit_Dummy && // see above
  9690. values[i]->GetUnit() != eCSSUnit_DummyInherit) {
  9691. // If author colors are not allowed, only claim to have
  9692. // author-specified rules if we're looking at a non-color
  9693. // property or if we're looking at the background color and it's
  9694. // set to transparent. Anything else should get set to a dummy
  9695. // value instead.
  9696. if (aAuthorColorsAllowed ||
  9697. !nsCSSProps::PropHasFlags(properties[i],
  9698. CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED) ||
  9699. (properties[i] == eCSSProperty_background_color &&
  9700. !values[i]->IsNonTransparentColor())) {
  9701. return true;
  9702. }
  9703. values[i]->SetDummyValue();
  9704. }
  9705. }
  9706. }
  9707. }
  9708. }
  9709. if (haveExplicitUAInherit) {
  9710. // reset all the eCSSUnit_Null values to eCSSUnit_Dummy (since they're
  9711. // not styled by the author, or by anyone else), and then reset all the
  9712. // eCSSUnit_DummyInherit values to eCSSUnit_Null (so we will be able to
  9713. // detect them being styled by the author) and move up to our parent
  9714. // style context.
  9715. for (uint32_t i = 0; i < nValues; ++i) {
  9716. if (values[i]->GetUnit() == eCSSUnit_Null) {
  9717. values[i]->SetDummyValue();
  9718. }
  9719. }
  9720. for (uint32_t i = 0; i < nValues; ++i) {
  9721. if (values[i]->GetUnit() == eCSSUnit_DummyInherit) {
  9722. values[i]->Reset();
  9723. }
  9724. }
  9725. styleContext = styleContext->GetParent();
  9726. }
  9727. } while (haveExplicitUAInherit && styleContext);
  9728. return false;
  9729. }
  9730. /* static */ void
  9731. nsRuleNode::ComputePropertiesOverridingAnimation(
  9732. const nsTArray<nsCSSPropertyID>& aProperties,
  9733. nsStyleContext* aStyleContext,
  9734. nsCSSPropertyIDSet& aPropertiesOverridden)
  9735. {
  9736. /*
  9737. * Set up an nsRuleData with all the structs needed for all of the
  9738. * properties in aProperties.
  9739. */
  9740. uint32_t structBits = 0;
  9741. size_t nprops = 0;
  9742. size_t offsets[nsStyleStructID_Length];
  9743. for (size_t propIdx = 0, propEnd = aProperties.Length();
  9744. propIdx < propEnd; ++propIdx) {
  9745. nsCSSPropertyID prop = aProperties[propIdx];
  9746. nsStyleStructID sid = nsCSSProps::kSIDTable[prop];
  9747. uint32_t bit = nsCachedStyleData::GetBitForSID(sid);
  9748. if (!(structBits & bit)) {
  9749. structBits |= bit;
  9750. offsets[sid] = nprops;
  9751. nprops += nsCSSProps::PropertyCountInStruct(sid);
  9752. }
  9753. }
  9754. void* dataStorage = alloca(nprops * sizeof(nsCSSValue));
  9755. AutoCSSValueArray dataArray(dataStorage, nprops);
  9756. // We're relying on the use of |aStyleContext| not mutating it!
  9757. nsRuleData ruleData(structBits, dataArray.get(),
  9758. aStyleContext->PresContext(), aStyleContext);
  9759. for (nsStyleStructID sid = nsStyleStructID(0);
  9760. sid < nsStyleStructID_Length; sid = nsStyleStructID(sid + 1)) {
  9761. if (structBits & nsCachedStyleData::GetBitForSID(sid)) {
  9762. ruleData.mValueOffsets[sid] = offsets[sid];
  9763. }
  9764. }
  9765. /*
  9766. * Actually walk up the rule tree until we're someplace less
  9767. * specific than animations.
  9768. */
  9769. for (nsRuleNode* ruleNode = aStyleContext->RuleNode(); ruleNode;
  9770. ruleNode = ruleNode->GetParent()) {
  9771. nsIStyleRule *rule = ruleNode->GetRule();
  9772. if (rule) {
  9773. ruleData.mLevel = ruleNode->GetLevel();
  9774. ruleData.mIsImportantRule = ruleNode->IsImportantRule();
  9775. // Transitions are the only non-!important level overriding
  9776. // animations in the cascade ordering. They also don't actually
  9777. // override animations, since transitions are suppressed when both
  9778. // are present. And since we might not have called
  9779. // UpdateCascadeResults (which updates when they are suppressed
  9780. // due to the presence of animations for the same element and
  9781. // property) for transitions yet (which will make their
  9782. // MapRuleInfoInto skip the properties that are currently
  9783. // animating), we should skip them explicitly.
  9784. if (ruleData.mLevel == SheetType::Transition) {
  9785. continue;
  9786. }
  9787. if (!ruleData.mIsImportantRule) {
  9788. // We're now equal to or less than the animation level; stop.
  9789. break;
  9790. }
  9791. rule->MapRuleInfoInto(&ruleData);
  9792. }
  9793. }
  9794. /*
  9795. * Fill in which properties were overridden.
  9796. */
  9797. for (size_t propIdx = 0, propEnd = aProperties.Length();
  9798. propIdx < propEnd; ++propIdx) {
  9799. nsCSSPropertyID prop = aProperties[propIdx];
  9800. if (ruleData.ValueFor(prop)->GetUnit() != eCSSUnit_Null) {
  9801. aPropertiesOverridden.AddProperty(prop);
  9802. }
  9803. }
  9804. }
  9805. /* static */
  9806. bool
  9807. nsRuleNode::ComputeColor(const nsCSSValue& aValue, nsPresContext* aPresContext,
  9808. nsStyleContext* aStyleContext, nscolor& aResult)
  9809. {
  9810. MOZ_ASSERT(aValue.GetUnit() != eCSSUnit_Inherit,
  9811. "aValue shouldn't have eCSSUnit_Inherit");
  9812. MOZ_ASSERT(aValue.GetUnit() != eCSSUnit_Initial,
  9813. "aValue shouldn't have eCSSUnit_Initial");
  9814. MOZ_ASSERT(aValue.GetUnit() != eCSSUnit_Unset,
  9815. "aValue shouldn't have eCSSUnit_Unset");
  9816. RuleNodeCacheConditions conditions;
  9817. bool ok = SetColor(aValue, NS_RGB(0, 0, 0), aPresContext, aStyleContext,
  9818. aResult, conditions);
  9819. MOZ_ASSERT(ok || !(aPresContext && aStyleContext));
  9820. return ok;
  9821. }
  9822. /* static */ bool
  9823. nsRuleNode::ParentHasPseudoElementData(nsStyleContext* aContext)
  9824. {
  9825. nsStyleContext* parent = aContext->GetParent();
  9826. return parent && parent->HasPseudoElementData();
  9827. }
  9828. /* static */ void
  9829. nsRuleNode::StoreStyleOnContext(nsStyleContext* aContext,
  9830. nsStyleStructID aSID,
  9831. void* aStruct)
  9832. {
  9833. aContext->AddStyleBit(nsCachedStyleData::GetBitForSID(aSID));
  9834. aContext->SetStyle(aSID, aStruct);
  9835. }
  9836. #ifdef DEBUG
  9837. bool
  9838. nsRuleNode::ContextHasCachedData(nsStyleContext* aContext,
  9839. nsStyleStructID aSID)
  9840. {
  9841. return !!aContext->GetCachedStyleData(aSID);
  9842. }
  9843. #endif