nsStyleStruct.cpp 130 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276
  1. /* -*- Mode: C++; tab-width: 8; 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. * structs that contain the data provided by nsStyleContext, the
  7. * internal API for computed style data for an element
  8. */
  9. #include "nsStyleStruct.h"
  10. #include "nsStyleStructInlines.h"
  11. #include "nsStyleConsts.h"
  12. #include "nsThemeConstants.h"
  13. #include "nsString.h"
  14. #include "nsPresContext.h"
  15. #include "nsIAppShellService.h"
  16. #include "nsIWidget.h"
  17. #include "nsCRTGlue.h"
  18. #include "nsCSSParser.h"
  19. #include "nsCSSProps.h"
  20. #include "nsDeviceContext.h"
  21. #include "nsStyleUtil.h"
  22. #include "nsCOMPtr.h"
  23. #include "nsBidiUtils.h"
  24. #include "nsLayoutUtils.h"
  25. #include "imgIRequest.h"
  26. #include "imgIContainer.h"
  27. #include "CounterStyleManager.h"
  28. #include "mozilla/dom/AnimationEffectReadOnlyBinding.h" // for PlaybackDirection
  29. #include "mozilla/dom/ImageTracker.h"
  30. #include "mozilla/Likely.h"
  31. #include "nsIURI.h"
  32. #include "nsIDocument.h"
  33. #include <algorithm>
  34. using namespace mozilla;
  35. using namespace mozilla::dom;
  36. static_assert((((1 << nsStyleStructID_Length) - 1) &
  37. ~(NS_STYLE_INHERIT_MASK)) == 0,
  38. "Not enough bits in NS_STYLE_INHERIT_MASK");
  39. /* static */ const int32_t nsStyleGridLine::kMinLine;
  40. /* static */ const int32_t nsStyleGridLine::kMaxLine;
  41. static bool
  42. EqualURIs(nsIURI *aURI1, nsIURI *aURI2)
  43. {
  44. bool eq;
  45. return aURI1 == aURI2 || // handle null==null, and optimize
  46. (aURI1 && aURI2 &&
  47. NS_SUCCEEDED(aURI1->Equals(aURI2, &eq)) && // not equal on fail
  48. eq);
  49. }
  50. static bool
  51. DefinitelyEqualURIs(css::URLValueData* aURI1,
  52. css::URLValueData* aURI2)
  53. {
  54. return aURI1 == aURI2 ||
  55. (aURI1 && aURI2 && aURI1->DefinitelyEqualURIs(*aURI2));
  56. }
  57. static bool
  58. DefinitelyEqualURIsAndPrincipal(css::URLValueData* aURI1,
  59. css::URLValueData* aURI2)
  60. {
  61. return aURI1 == aURI2 ||
  62. (aURI1 && aURI2 && aURI1->DefinitelyEqualURIsAndPrincipal(*aURI2));
  63. }
  64. static bool
  65. EqualImages(imgIRequest *aImage1, imgIRequest* aImage2)
  66. {
  67. if (aImage1 == aImage2) {
  68. return true;
  69. }
  70. if (!aImage1 || !aImage2) {
  71. return false;
  72. }
  73. nsCOMPtr<nsIURI> uri1, uri2;
  74. aImage1->GetURI(getter_AddRefs(uri1));
  75. aImage2->GetURI(getter_AddRefs(uri2));
  76. return EqualURIs(uri1, uri2);
  77. }
  78. static bool
  79. DefinitelyEqualImages(nsStyleImageRequest* aRequest1,
  80. nsStyleImageRequest* aRequest2)
  81. {
  82. if (aRequest1 == aRequest2) {
  83. return true;
  84. }
  85. if (!aRequest1 || !aRequest2) {
  86. return false;
  87. }
  88. return aRequest1->DefinitelyEquals(*aRequest2);
  89. }
  90. // A nullsafe wrapper for strcmp. We depend on null-safety.
  91. static int
  92. safe_strcmp(const char16_t* a, const char16_t* b)
  93. {
  94. if (!a || !b) {
  95. return (int)(a - b);
  96. }
  97. return NS_strcmp(a, b);
  98. }
  99. int32_t
  100. StyleStructContext::AppUnitsPerDevPixel()
  101. {
  102. return DeviceContext()->AppUnitsPerDevPixel();
  103. }
  104. nsDeviceContext*
  105. StyleStructContext::HackilyFindSomeDeviceContext()
  106. {
  107. nsCOMPtr<nsIAppShellService> appShell(do_GetService("@mozilla.org/appshell/appShellService;1"));
  108. MOZ_ASSERT(appShell);
  109. nsCOMPtr<mozIDOMWindowProxy> win;
  110. appShell->GetHiddenDOMWindow(getter_AddRefs(win));
  111. return nsLayoutUtils::GetDeviceContextForScreenInfo(static_cast<nsPIDOMWindowOuter*>(win.get()));
  112. }
  113. static bool AreShadowArraysEqual(nsCSSShadowArray* lhs, nsCSSShadowArray* rhs);
  114. // --------------------
  115. // nsStyleFont
  116. //
  117. nsStyleFont::nsStyleFont(const nsFont& aFont, StyleStructContext aContext)
  118. : mFont(aFont)
  119. , mSize(nsStyleFont::ZoomText(aContext, mFont.size))
  120. , mGenericID(kGenericFont_NONE)
  121. , mScriptLevel(0)
  122. , mMathVariant(NS_MATHML_MATHVARIANT_NONE)
  123. , mMathDisplay(NS_MATHML_DISPLAYSTYLE_INLINE)
  124. , mMinFontSizeRatio(100) // 100%
  125. , mExplicitLanguage(false)
  126. , mAllowZoom(true)
  127. , mScriptUnconstrainedSize(mSize)
  128. , mScriptMinSize(nsPresContext::CSSTwipsToAppUnits(
  129. NS_POINTS_TO_TWIPS(NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT)))
  130. , mScriptSizeMultiplier(NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER)
  131. , mLanguage(GetLanguage(aContext))
  132. {
  133. MOZ_COUNT_CTOR(nsStyleFont);
  134. mFont.size = mSize;
  135. }
  136. nsStyleFont::nsStyleFont(const nsStyleFont& aSrc)
  137. : mFont(aSrc.mFont)
  138. , mSize(aSrc.mSize)
  139. , mGenericID(aSrc.mGenericID)
  140. , mScriptLevel(aSrc.mScriptLevel)
  141. , mMathVariant(aSrc.mMathVariant)
  142. , mMathDisplay(aSrc.mMathDisplay)
  143. , mMinFontSizeRatio(aSrc.mMinFontSizeRatio)
  144. , mExplicitLanguage(aSrc.mExplicitLanguage)
  145. , mAllowZoom(aSrc.mAllowZoom)
  146. , mScriptUnconstrainedSize(aSrc.mScriptUnconstrainedSize)
  147. , mScriptMinSize(aSrc.mScriptMinSize)
  148. , mScriptSizeMultiplier(aSrc.mScriptSizeMultiplier)
  149. , mLanguage(aSrc.mLanguage)
  150. {
  151. MOZ_COUNT_CTOR(nsStyleFont);
  152. }
  153. nsStyleFont::nsStyleFont(StyleStructContext aContext)
  154. : nsStyleFont(*aContext.GetDefaultFont(kPresContext_DefaultVariableFont_ID),
  155. aContext)
  156. {
  157. }
  158. void
  159. nsStyleFont::Destroy(nsPresContext* aContext) {
  160. this->~nsStyleFont();
  161. aContext->PresShell()->
  162. FreeByObjectID(eArenaObjectID_nsStyleFont, this);
  163. }
  164. void
  165. nsStyleFont::EnableZoom(nsPresContext* aContext, bool aEnable)
  166. {
  167. if (mAllowZoom == aEnable) {
  168. return;
  169. }
  170. mAllowZoom = aEnable;
  171. if (mAllowZoom) {
  172. mSize = nsStyleFont::ZoomText(aContext, mSize);
  173. mFont.size = nsStyleFont::ZoomText(aContext, mFont.size);
  174. mScriptUnconstrainedSize =
  175. nsStyleFont::ZoomText(aContext, mScriptUnconstrainedSize);
  176. } else {
  177. mSize = nsStyleFont::UnZoomText(aContext, mSize);
  178. mFont.size = nsStyleFont::UnZoomText(aContext, mFont.size);
  179. mScriptUnconstrainedSize =
  180. nsStyleFont::UnZoomText(aContext, mScriptUnconstrainedSize);
  181. }
  182. }
  183. nsChangeHint
  184. nsStyleFont::CalcDifference(const nsStyleFont& aNewData) const
  185. {
  186. MOZ_ASSERT(mAllowZoom == aNewData.mAllowZoom,
  187. "expected mAllowZoom to be the same on both nsStyleFonts");
  188. if (mSize != aNewData.mSize ||
  189. mFont != aNewData.mFont ||
  190. mLanguage != aNewData.mLanguage ||
  191. mExplicitLanguage != aNewData.mExplicitLanguage ||
  192. mMathVariant != aNewData.mMathVariant ||
  193. mMathDisplay != aNewData.mMathDisplay ||
  194. mMinFontSizeRatio != aNewData.mMinFontSizeRatio) {
  195. return NS_STYLE_HINT_REFLOW;
  196. }
  197. // XXX Should any of these cause a non-nsChangeHint_NeutralChange change?
  198. if (mGenericID != aNewData.mGenericID ||
  199. mScriptLevel != aNewData.mScriptLevel ||
  200. mScriptUnconstrainedSize != aNewData.mScriptUnconstrainedSize ||
  201. mScriptMinSize != aNewData.mScriptMinSize ||
  202. mScriptSizeMultiplier != aNewData.mScriptSizeMultiplier) {
  203. return nsChangeHint_NeutralChange;
  204. }
  205. return nsChangeHint(0);
  206. }
  207. /* static */ nscoord
  208. nsStyleFont::ZoomText(StyleStructContext aContext, nscoord aSize)
  209. {
  210. // aSize can be negative (e.g.: calc(-1px)) so we can't assert that here.
  211. // The caller is expected deal with that.
  212. return NSToCoordTruncClamped(float(aSize) * aContext.TextZoom());
  213. }
  214. /* static */ nscoord
  215. nsStyleFont::UnZoomText(nsPresContext *aPresContext, nscoord aSize)
  216. {
  217. // aSize can be negative (e.g.: calc(-1px)) so we can't assert that here.
  218. // The caller is expected deal with that.
  219. return NSToCoordTruncClamped(float(aSize) / aPresContext->TextZoom());
  220. }
  221. /* static */ already_AddRefed<nsIAtom>
  222. nsStyleFont::GetLanguage(StyleStructContext aContext)
  223. {
  224. RefPtr<nsIAtom> language = aContext.GetContentLanguage();
  225. if (!language) {
  226. // we didn't find a (usable) Content-Language, so we fall back
  227. // to whatever the presContext guessed from the charset
  228. // NOTE this should not be used elsewhere, because we want websites
  229. // to use UTF-8 with proper language tag, instead of relying on
  230. // deriving language from charset. See bug 1040668 comment 67.
  231. language = aContext.GetLanguageFromCharset();
  232. }
  233. return language.forget();
  234. }
  235. static nscoord
  236. CalcCoord(const nsStyleCoord& aCoord, const nscoord* aEnumTable, int32_t aNumEnums)
  237. {
  238. if (aCoord.GetUnit() == eStyleUnit_Enumerated) {
  239. MOZ_ASSERT(aEnumTable, "must have enum table");
  240. int32_t value = aCoord.GetIntValue();
  241. if (0 <= value && value < aNumEnums) {
  242. return aEnumTable[aCoord.GetIntValue()];
  243. }
  244. NS_NOTREACHED("unexpected enum value");
  245. return 0;
  246. }
  247. MOZ_ASSERT(aCoord.ConvertsToLength(), "unexpected unit");
  248. return nsRuleNode::ComputeCoordPercentCalc(aCoord, 0);
  249. }
  250. nsStyleMargin::nsStyleMargin(StyleStructContext aContext)
  251. {
  252. MOZ_COUNT_CTOR(nsStyleMargin);
  253. nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
  254. NS_FOR_CSS_SIDES(side) {
  255. mMargin.Set(side, zero);
  256. }
  257. }
  258. nsStyleMargin::nsStyleMargin(const nsStyleMargin& aSrc)
  259. : mMargin(aSrc.mMargin)
  260. {
  261. MOZ_COUNT_CTOR(nsStyleMargin);
  262. }
  263. void
  264. nsStyleMargin::Destroy(nsPresContext* aContext) {
  265. this->~nsStyleMargin();
  266. aContext->PresShell()->
  267. FreeByObjectID(eArenaObjectID_nsStyleMargin, this);
  268. }
  269. nsChangeHint
  270. nsStyleMargin::CalcDifference(const nsStyleMargin& aNewData) const
  271. {
  272. if (mMargin == aNewData.mMargin) {
  273. return nsChangeHint(0);
  274. }
  275. // Margin differences can't affect descendant intrinsic sizes and
  276. // don't need to force children to reflow.
  277. return nsChangeHint_NeedReflow |
  278. nsChangeHint_ReflowChangesSizeOrPosition |
  279. nsChangeHint_ClearAncestorIntrinsics;
  280. }
  281. nsStylePadding::nsStylePadding(StyleStructContext aContext)
  282. {
  283. MOZ_COUNT_CTOR(nsStylePadding);
  284. nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
  285. NS_FOR_CSS_SIDES(side) {
  286. mPadding.Set(side, zero);
  287. }
  288. }
  289. nsStylePadding::nsStylePadding(const nsStylePadding& aSrc)
  290. : mPadding(aSrc.mPadding)
  291. {
  292. MOZ_COUNT_CTOR(nsStylePadding);
  293. }
  294. void
  295. nsStylePadding::Destroy(nsPresContext* aContext) {
  296. this->~nsStylePadding();
  297. aContext->PresShell()->
  298. FreeByObjectID(eArenaObjectID_nsStylePadding, this);
  299. }
  300. nsChangeHint
  301. nsStylePadding::CalcDifference(const nsStylePadding& aNewData) const
  302. {
  303. if (mPadding == aNewData.mPadding) {
  304. return nsChangeHint(0);
  305. }
  306. // Padding differences can't affect descendant intrinsic sizes, but do need
  307. // to force children to reflow so that we can reposition them, since their
  308. // offsets are from our frame bounds but our content rect's position within
  309. // those bounds is moving.
  310. // FIXME: It would be good to return a weaker hint here that doesn't
  311. // force reflow of all descendants, but the hint would need to force
  312. // reflow of the frame's children (see how
  313. // ReflowInput::InitResizeFlags initializes the inline-resize flag).
  314. return NS_STYLE_HINT_REFLOW & ~nsChangeHint_ClearDescendantIntrinsics;
  315. }
  316. nsStyleBorder::nsStyleBorder(StyleStructContext aContext)
  317. : mBorderColors(nullptr)
  318. , mBorderImageFill(NS_STYLE_BORDER_IMAGE_SLICE_NOFILL)
  319. , mBorderImageRepeatH(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH)
  320. , mBorderImageRepeatV(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH)
  321. , mFloatEdge(StyleFloatEdge::ContentBox)
  322. , mBoxDecorationBreak(StyleBoxDecorationBreak::Slice)
  323. , mComputedBorder(0, 0, 0, 0)
  324. {
  325. MOZ_COUNT_CTOR(nsStyleBorder);
  326. NS_FOR_CSS_HALF_CORNERS (corner) {
  327. mBorderRadius.Set(corner, nsStyleCoord(0, nsStyleCoord::CoordConstructor));
  328. }
  329. nscoord medium =
  330. (StaticPresData::Get()->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM];
  331. NS_FOR_CSS_SIDES(side) {
  332. mBorderImageSlice.Set(side, nsStyleCoord(1.0f, eStyleUnit_Percent));
  333. mBorderImageWidth.Set(side, nsStyleCoord(1.0f, eStyleUnit_Factor));
  334. mBorderImageOutset.Set(side, nsStyleCoord(0.0f, eStyleUnit_Factor));
  335. mBorder.Side(side) = medium;
  336. mBorderStyle[side] = NS_STYLE_BORDER_STYLE_NONE;
  337. mBorderColor[side] = StyleComplexColor::CurrentColor();
  338. }
  339. mTwipsPerPixel = aContext.DevPixelsToAppUnits(1);
  340. }
  341. nsBorderColors::~nsBorderColors()
  342. {
  343. NS_CSS_DELETE_LIST_MEMBER(nsBorderColors, this, mNext);
  344. }
  345. nsBorderColors*
  346. nsBorderColors::Clone(bool aDeep) const
  347. {
  348. nsBorderColors* result = new nsBorderColors(mColor);
  349. if (MOZ_UNLIKELY(!result)) {
  350. return result;
  351. }
  352. if (aDeep) {
  353. NS_CSS_CLONE_LIST_MEMBER(nsBorderColors, this, mNext, result, (false));
  354. }
  355. return result;
  356. }
  357. nsStyleBorder::nsStyleBorder(const nsStyleBorder& aSrc)
  358. : mBorderColors(nullptr)
  359. , mBorderRadius(aSrc.mBorderRadius)
  360. , mBorderImageSource(aSrc.mBorderImageSource)
  361. , mBorderImageSlice(aSrc.mBorderImageSlice)
  362. , mBorderImageWidth(aSrc.mBorderImageWidth)
  363. , mBorderImageOutset(aSrc.mBorderImageOutset)
  364. , mBorderImageFill(aSrc.mBorderImageFill)
  365. , mBorderImageRepeatH(aSrc.mBorderImageRepeatH)
  366. , mBorderImageRepeatV(aSrc.mBorderImageRepeatV)
  367. , mFloatEdge(aSrc.mFloatEdge)
  368. , mBoxDecorationBreak(aSrc.mBoxDecorationBreak)
  369. , mComputedBorder(aSrc.mComputedBorder)
  370. , mBorder(aSrc.mBorder)
  371. , mTwipsPerPixel(aSrc.mTwipsPerPixel)
  372. {
  373. MOZ_COUNT_CTOR(nsStyleBorder);
  374. if (aSrc.mBorderColors) {
  375. EnsureBorderColors();
  376. for (int32_t i = 0; i < 4; i++) {
  377. if (aSrc.mBorderColors[i]) {
  378. mBorderColors[i] = aSrc.mBorderColors[i]->Clone();
  379. } else {
  380. mBorderColors[i] = nullptr;
  381. }
  382. }
  383. }
  384. NS_FOR_CSS_SIDES(side) {
  385. mBorderStyle[side] = aSrc.mBorderStyle[side];
  386. mBorderColor[side] = aSrc.mBorderColor[side];
  387. }
  388. }
  389. nsStyleBorder::~nsStyleBorder()
  390. {
  391. MOZ_COUNT_DTOR(nsStyleBorder);
  392. if (mBorderColors) {
  393. for (int32_t i = 0; i < 4; i++) {
  394. delete mBorderColors[i];
  395. }
  396. delete [] mBorderColors;
  397. }
  398. }
  399. void
  400. nsStyleBorder::FinishStyle(nsPresContext* aPresContext)
  401. {
  402. MOZ_ASSERT(NS_IsMainThread());
  403. MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
  404. mBorderImageSource.ResolveImage(aPresContext);
  405. }
  406. nsMargin
  407. nsStyleBorder::GetImageOutset() const
  408. {
  409. // We don't check whether there is a border-image (which is OK since
  410. // the initial values yields 0 outset) so that we don't have to
  411. // reflow to update overflow areas when an image loads.
  412. nsMargin outset;
  413. NS_FOR_CSS_SIDES(s) {
  414. nsStyleCoord coord = mBorderImageOutset.Get(s);
  415. nscoord value;
  416. switch (coord.GetUnit()) {
  417. case eStyleUnit_Coord:
  418. value = coord.GetCoordValue();
  419. break;
  420. case eStyleUnit_Factor:
  421. value = coord.GetFactorValue() * mComputedBorder.Side(s);
  422. break;
  423. default:
  424. NS_NOTREACHED("unexpected CSS unit for image outset");
  425. value = 0;
  426. break;
  427. }
  428. outset.Side(s) = value;
  429. }
  430. return outset;
  431. }
  432. void
  433. nsStyleBorder::Destroy(nsPresContext* aContext)
  434. {
  435. this->~nsStyleBorder();
  436. aContext->PresShell()->
  437. FreeByObjectID(eArenaObjectID_nsStyleBorder, this);
  438. }
  439. nsChangeHint
  440. nsStyleBorder::CalcDifference(const nsStyleBorder& aNewData) const
  441. {
  442. // FIXME: XXXbz: As in nsStylePadding::CalcDifference, many of these
  443. // differences should not need to clear descendant intrinsics.
  444. // FIXME: It would be good to return a weaker hint for the
  445. // GetComputedBorder() differences (and perhaps others) that doesn't
  446. // force reflow of all descendants, but the hint would need to force
  447. // reflow of the frame's children (see how
  448. // ReflowInput::InitResizeFlags initializes the inline-resize flag).
  449. if (mTwipsPerPixel != aNewData.mTwipsPerPixel ||
  450. GetComputedBorder() != aNewData.GetComputedBorder() ||
  451. mFloatEdge != aNewData.mFloatEdge ||
  452. mBorderImageOutset != aNewData.mBorderImageOutset ||
  453. mBoxDecorationBreak != aNewData.mBoxDecorationBreak) {
  454. return NS_STYLE_HINT_REFLOW;
  455. }
  456. NS_FOR_CSS_SIDES(ix) {
  457. // See the explanation in nsChangeHint.h of
  458. // nsChangeHint_BorderStyleNoneChange .
  459. // Furthermore, even though we know *this* side is 0 width, just
  460. // assume a repaint hint for some other change rather than bother
  461. // tracking this result through the rest of the function.
  462. if (HasVisibleStyle(ix) != aNewData.HasVisibleStyle(ix)) {
  463. return nsChangeHint_RepaintFrame |
  464. nsChangeHint_BorderStyleNoneChange;
  465. }
  466. }
  467. // Note that mBorderStyle stores not only the border style but also
  468. // color-related flags. Given that we've already done an mComputedBorder
  469. // comparison, border-style differences can only lead to a repaint hint. So
  470. // it's OK to just compare the values directly -- if either the actual
  471. // style or the color flags differ we want to repaint.
  472. NS_FOR_CSS_SIDES(ix) {
  473. if (mBorderStyle[ix] != aNewData.mBorderStyle[ix] ||
  474. mBorderColor[ix] != aNewData.mBorderColor[ix]) {
  475. return nsChangeHint_RepaintFrame;
  476. }
  477. }
  478. if (mBorderRadius != aNewData.mBorderRadius ||
  479. !mBorderColors != !aNewData.mBorderColors) {
  480. return nsChangeHint_RepaintFrame;
  481. }
  482. if (IsBorderImageLoaded() || aNewData.IsBorderImageLoaded()) {
  483. if (mBorderImageSource != aNewData.mBorderImageSource ||
  484. mBorderImageRepeatH != aNewData.mBorderImageRepeatH ||
  485. mBorderImageRepeatV != aNewData.mBorderImageRepeatV ||
  486. mBorderImageSlice != aNewData.mBorderImageSlice ||
  487. mBorderImageFill != aNewData.mBorderImageFill ||
  488. mBorderImageWidth != aNewData.mBorderImageWidth ||
  489. mBorderImageOutset != aNewData.mBorderImageOutset) {
  490. return nsChangeHint_RepaintFrame;
  491. }
  492. }
  493. // Note that at this point if mBorderColors is non-null so is
  494. // aNewData.mBorderColors
  495. if (mBorderColors) {
  496. NS_FOR_CSS_SIDES(ix) {
  497. if (!nsBorderColors::Equal(mBorderColors[ix],
  498. aNewData.mBorderColors[ix])) {
  499. return nsChangeHint_RepaintFrame;
  500. }
  501. }
  502. }
  503. // mBorder is the specified border value. Changes to this don't
  504. // need any change processing, since we operate on the computed
  505. // border values instead.
  506. if (mBorder != aNewData.mBorder) {
  507. return nsChangeHint_NeutralChange;
  508. }
  509. return nsChangeHint(0);
  510. }
  511. nsStyleOutline::nsStyleOutline(StyleStructContext aContext)
  512. : mOutlineWidth(NS_STYLE_BORDER_WIDTH_MEDIUM, eStyleUnit_Enumerated)
  513. , mOutlineOffset(0)
  514. , mOutlineColor(StyleComplexColor::CurrentColor())
  515. , mOutlineStyle(NS_STYLE_BORDER_STYLE_NONE)
  516. , mActualOutlineWidth(0)
  517. , mTwipsPerPixel(aContext.DevPixelsToAppUnits(1))
  518. {
  519. MOZ_COUNT_CTOR(nsStyleOutline);
  520. // spacing values not inherited
  521. nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
  522. NS_FOR_CSS_HALF_CORNERS(corner) {
  523. mOutlineRadius.Set(corner, zero);
  524. }
  525. }
  526. nsStyleOutline::nsStyleOutline(const nsStyleOutline& aSrc)
  527. : mOutlineRadius(aSrc.mOutlineRadius)
  528. , mOutlineWidth(aSrc.mOutlineWidth)
  529. , mOutlineOffset(aSrc.mOutlineOffset)
  530. , mOutlineColor(aSrc.mOutlineColor)
  531. , mOutlineStyle(aSrc.mOutlineStyle)
  532. , mActualOutlineWidth(aSrc.mActualOutlineWidth)
  533. , mTwipsPerPixel(aSrc.mTwipsPerPixel)
  534. {
  535. MOZ_COUNT_CTOR(nsStyleOutline);
  536. }
  537. void
  538. nsStyleOutline::RecalcData()
  539. {
  540. if (NS_STYLE_BORDER_STYLE_NONE == mOutlineStyle) {
  541. mActualOutlineWidth = 0;
  542. } else {
  543. MOZ_ASSERT(mOutlineWidth.ConvertsToLength() ||
  544. mOutlineWidth.GetUnit() == eStyleUnit_Enumerated);
  545. // Clamp negative calc() to 0.
  546. mActualOutlineWidth =
  547. std::max(CalcCoord(mOutlineWidth,
  548. StaticPresData::Get()->GetBorderWidthTable(), 3), 0);
  549. mActualOutlineWidth =
  550. NS_ROUND_BORDER_TO_PIXELS(mActualOutlineWidth, mTwipsPerPixel);
  551. }
  552. }
  553. nsChangeHint
  554. nsStyleOutline::CalcDifference(const nsStyleOutline& aNewData) const
  555. {
  556. if (mActualOutlineWidth != aNewData.mActualOutlineWidth ||
  557. (mActualOutlineWidth > 0 &&
  558. mOutlineOffset != aNewData.mOutlineOffset)) {
  559. return nsChangeHint_UpdateOverflow |
  560. nsChangeHint_SchedulePaint;
  561. }
  562. if (mOutlineStyle != aNewData.mOutlineStyle ||
  563. mOutlineColor != aNewData.mOutlineColor ||
  564. mOutlineRadius != aNewData.mOutlineRadius) {
  565. if (mActualOutlineWidth > 0) {
  566. return nsChangeHint_RepaintFrame;
  567. }
  568. return nsChangeHint_NeutralChange;
  569. }
  570. if (mOutlineWidth != aNewData.mOutlineWidth ||
  571. mOutlineOffset != aNewData.mOutlineOffset ||
  572. mTwipsPerPixel != aNewData.mTwipsPerPixel) {
  573. return nsChangeHint_NeutralChange;
  574. }
  575. return nsChangeHint(0);
  576. }
  577. // --------------------
  578. // nsStyleList
  579. //
  580. nsStyleList::nsStyleList(StyleStructContext aContext)
  581. : mListStylePosition(NS_STYLE_LIST_STYLE_POSITION_OUTSIDE)
  582. , mCounterStyle(aContext.BuildCounterStyle(NS_LITERAL_STRING("disc")))
  583. {
  584. MOZ_COUNT_CTOR(nsStyleList);
  585. SetQuotesInitial();
  586. }
  587. nsStyleList::~nsStyleList()
  588. {
  589. MOZ_COUNT_DTOR(nsStyleList);
  590. }
  591. nsStyleList::nsStyleList(const nsStyleList& aSource)
  592. : mListStylePosition(aSource.mListStylePosition)
  593. , mListStyleImage(aSource.mListStyleImage)
  594. , mCounterStyle(aSource.mCounterStyle)
  595. , mQuotes(aSource.mQuotes)
  596. , mImageRegion(aSource.mImageRegion)
  597. {
  598. MOZ_COUNT_CTOR(nsStyleList);
  599. }
  600. void
  601. nsStyleList::FinishStyle(nsPresContext* aPresContext)
  602. {
  603. MOZ_ASSERT(NS_IsMainThread());
  604. MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
  605. if (mListStyleImage && !mListStyleImage->IsResolved()) {
  606. mListStyleImage->Resolve(aPresContext);
  607. }
  608. }
  609. void
  610. nsStyleList::SetQuotesInherit(const nsStyleList* aOther)
  611. {
  612. mQuotes = aOther->mQuotes;
  613. }
  614. void
  615. nsStyleList::SetQuotesInitial()
  616. {
  617. if (!sInitialQuotes) {
  618. // The initial value for quotes is the en-US typographic convention:
  619. // outermost are LEFT and RIGHT DOUBLE QUOTATION MARK, alternating
  620. // with LEFT and RIGHT SINGLE QUOTATION MARK.
  621. static const char16_t initialQuotes[8] = {
  622. 0x201C, 0, 0x201D, 0, 0x2018, 0, 0x2019, 0
  623. };
  624. sInitialQuotes = new nsStyleQuoteValues;
  625. sInitialQuotes->mQuotePairs.AppendElement(
  626. std::make_pair(nsDependentString(&initialQuotes[0], 1),
  627. nsDependentString(&initialQuotes[2], 1)));
  628. sInitialQuotes->mQuotePairs.AppendElement(
  629. std::make_pair(nsDependentString(&initialQuotes[4], 1),
  630. nsDependentString(&initialQuotes[6], 1)));
  631. }
  632. mQuotes = sInitialQuotes;
  633. }
  634. void
  635. nsStyleList::SetQuotesNone()
  636. {
  637. if (!sNoneQuotes) {
  638. sNoneQuotes = new nsStyleQuoteValues;
  639. }
  640. mQuotes = sNoneQuotes;
  641. }
  642. void
  643. nsStyleList::SetQuotes(nsStyleQuoteValues::QuotePairArray&& aValues)
  644. {
  645. mQuotes = new nsStyleQuoteValues;
  646. mQuotes->mQuotePairs = Move(aValues);
  647. }
  648. const nsStyleQuoteValues::QuotePairArray&
  649. nsStyleList::GetQuotePairs() const
  650. {
  651. return mQuotes->mQuotePairs;
  652. }
  653. nsChangeHint
  654. nsStyleList::CalcDifference(const nsStyleList& aNewData) const
  655. {
  656. // If the quotes implementation is ever going to change we might not need
  657. // a framechange here and a reflow should be sufficient. See bug 35768.
  658. if (mQuotes != aNewData.mQuotes &&
  659. (mQuotes || aNewData.mQuotes) &&
  660. GetQuotePairs() != aNewData.GetQuotePairs()) {
  661. return nsChangeHint_ReconstructFrame;
  662. }
  663. if (mListStylePosition != aNewData.mListStylePosition) {
  664. return nsChangeHint_ReconstructFrame;
  665. }
  666. if (DefinitelyEqualImages(mListStyleImage, aNewData.mListStyleImage) &&
  667. mCounterStyle == aNewData.mCounterStyle) {
  668. if (mImageRegion.IsEqualInterior(aNewData.mImageRegion)) {
  669. return nsChangeHint(0);
  670. }
  671. if (mImageRegion.width == aNewData.mImageRegion.width &&
  672. mImageRegion.height == aNewData.mImageRegion.height) {
  673. return NS_STYLE_HINT_VISUAL;
  674. }
  675. }
  676. return NS_STYLE_HINT_REFLOW;
  677. }
  678. StaticRefPtr<nsStyleQuoteValues>
  679. nsStyleList::sInitialQuotes;
  680. StaticRefPtr<nsStyleQuoteValues>
  681. nsStyleList::sNoneQuotes;
  682. // --------------------
  683. // nsStyleXUL
  684. //
  685. nsStyleXUL::nsStyleXUL(StyleStructContext aContext)
  686. : mBoxFlex(0.0f)
  687. , mBoxOrdinal(1)
  688. , mBoxAlign(StyleBoxAlign::Stretch)
  689. , mBoxDirection(StyleBoxDirection::Normal)
  690. , mBoxOrient(StyleBoxOrient::Horizontal)
  691. , mBoxPack(StyleBoxPack::Start)
  692. , mStretchStack(true)
  693. {
  694. MOZ_COUNT_CTOR(nsStyleXUL);
  695. }
  696. nsStyleXUL::~nsStyleXUL()
  697. {
  698. MOZ_COUNT_DTOR(nsStyleXUL);
  699. }
  700. nsStyleXUL::nsStyleXUL(const nsStyleXUL& aSource)
  701. : mBoxFlex(aSource.mBoxFlex)
  702. , mBoxOrdinal(aSource.mBoxOrdinal)
  703. , mBoxAlign(aSource.mBoxAlign)
  704. , mBoxDirection(aSource.mBoxDirection)
  705. , mBoxOrient(aSource.mBoxOrient)
  706. , mBoxPack(aSource.mBoxPack)
  707. , mStretchStack(aSource.mStretchStack)
  708. {
  709. MOZ_COUNT_CTOR(nsStyleXUL);
  710. }
  711. nsChangeHint
  712. nsStyleXUL::CalcDifference(const nsStyleXUL& aNewData) const
  713. {
  714. if (mBoxAlign == aNewData.mBoxAlign &&
  715. mBoxDirection == aNewData.mBoxDirection &&
  716. mBoxFlex == aNewData.mBoxFlex &&
  717. mBoxOrient == aNewData.mBoxOrient &&
  718. mBoxPack == aNewData.mBoxPack &&
  719. mBoxOrdinal == aNewData.mBoxOrdinal &&
  720. mStretchStack == aNewData.mStretchStack) {
  721. return nsChangeHint(0);
  722. }
  723. if (mBoxOrdinal != aNewData.mBoxOrdinal) {
  724. return nsChangeHint_ReconstructFrame;
  725. }
  726. return NS_STYLE_HINT_REFLOW;
  727. }
  728. // --------------------
  729. // nsStyleColumn
  730. //
  731. /* static */ const uint32_t nsStyleColumn::kMaxColumnCount;
  732. nsStyleColumn::nsStyleColumn(StyleStructContext aContext)
  733. : mColumnCount(NS_STYLE_COLUMN_COUNT_AUTO)
  734. , mColumnWidth(eStyleUnit_Auto)
  735. , mColumnGap(eStyleUnit_Normal)
  736. , mColumnRuleColor(StyleComplexColor::CurrentColor())
  737. , mColumnRuleStyle(NS_STYLE_BORDER_STYLE_NONE)
  738. , mColumnFill(NS_STYLE_COLUMN_FILL_BALANCE)
  739. , mColumnRuleWidth((StaticPresData::Get()
  740. ->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM])
  741. , mTwipsPerPixel(aContext.AppUnitsPerDevPixel())
  742. {
  743. MOZ_COUNT_CTOR(nsStyleColumn);
  744. }
  745. nsStyleColumn::~nsStyleColumn()
  746. {
  747. MOZ_COUNT_DTOR(nsStyleColumn);
  748. }
  749. nsStyleColumn::nsStyleColumn(const nsStyleColumn& aSource)
  750. : mColumnCount(aSource.mColumnCount)
  751. , mColumnWidth(aSource.mColumnWidth)
  752. , mColumnGap(aSource.mColumnGap)
  753. , mColumnRuleColor(aSource.mColumnRuleColor)
  754. , mColumnRuleStyle(aSource.mColumnRuleStyle)
  755. , mColumnFill(aSource.mColumnFill)
  756. , mColumnRuleWidth(aSource.mColumnRuleWidth)
  757. , mTwipsPerPixel(aSource.mTwipsPerPixel)
  758. {
  759. MOZ_COUNT_CTOR(nsStyleColumn);
  760. }
  761. nsChangeHint
  762. nsStyleColumn::CalcDifference(const nsStyleColumn& aNewData) const
  763. {
  764. if ((mColumnWidth.GetUnit() == eStyleUnit_Auto)
  765. != (aNewData.mColumnWidth.GetUnit() == eStyleUnit_Auto) ||
  766. mColumnCount != aNewData.mColumnCount) {
  767. // We force column count changes to do a reframe, because it's tricky to handle
  768. // some edge cases where the column count gets smaller and content overflows.
  769. // XXX not ideal
  770. return nsChangeHint_ReconstructFrame;
  771. }
  772. if (mColumnWidth != aNewData.mColumnWidth ||
  773. mColumnGap != aNewData.mColumnGap ||
  774. mColumnFill != aNewData.mColumnFill) {
  775. return NS_STYLE_HINT_REFLOW;
  776. }
  777. if (GetComputedColumnRuleWidth() != aNewData.GetComputedColumnRuleWidth() ||
  778. mColumnRuleStyle != aNewData.mColumnRuleStyle ||
  779. mColumnRuleColor != aNewData.mColumnRuleColor) {
  780. return NS_STYLE_HINT_VISUAL;
  781. }
  782. // XXX Is it right that we never check mTwipsPerPixel to return a
  783. // non-nsChangeHint_NeutralChange hint?
  784. if (mColumnRuleWidth != aNewData.mColumnRuleWidth ||
  785. mTwipsPerPixel != aNewData.mTwipsPerPixel) {
  786. return nsChangeHint_NeutralChange;
  787. }
  788. return nsChangeHint(0);
  789. }
  790. // --------------------
  791. // nsStyleSVG
  792. //
  793. nsStyleSVG::nsStyleSVG(StyleStructContext aContext)
  794. : mFill(eStyleSVGPaintType_Color) // Will be initialized to NS_RGB(0, 0, 0)
  795. , mStroke(eStyleSVGPaintType_None)
  796. , mStrokeDashoffset(0, nsStyleCoord::CoordConstructor)
  797. , mStrokeWidth(nsPresContext::CSSPixelsToAppUnits(1), nsStyleCoord::CoordConstructor)
  798. , mFillOpacity(1.0f)
  799. , mStrokeMiterlimit(4.0f)
  800. , mStrokeOpacity(1.0f)
  801. , mClipRule(StyleFillRule::Nonzero)
  802. , mColorInterpolation(NS_STYLE_COLOR_INTERPOLATION_SRGB)
  803. , mColorInterpolationFilters(NS_STYLE_COLOR_INTERPOLATION_LINEARRGB)
  804. , mFillRule(StyleFillRule::Nonzero)
  805. , mPaintOrder(NS_STYLE_PAINT_ORDER_NORMAL)
  806. , mShapeRendering(NS_STYLE_SHAPE_RENDERING_AUTO)
  807. , mStrokeLinecap(NS_STYLE_STROKE_LINECAP_BUTT)
  808. , mStrokeLinejoin(NS_STYLE_STROKE_LINEJOIN_MITER)
  809. , mTextAnchor(NS_STYLE_TEXT_ANCHOR_START)
  810. , mContextFlags((eStyleSVGOpacitySource_Normal << FILL_OPACITY_SOURCE_SHIFT) |
  811. (eStyleSVGOpacitySource_Normal << STROKE_OPACITY_SOURCE_SHIFT))
  812. {
  813. MOZ_COUNT_CTOR(nsStyleSVG);
  814. }
  815. nsStyleSVG::~nsStyleSVG()
  816. {
  817. MOZ_COUNT_DTOR(nsStyleSVG);
  818. }
  819. nsStyleSVG::nsStyleSVG(const nsStyleSVG& aSource)
  820. : mFill(aSource.mFill)
  821. , mStroke(aSource.mStroke)
  822. , mMarkerEnd(aSource.mMarkerEnd)
  823. , mMarkerMid(aSource.mMarkerMid)
  824. , mMarkerStart(aSource.mMarkerStart)
  825. , mStrokeDasharray(aSource.mStrokeDasharray)
  826. , mStrokeDashoffset(aSource.mStrokeDashoffset)
  827. , mStrokeWidth(aSource.mStrokeWidth)
  828. , mFillOpacity(aSource.mFillOpacity)
  829. , mStrokeMiterlimit(aSource.mStrokeMiterlimit)
  830. , mStrokeOpacity(aSource.mStrokeOpacity)
  831. , mClipRule(aSource.mClipRule)
  832. , mColorInterpolation(aSource.mColorInterpolation)
  833. , mColorInterpolationFilters(aSource.mColorInterpolationFilters)
  834. , mFillRule(aSource.mFillRule)
  835. , mPaintOrder(aSource.mPaintOrder)
  836. , mShapeRendering(aSource.mShapeRendering)
  837. , mStrokeLinecap(aSource.mStrokeLinecap)
  838. , mStrokeLinejoin(aSource.mStrokeLinejoin)
  839. , mTextAnchor(aSource.mTextAnchor)
  840. , mContextFlags(aSource.mContextFlags)
  841. {
  842. MOZ_COUNT_CTOR(nsStyleSVG);
  843. }
  844. static bool
  845. PaintURIChanged(const nsStyleSVGPaint& aPaint1, const nsStyleSVGPaint& aPaint2)
  846. {
  847. if (aPaint1.Type() != aPaint2.Type()) {
  848. return aPaint1.Type() == eStyleSVGPaintType_Server ||
  849. aPaint2.Type() == eStyleSVGPaintType_Server;
  850. }
  851. return aPaint1.Type() == eStyleSVGPaintType_Server &&
  852. !DefinitelyEqualURIs(aPaint1.GetPaintServer(),
  853. aPaint2.GetPaintServer());
  854. }
  855. nsChangeHint
  856. nsStyleSVG::CalcDifference(const nsStyleSVG& aNewData) const
  857. {
  858. nsChangeHint hint = nsChangeHint(0);
  859. if (!DefinitelyEqualURIs(mMarkerEnd, aNewData.mMarkerEnd) ||
  860. !DefinitelyEqualURIs(mMarkerMid, aNewData.mMarkerMid) ||
  861. !DefinitelyEqualURIs(mMarkerStart, aNewData.mMarkerStart)) {
  862. // Markers currently contribute to nsSVGPathGeometryFrame::mRect,
  863. // so we need a reflow as well as a repaint. No intrinsic sizes need
  864. // to change, so nsChangeHint_NeedReflow is sufficient.
  865. return nsChangeHint_UpdateEffects |
  866. nsChangeHint_NeedReflow |
  867. nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
  868. nsChangeHint_RepaintFrame;
  869. }
  870. if (mFill != aNewData.mFill ||
  871. mStroke != aNewData.mStroke ||
  872. mFillOpacity != aNewData.mFillOpacity ||
  873. mStrokeOpacity != aNewData.mStrokeOpacity) {
  874. hint |= nsChangeHint_RepaintFrame;
  875. if (HasStroke() != aNewData.HasStroke() ||
  876. (!HasStroke() && HasFill() != aNewData.HasFill())) {
  877. // Frame bounds and overflow rects depend on whether we "have" fill or
  878. // stroke. Whether we have stroke or not just changed, or else we have no
  879. // stroke (in which case whether we have fill or not is significant to frame
  880. // bounds) and whether we have fill or not just changed. In either case we
  881. // need to reflow so the frame rect is updated.
  882. // XXXperf this is a waste on non nsSVGPathGeometryFrames.
  883. hint |= nsChangeHint_NeedReflow |
  884. nsChangeHint_NeedDirtyReflow; // XXX remove me: bug 876085
  885. }
  886. if (PaintURIChanged(mFill, aNewData.mFill) ||
  887. PaintURIChanged(mStroke, aNewData.mStroke)) {
  888. hint |= nsChangeHint_UpdateEffects;
  889. }
  890. }
  891. // Stroke currently contributes to nsSVGPathGeometryFrame::mRect, so
  892. // we need a reflow here. No intrinsic sizes need to change, so
  893. // nsChangeHint_NeedReflow is sufficient.
  894. // Note that stroke-dashoffset does not affect nsSVGPathGeometryFrame::mRect.
  895. // text-anchor changes also require a reflow since it changes frames' rects.
  896. if (mStrokeWidth != aNewData.mStrokeWidth ||
  897. mStrokeMiterlimit != aNewData.mStrokeMiterlimit ||
  898. mStrokeLinecap != aNewData.mStrokeLinecap ||
  899. mStrokeLinejoin != aNewData.mStrokeLinejoin ||
  900. mTextAnchor != aNewData.mTextAnchor) {
  901. return hint |
  902. nsChangeHint_NeedReflow |
  903. nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
  904. nsChangeHint_RepaintFrame;
  905. }
  906. if (hint & nsChangeHint_RepaintFrame) {
  907. return hint; // we don't add anything else below
  908. }
  909. if ( mStrokeDashoffset != aNewData.mStrokeDashoffset ||
  910. mClipRule != aNewData.mClipRule ||
  911. mColorInterpolation != aNewData.mColorInterpolation ||
  912. mColorInterpolationFilters != aNewData.mColorInterpolationFilters ||
  913. mFillRule != aNewData.mFillRule ||
  914. mPaintOrder != aNewData.mPaintOrder ||
  915. mShapeRendering != aNewData.mShapeRendering ||
  916. mStrokeDasharray != aNewData.mStrokeDasharray ||
  917. mContextFlags != aNewData.mContextFlags) {
  918. return hint | nsChangeHint_RepaintFrame;
  919. }
  920. return hint;
  921. }
  922. // --------------------
  923. // StyleBasicShape
  924. nsCSSKeyword
  925. StyleBasicShape::GetShapeTypeName() const
  926. {
  927. switch (mType) {
  928. case StyleBasicShapeType::Polygon:
  929. return eCSSKeyword_polygon;
  930. case StyleBasicShapeType::Circle:
  931. return eCSSKeyword_circle;
  932. case StyleBasicShapeType::Ellipse:
  933. return eCSSKeyword_ellipse;
  934. case StyleBasicShapeType::Inset:
  935. return eCSSKeyword_inset;
  936. }
  937. NS_NOTREACHED("unexpected type");
  938. return eCSSKeyword_UNKNOWN;
  939. }
  940. // --------------------
  941. // nsStyleFilter
  942. //
  943. nsStyleFilter::nsStyleFilter()
  944. : mType(NS_STYLE_FILTER_NONE)
  945. , mDropShadow(nullptr)
  946. {
  947. MOZ_COUNT_CTOR(nsStyleFilter);
  948. }
  949. nsStyleFilter::nsStyleFilter(const nsStyleFilter& aSource)
  950. : mType(NS_STYLE_FILTER_NONE)
  951. , mDropShadow(nullptr)
  952. {
  953. MOZ_COUNT_CTOR(nsStyleFilter);
  954. if (aSource.mType == NS_STYLE_FILTER_URL) {
  955. SetURL(aSource.mURL);
  956. } else if (aSource.mType == NS_STYLE_FILTER_DROP_SHADOW) {
  957. SetDropShadow(aSource.mDropShadow);
  958. } else if (aSource.mType != NS_STYLE_FILTER_NONE) {
  959. SetFilterParameter(aSource.mFilterParameter, aSource.mType);
  960. }
  961. }
  962. nsStyleFilter::~nsStyleFilter()
  963. {
  964. ReleaseRef();
  965. MOZ_COUNT_DTOR(nsStyleFilter);
  966. }
  967. nsStyleFilter&
  968. nsStyleFilter::operator=(const nsStyleFilter& aOther)
  969. {
  970. if (this == &aOther) {
  971. return *this;
  972. }
  973. if (aOther.mType == NS_STYLE_FILTER_URL) {
  974. SetURL(aOther.mURL);
  975. } else if (aOther.mType == NS_STYLE_FILTER_DROP_SHADOW) {
  976. SetDropShadow(aOther.mDropShadow);
  977. } else if (aOther.mType != NS_STYLE_FILTER_NONE) {
  978. SetFilterParameter(aOther.mFilterParameter, aOther.mType);
  979. } else {
  980. ReleaseRef();
  981. mType = NS_STYLE_FILTER_NONE;
  982. }
  983. return *this;
  984. }
  985. bool
  986. nsStyleFilter::operator==(const nsStyleFilter& aOther) const
  987. {
  988. if (mType != aOther.mType) {
  989. return false;
  990. }
  991. if (mType == NS_STYLE_FILTER_URL) {
  992. return DefinitelyEqualURIs(mURL, aOther.mURL);
  993. } else if (mType == NS_STYLE_FILTER_DROP_SHADOW) {
  994. return *mDropShadow == *aOther.mDropShadow;
  995. } else if (mType != NS_STYLE_FILTER_NONE) {
  996. return mFilterParameter == aOther.mFilterParameter;
  997. }
  998. return true;
  999. }
  1000. void
  1001. nsStyleFilter::ReleaseRef()
  1002. {
  1003. if (mType == NS_STYLE_FILTER_DROP_SHADOW) {
  1004. NS_ASSERTION(mDropShadow, "expected pointer");
  1005. mDropShadow->Release();
  1006. } else if (mType == NS_STYLE_FILTER_URL) {
  1007. NS_ASSERTION(mURL, "expected pointer");
  1008. mURL->Release();
  1009. }
  1010. mURL = nullptr;
  1011. }
  1012. void
  1013. nsStyleFilter::SetFilterParameter(const nsStyleCoord& aFilterParameter,
  1014. int32_t aType)
  1015. {
  1016. ReleaseRef();
  1017. mFilterParameter = aFilterParameter;
  1018. mType = aType;
  1019. }
  1020. bool
  1021. nsStyleFilter::SetURL(css::URLValue* aURL)
  1022. {
  1023. ReleaseRef();
  1024. mURL = aURL;
  1025. mURL->AddRef();
  1026. mType = NS_STYLE_FILTER_URL;
  1027. return true;
  1028. }
  1029. void
  1030. nsStyleFilter::SetDropShadow(nsCSSShadowArray* aDropShadow)
  1031. {
  1032. NS_ASSERTION(aDropShadow, "expected pointer");
  1033. ReleaseRef();
  1034. mDropShadow = aDropShadow;
  1035. mDropShadow->AddRef();
  1036. mType = NS_STYLE_FILTER_DROP_SHADOW;
  1037. }
  1038. // --------------------
  1039. // nsStyleSVGReset
  1040. //
  1041. nsStyleSVGReset::nsStyleSVGReset(StyleStructContext aContext)
  1042. : mMask(nsStyleImageLayers::LayerType::Mask)
  1043. , mStopColor(NS_RGB(0, 0, 0))
  1044. , mFloodColor(NS_RGB(0, 0, 0))
  1045. , mLightingColor(NS_RGB(255, 255, 255))
  1046. , mStopOpacity(1.0f)
  1047. , mFloodOpacity(1.0f)
  1048. , mDominantBaseline(NS_STYLE_DOMINANT_BASELINE_AUTO)
  1049. , mVectorEffect(NS_STYLE_VECTOR_EFFECT_NONE)
  1050. , mMaskType(NS_STYLE_MASK_TYPE_LUMINANCE)
  1051. {
  1052. MOZ_COUNT_CTOR(nsStyleSVGReset);
  1053. }
  1054. nsStyleSVGReset::~nsStyleSVGReset()
  1055. {
  1056. MOZ_COUNT_DTOR(nsStyleSVGReset);
  1057. }
  1058. nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset& aSource)
  1059. : mMask(aSource.mMask)
  1060. , mClipPath(aSource.mClipPath)
  1061. , mStopColor(aSource.mStopColor)
  1062. , mFloodColor(aSource.mFloodColor)
  1063. , mLightingColor(aSource.mLightingColor)
  1064. , mStopOpacity(aSource.mStopOpacity)
  1065. , mFloodOpacity(aSource.mFloodOpacity)
  1066. , mDominantBaseline(aSource.mDominantBaseline)
  1067. , mVectorEffect(aSource.mVectorEffect)
  1068. , mMaskType(aSource.mMaskType)
  1069. {
  1070. MOZ_COUNT_CTOR(nsStyleSVGReset);
  1071. }
  1072. void
  1073. nsStyleSVGReset::Destroy(nsPresContext* aContext)
  1074. {
  1075. this->~nsStyleSVGReset();
  1076. aContext->PresShell()->
  1077. FreeByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, this);
  1078. }
  1079. void
  1080. nsStyleSVGReset::FinishStyle(nsPresContext* aPresContext)
  1081. {
  1082. MOZ_ASSERT(NS_IsMainThread());
  1083. MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
  1084. mMask.ResolveImages(aPresContext);
  1085. }
  1086. nsChangeHint
  1087. nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aNewData) const
  1088. {
  1089. nsChangeHint hint = nsChangeHint(0);
  1090. if (mClipPath != aNewData.mClipPath) {
  1091. hint |= nsChangeHint_UpdateEffects |
  1092. nsChangeHint_RepaintFrame;
  1093. // clip-path changes require that we update the PreEffectsBBoxProperty,
  1094. // which is done during overflow computation.
  1095. hint |= nsChangeHint_UpdateOverflow;
  1096. }
  1097. if (mDominantBaseline != aNewData.mDominantBaseline) {
  1098. // XXXjwatt: why NS_STYLE_HINT_REFLOW? Isn't that excessive?
  1099. hint |= NS_STYLE_HINT_REFLOW;
  1100. } else if (mVectorEffect != aNewData.mVectorEffect) {
  1101. // Stroke currently affects nsSVGPathGeometryFrame::mRect, and
  1102. // vector-effect affect stroke. As a result we need to reflow if
  1103. // vector-effect changes in order to have nsSVGPathGeometryFrame::
  1104. // ReflowSVG called to update its mRect. No intrinsic sizes need
  1105. // to change so nsChangeHint_NeedReflow is sufficient.
  1106. hint |= nsChangeHint_NeedReflow |
  1107. nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
  1108. nsChangeHint_RepaintFrame;
  1109. } else if (mStopColor != aNewData.mStopColor ||
  1110. mFloodColor != aNewData.mFloodColor ||
  1111. mLightingColor != aNewData.mLightingColor ||
  1112. mStopOpacity != aNewData.mStopOpacity ||
  1113. mFloodOpacity != aNewData.mFloodOpacity ||
  1114. mMaskType != aNewData.mMaskType) {
  1115. hint |= nsChangeHint_RepaintFrame;
  1116. }
  1117. hint |= mMask.CalcDifference(aNewData.mMask,
  1118. nsStyleImageLayers::LayerType::Mask);
  1119. return hint;
  1120. }
  1121. // nsStyleSVGPaint implementation
  1122. nsStyleSVGPaint::nsStyleSVGPaint(nsStyleSVGPaintType aType)
  1123. : mType(aType)
  1124. , mFallbackColor(NS_RGB(0, 0, 0))
  1125. {
  1126. MOZ_ASSERT(aType == nsStyleSVGPaintType(0) ||
  1127. aType == eStyleSVGPaintType_None ||
  1128. aType == eStyleSVGPaintType_Color);
  1129. mPaint.mColor = NS_RGB(0, 0, 0);
  1130. }
  1131. nsStyleSVGPaint::nsStyleSVGPaint(const nsStyleSVGPaint& aSource)
  1132. : nsStyleSVGPaint(nsStyleSVGPaintType(0))
  1133. {
  1134. Assign(aSource);
  1135. }
  1136. nsStyleSVGPaint::~nsStyleSVGPaint()
  1137. {
  1138. Reset();
  1139. }
  1140. void
  1141. nsStyleSVGPaint::Reset()
  1142. {
  1143. switch (mType) {
  1144. case eStyleSVGPaintType_None:
  1145. break;
  1146. case eStyleSVGPaintType_Color:
  1147. mPaint.mColor = NS_RGB(0, 0, 0);
  1148. break;
  1149. case eStyleSVGPaintType_Server:
  1150. mPaint.mPaintServer->Release();
  1151. mPaint.mPaintServer = nullptr;
  1152. MOZ_FALLTHROUGH;
  1153. case eStyleSVGPaintType_ContextFill:
  1154. case eStyleSVGPaintType_ContextStroke:
  1155. mFallbackColor = NS_RGB(0, 0, 0);
  1156. break;
  1157. }
  1158. mType = nsStyleSVGPaintType(0);
  1159. }
  1160. nsStyleSVGPaint&
  1161. nsStyleSVGPaint::operator=(const nsStyleSVGPaint& aOther)
  1162. {
  1163. if (this != &aOther) {
  1164. Assign(aOther);
  1165. }
  1166. return *this;
  1167. }
  1168. void
  1169. nsStyleSVGPaint::Assign(const nsStyleSVGPaint& aOther)
  1170. {
  1171. MOZ_ASSERT(aOther.mType != nsStyleSVGPaintType(0),
  1172. "shouldn't copy uninitialized nsStyleSVGPaint");
  1173. switch (aOther.mType) {
  1174. case eStyleSVGPaintType_None:
  1175. SetNone();
  1176. break;
  1177. case eStyleSVGPaintType_Color:
  1178. SetColor(aOther.mPaint.mColor);
  1179. break;
  1180. case eStyleSVGPaintType_Server:
  1181. SetPaintServer(aOther.mPaint.mPaintServer,
  1182. aOther.mFallbackColor);
  1183. break;
  1184. case eStyleSVGPaintType_ContextFill:
  1185. case eStyleSVGPaintType_ContextStroke:
  1186. SetContextValue(aOther.mType, aOther.mFallbackColor);
  1187. break;
  1188. }
  1189. }
  1190. void
  1191. nsStyleSVGPaint::SetNone()
  1192. {
  1193. Reset();
  1194. mType = eStyleSVGPaintType_None;
  1195. }
  1196. void
  1197. nsStyleSVGPaint::SetContextValue(nsStyleSVGPaintType aType,
  1198. nscolor aFallbackColor)
  1199. {
  1200. MOZ_ASSERT(aType == eStyleSVGPaintType_ContextFill ||
  1201. aType == eStyleSVGPaintType_ContextStroke);
  1202. Reset();
  1203. mType = aType;
  1204. mFallbackColor = aFallbackColor;
  1205. }
  1206. void
  1207. nsStyleSVGPaint::SetColor(nscolor aColor)
  1208. {
  1209. Reset();
  1210. mType = eStyleSVGPaintType_Color;
  1211. mPaint.mColor = aColor;
  1212. }
  1213. void
  1214. nsStyleSVGPaint::SetPaintServer(css::URLValue* aPaintServer,
  1215. nscolor aFallbackColor)
  1216. {
  1217. MOZ_ASSERT(aPaintServer);
  1218. Reset();
  1219. mType = eStyleSVGPaintType_Server;
  1220. mPaint.mPaintServer = aPaintServer;
  1221. mPaint.mPaintServer->AddRef();
  1222. mFallbackColor = aFallbackColor;
  1223. }
  1224. bool nsStyleSVGPaint::operator==(const nsStyleSVGPaint& aOther) const
  1225. {
  1226. if (mType != aOther.mType) {
  1227. return false;
  1228. }
  1229. switch (mType) {
  1230. case eStyleSVGPaintType_Color:
  1231. return mPaint.mColor == aOther.mPaint.mColor;
  1232. case eStyleSVGPaintType_Server:
  1233. return DefinitelyEqualURIs(mPaint.mPaintServer,
  1234. aOther.mPaint.mPaintServer) &&
  1235. mFallbackColor == aOther.mFallbackColor;
  1236. case eStyleSVGPaintType_ContextFill:
  1237. case eStyleSVGPaintType_ContextStroke:
  1238. return mFallbackColor == aOther.mFallbackColor;
  1239. default:
  1240. MOZ_ASSERT(mType == eStyleSVGPaintType_None,
  1241. "Unexpected SVG paint type");
  1242. return true;
  1243. }
  1244. }
  1245. // --------------------
  1246. // nsStylePosition
  1247. //
  1248. nsStylePosition::nsStylePosition(StyleStructContext aContext)
  1249. : mWidth(eStyleUnit_Auto)
  1250. , mMinWidth(eStyleUnit_Auto)
  1251. , mMaxWidth(eStyleUnit_None)
  1252. , mHeight(eStyleUnit_Auto)
  1253. , mMinHeight(eStyleUnit_Auto)
  1254. , mMaxHeight(eStyleUnit_None)
  1255. , mFlexBasis(eStyleUnit_Auto)
  1256. , mGridAutoColumnsMin(eStyleUnit_Auto)
  1257. , mGridAutoColumnsMax(eStyleUnit_Auto)
  1258. , mGridAutoRowsMin(eStyleUnit_Auto)
  1259. , mGridAutoRowsMax(eStyleUnit_Auto)
  1260. , mAspectRatio(0.0f)
  1261. , mGridAutoFlow(NS_STYLE_GRID_AUTO_FLOW_ROW)
  1262. , mBoxSizing(StyleBoxSizing::Content)
  1263. , mAlignContent(NS_STYLE_ALIGN_NORMAL)
  1264. , mAlignItems(NS_STYLE_ALIGN_NORMAL)
  1265. , mAlignSelf(NS_STYLE_ALIGN_AUTO)
  1266. , mJustifyContent(NS_STYLE_JUSTIFY_NORMAL)
  1267. , mJustifyItems(NS_STYLE_JUSTIFY_AUTO)
  1268. , mJustifySelf(NS_STYLE_JUSTIFY_AUTO)
  1269. , mFlexDirection(NS_STYLE_FLEX_DIRECTION_ROW)
  1270. , mFlexWrap(NS_STYLE_FLEX_WRAP_NOWRAP)
  1271. , mObjectFit(NS_STYLE_OBJECT_FIT_FILL)
  1272. , mOrder(NS_STYLE_ORDER_INITIAL)
  1273. , mFlexGrow(0.0f)
  1274. , mFlexShrink(1.0f)
  1275. , mZIndex(eStyleUnit_Auto)
  1276. , mGridColumnGap(nscoord(0), nsStyleCoord::CoordConstructor)
  1277. , mGridRowGap(nscoord(0), nsStyleCoord::CoordConstructor)
  1278. {
  1279. MOZ_COUNT_CTOR(nsStylePosition);
  1280. // positioning values not inherited
  1281. mObjectPosition.SetInitialPercentValues(0.5f);
  1282. nsStyleCoord autoCoord(eStyleUnit_Auto);
  1283. NS_FOR_CSS_SIDES(side) {
  1284. mOffset.Set(side, autoCoord);
  1285. }
  1286. // The initial value of grid-auto-columns and grid-auto-rows is 'auto',
  1287. // which computes to 'minmax(auto, auto)'.
  1288. // Other members get their default constructors
  1289. // which initialize them to representations of their respective initial value.
  1290. // mGridTemplateAreas: nullptr for 'none'
  1291. // mGridTemplate{Rows,Columns}: false and empty arrays for 'none'
  1292. // mGrid{Column,Row}{Start,End}: false/0/empty values for 'auto'
  1293. }
  1294. nsStylePosition::~nsStylePosition()
  1295. {
  1296. MOZ_COUNT_DTOR(nsStylePosition);
  1297. }
  1298. nsStylePosition::nsStylePosition(const nsStylePosition& aSource)
  1299. : mObjectPosition(aSource.mObjectPosition)
  1300. , mOffset(aSource.mOffset)
  1301. , mWidth(aSource.mWidth)
  1302. , mMinWidth(aSource.mMinWidth)
  1303. , mMaxWidth(aSource.mMaxWidth)
  1304. , mHeight(aSource.mHeight)
  1305. , mMinHeight(aSource.mMinHeight)
  1306. , mMaxHeight(aSource.mMaxHeight)
  1307. , mFlexBasis(aSource.mFlexBasis)
  1308. , mGridAutoColumnsMin(aSource.mGridAutoColumnsMin)
  1309. , mGridAutoColumnsMax(aSource.mGridAutoColumnsMax)
  1310. , mGridAutoRowsMin(aSource.mGridAutoRowsMin)
  1311. , mGridAutoRowsMax(aSource.mGridAutoRowsMax)
  1312. , mAspectRatio(aSource.mAspectRatio)
  1313. , mGridAutoFlow(aSource.mGridAutoFlow)
  1314. , mBoxSizing(aSource.mBoxSizing)
  1315. , mAlignContent(aSource.mAlignContent)
  1316. , mAlignItems(aSource.mAlignItems)
  1317. , mAlignSelf(aSource.mAlignSelf)
  1318. , mJustifyContent(aSource.mJustifyContent)
  1319. , mJustifyItems(aSource.mJustifyItems)
  1320. , mJustifySelf(aSource.mJustifySelf)
  1321. , mFlexDirection(aSource.mFlexDirection)
  1322. , mFlexWrap(aSource.mFlexWrap)
  1323. , mObjectFit(aSource.mObjectFit)
  1324. , mOrder(aSource.mOrder)
  1325. , mFlexGrow(aSource.mFlexGrow)
  1326. , mFlexShrink(aSource.mFlexShrink)
  1327. , mZIndex(aSource.mZIndex)
  1328. , mGridTemplateColumns(aSource.mGridTemplateColumns)
  1329. , mGridTemplateRows(aSource.mGridTemplateRows)
  1330. , mGridTemplateAreas(aSource.mGridTemplateAreas)
  1331. , mGridColumnStart(aSource.mGridColumnStart)
  1332. , mGridColumnEnd(aSource.mGridColumnEnd)
  1333. , mGridRowStart(aSource.mGridRowStart)
  1334. , mGridRowEnd(aSource.mGridRowEnd)
  1335. , mGridColumnGap(aSource.mGridColumnGap)
  1336. , mGridRowGap(aSource.mGridRowGap)
  1337. {
  1338. MOZ_COUNT_CTOR(nsStylePosition);
  1339. }
  1340. static bool
  1341. IsAutonessEqual(const nsStyleSides& aSides1, const nsStyleSides& aSides2)
  1342. {
  1343. NS_FOR_CSS_SIDES(side) {
  1344. if ((aSides1.GetUnit(side) == eStyleUnit_Auto) !=
  1345. (aSides2.GetUnit(side) == eStyleUnit_Auto)) {
  1346. return false;
  1347. }
  1348. }
  1349. return true;
  1350. }
  1351. nsChangeHint
  1352. nsStylePosition::CalcDifference(const nsStylePosition& aNewData,
  1353. const nsStyleVisibility* aOldStyleVisibility) const
  1354. {
  1355. nsChangeHint hint = nsChangeHint(0);
  1356. // Changes to "z-index" require a repaint.
  1357. if (mZIndex != aNewData.mZIndex) {
  1358. hint |= nsChangeHint_RepaintFrame;
  1359. }
  1360. // Changes to "object-fit" & "object-position" require a repaint. They
  1361. // may also require a reflow, if we have a nsSubDocumentFrame, so that we
  1362. // can adjust the size & position of the subdocument.
  1363. if (mObjectFit != aNewData.mObjectFit ||
  1364. mObjectPosition != aNewData.mObjectPosition) {
  1365. hint |= nsChangeHint_RepaintFrame |
  1366. nsChangeHint_NeedReflow;
  1367. }
  1368. if (mOrder != aNewData.mOrder) {
  1369. // "order" impacts both layout order and stacking order, so we need both a
  1370. // reflow and a repaint when it changes. (Technically, we only need a
  1371. // reflow if we're in a multi-line flexbox (which we can't be sure about,
  1372. // since that's determined by styling on our parent) -- there, "order" can
  1373. // affect which flex line we end up on, & hence can affect our sizing by
  1374. // changing the group of flex items we're competing with for space.)
  1375. return hint |
  1376. nsChangeHint_RepaintFrame |
  1377. nsChangeHint_AllReflowHints;
  1378. }
  1379. if (mBoxSizing != aNewData.mBoxSizing) {
  1380. // Can affect both widths and heights; just a bad scene.
  1381. return hint |
  1382. nsChangeHint_AllReflowHints;
  1383. }
  1384. // Properties that apply to flex items:
  1385. // XXXdholbert These should probably be more targeted (bug 819536)
  1386. if (mAlignSelf != aNewData.mAlignSelf ||
  1387. mFlexBasis != aNewData.mFlexBasis ||
  1388. mFlexGrow != aNewData.mFlexGrow ||
  1389. mFlexShrink != aNewData.mFlexShrink) {
  1390. return hint |
  1391. nsChangeHint_AllReflowHints;
  1392. }
  1393. // Properties that apply to flex containers:
  1394. // - flex-direction can swap a flex container between vertical & horizontal.
  1395. // - align-items can change the sizing of a flex container & the positioning
  1396. // of its children.
  1397. // - flex-wrap changes whether a flex container's children are wrapped, which
  1398. // impacts their sizing/positioning and hence impacts the container's size.
  1399. if (mAlignItems != aNewData.mAlignItems ||
  1400. mFlexDirection != aNewData.mFlexDirection ||
  1401. mFlexWrap != aNewData.mFlexWrap) {
  1402. return hint |
  1403. nsChangeHint_AllReflowHints;
  1404. }
  1405. // Properties that apply to grid containers:
  1406. // FIXME: only for grid containers
  1407. // (ie. 'display: grid' or 'display: inline-grid')
  1408. if (mGridTemplateColumns != aNewData.mGridTemplateColumns ||
  1409. mGridTemplateRows != aNewData.mGridTemplateRows ||
  1410. mGridTemplateAreas != aNewData.mGridTemplateAreas ||
  1411. mGridAutoColumnsMin != aNewData.mGridAutoColumnsMin ||
  1412. mGridAutoColumnsMax != aNewData.mGridAutoColumnsMax ||
  1413. mGridAutoRowsMin != aNewData.mGridAutoRowsMin ||
  1414. mGridAutoRowsMax != aNewData.mGridAutoRowsMax ||
  1415. mGridAutoFlow != aNewData.mGridAutoFlow) {
  1416. return hint |
  1417. nsChangeHint_AllReflowHints;
  1418. }
  1419. // Properties that apply to grid items:
  1420. // FIXME: only for grid items
  1421. // (ie. parent frame is 'display: grid' or 'display: inline-grid')
  1422. if (mGridColumnStart != aNewData.mGridColumnStart ||
  1423. mGridColumnEnd != aNewData.mGridColumnEnd ||
  1424. mGridRowStart != aNewData.mGridRowStart ||
  1425. mGridRowEnd != aNewData.mGridRowEnd ||
  1426. mGridColumnGap != aNewData.mGridColumnGap ||
  1427. mGridRowGap != aNewData.mGridRowGap) {
  1428. return hint |
  1429. nsChangeHint_AllReflowHints;
  1430. }
  1431. // Changing 'justify-content/items/self' might affect the positioning,
  1432. // but it won't affect any sizing.
  1433. if (mJustifyContent != aNewData.mJustifyContent ||
  1434. mJustifyItems != aNewData.mJustifyItems ||
  1435. mJustifySelf != aNewData.mJustifySelf) {
  1436. hint |= nsChangeHint_NeedReflow;
  1437. }
  1438. // 'align-content' doesn't apply to a single-line flexbox but we don't know
  1439. // if we're a flex container at this point so we can't optimize for that.
  1440. if (mAlignContent != aNewData.mAlignContent) {
  1441. hint |= nsChangeHint_NeedReflow;
  1442. }
  1443. bool widthChanged = mWidth != aNewData.mWidth ||
  1444. mMinWidth != aNewData.mMinWidth ||
  1445. mMaxWidth != aNewData.mMaxWidth;
  1446. bool heightChanged = mHeight != aNewData.mHeight ||
  1447. mMinHeight != aNewData.mMinHeight ||
  1448. mMaxHeight != aNewData.mMaxHeight;
  1449. // If aOldStyleVisibility is null, we don't need to bother with any of
  1450. // these tests, since we know that the element never had its
  1451. // nsStyleVisibility accessed, which means it couldn't have done
  1452. // layout.
  1453. // Note that we pass an nsStyleVisibility here because we don't want
  1454. // to cause a new struct to be computed during
  1455. // nsStyleContext::CalcStyleDifference, which can lead to incorrect
  1456. // style data.
  1457. // It doesn't matter whether we're looking at the old or new
  1458. // visibility struct, since a change between vertical and horizontal
  1459. // writing-mode will cause a reframe, and it's easier to pass the old.
  1460. if (aOldStyleVisibility) {
  1461. bool isVertical = WritingMode(aOldStyleVisibility).IsVertical();
  1462. if (isVertical ? widthChanged : heightChanged) {
  1463. hint |= nsChangeHint_ReflowHintsForBSizeChange;
  1464. }
  1465. if (isVertical ? heightChanged : widthChanged) {
  1466. hint |= nsChangeHint_ReflowHintsForISizeChange;
  1467. }
  1468. if (mAspectRatio != aNewData.mAspectRatio) {
  1469. hint |= nsChangeHint_ReflowHintsForISizeChange |
  1470. nsChangeHint_ReflowHintsForBSizeChange;
  1471. }
  1472. } else {
  1473. if (widthChanged || heightChanged) {
  1474. hint |= nsChangeHint_NeutralChange;
  1475. }
  1476. }
  1477. // If any of the offsets have changed, then return the respective hints
  1478. // so that we would hopefully be able to avoid reflowing.
  1479. // Note that it is possible that we'll need to reflow when processing
  1480. // restyles, but we don't have enough information to make a good decision
  1481. // right now.
  1482. // Don't try to handle changes between "auto" and non-auto efficiently;
  1483. // that's tricky to do and will hardly ever be able to avoid a reflow.
  1484. if (mOffset != aNewData.mOffset) {
  1485. if (IsAutonessEqual(mOffset, aNewData.mOffset)) {
  1486. hint |= nsChangeHint_RecomputePosition |
  1487. nsChangeHint_UpdateParentOverflow;
  1488. } else {
  1489. hint |= nsChangeHint_AllReflowHints;
  1490. }
  1491. }
  1492. return hint;
  1493. }
  1494. /* static */ bool
  1495. nsStylePosition::WidthCoordDependsOnContainer(const nsStyleCoord &aCoord)
  1496. {
  1497. return aCoord.HasPercent() ||
  1498. (aCoord.GetUnit() == eStyleUnit_Enumerated &&
  1499. (aCoord.GetIntValue() == NS_STYLE_WIDTH_FIT_CONTENT ||
  1500. aCoord.GetIntValue() == NS_STYLE_WIDTH_AVAILABLE));
  1501. }
  1502. uint8_t
  1503. nsStylePosition::UsedAlignSelf(nsStyleContext* aParent) const
  1504. {
  1505. if (mAlignSelf != NS_STYLE_ALIGN_AUTO) {
  1506. return mAlignSelf;
  1507. }
  1508. if (MOZ_LIKELY(aParent)) {
  1509. auto parentAlignItems = aParent->StylePosition()->mAlignItems;
  1510. MOZ_ASSERT(!(parentAlignItems & NS_STYLE_ALIGN_LEGACY),
  1511. "align-items can't have 'legacy'");
  1512. return parentAlignItems;
  1513. }
  1514. return NS_STYLE_ALIGN_NORMAL;
  1515. }
  1516. uint8_t
  1517. nsStylePosition::ComputedJustifyItems(nsStyleContext* aParent) const
  1518. {
  1519. if (mJustifyItems != NS_STYLE_JUSTIFY_AUTO) {
  1520. return mJustifyItems;
  1521. }
  1522. if (MOZ_LIKELY(aParent)) {
  1523. auto inheritedJustifyItems =
  1524. aParent->StylePosition()->ComputedJustifyItems(aParent->GetParent());
  1525. // "If the inherited value of justify-items includes the 'legacy' keyword,
  1526. // 'auto' computes to the inherited value." Otherwise, 'normal'.
  1527. if (inheritedJustifyItems & NS_STYLE_JUSTIFY_LEGACY) {
  1528. return inheritedJustifyItems;
  1529. }
  1530. }
  1531. return NS_STYLE_JUSTIFY_NORMAL;
  1532. }
  1533. uint8_t
  1534. nsStylePosition::UsedJustifySelf(nsStyleContext* aParent) const
  1535. {
  1536. if (mJustifySelf != NS_STYLE_JUSTIFY_AUTO) {
  1537. return mJustifySelf;
  1538. }
  1539. if (MOZ_LIKELY(aParent)) {
  1540. auto inheritedJustifyItems = aParent->StylePosition()->
  1541. ComputedJustifyItems(aParent->GetParent());
  1542. return inheritedJustifyItems & ~NS_STYLE_JUSTIFY_LEGACY;
  1543. }
  1544. return NS_STYLE_JUSTIFY_NORMAL;
  1545. }
  1546. // --------------------
  1547. // nsStyleTable
  1548. //
  1549. nsStyleTable::nsStyleTable(StyleStructContext aContext)
  1550. : mLayoutStrategy(NS_STYLE_TABLE_LAYOUT_AUTO)
  1551. , mSpan(1)
  1552. {
  1553. MOZ_COUNT_CTOR(nsStyleTable);
  1554. }
  1555. nsStyleTable::~nsStyleTable()
  1556. {
  1557. MOZ_COUNT_DTOR(nsStyleTable);
  1558. }
  1559. nsStyleTable::nsStyleTable(const nsStyleTable& aSource)
  1560. : mLayoutStrategy(aSource.mLayoutStrategy)
  1561. , mSpan(aSource.mSpan)
  1562. {
  1563. MOZ_COUNT_CTOR(nsStyleTable);
  1564. }
  1565. nsChangeHint
  1566. nsStyleTable::CalcDifference(const nsStyleTable& aNewData) const
  1567. {
  1568. if (mSpan != aNewData.mSpan ||
  1569. mLayoutStrategy != aNewData.mLayoutStrategy) {
  1570. return nsChangeHint_ReconstructFrame;
  1571. }
  1572. return nsChangeHint(0);
  1573. }
  1574. // -----------------------
  1575. // nsStyleTableBorder
  1576. nsStyleTableBorder::nsStyleTableBorder(StyleStructContext aContext)
  1577. : mBorderSpacingCol(0)
  1578. , mBorderSpacingRow(0)
  1579. , mBorderCollapse(NS_STYLE_BORDER_SEPARATE)
  1580. , mCaptionSide(NS_STYLE_CAPTION_SIDE_TOP)
  1581. , mEmptyCells(NS_STYLE_TABLE_EMPTY_CELLS_SHOW)
  1582. {
  1583. MOZ_COUNT_CTOR(nsStyleTableBorder);
  1584. }
  1585. nsStyleTableBorder::~nsStyleTableBorder()
  1586. {
  1587. MOZ_COUNT_DTOR(nsStyleTableBorder);
  1588. }
  1589. nsStyleTableBorder::nsStyleTableBorder(const nsStyleTableBorder& aSource)
  1590. : mBorderSpacingCol(aSource.mBorderSpacingCol)
  1591. , mBorderSpacingRow(aSource.mBorderSpacingRow)
  1592. , mBorderCollapse(aSource.mBorderCollapse)
  1593. , mCaptionSide(aSource.mCaptionSide)
  1594. , mEmptyCells(aSource.mEmptyCells)
  1595. {
  1596. MOZ_COUNT_CTOR(nsStyleTableBorder);
  1597. }
  1598. nsChangeHint
  1599. nsStyleTableBorder::CalcDifference(const nsStyleTableBorder& aNewData) const
  1600. {
  1601. // Border-collapse changes need a reframe, because we use a different frame
  1602. // class for table cells in the collapsed border model. This is used to
  1603. // conserve memory when using the separated border model (collapsed borders
  1604. // require extra state to be stored).
  1605. if (mBorderCollapse != aNewData.mBorderCollapse) {
  1606. return nsChangeHint_ReconstructFrame;
  1607. }
  1608. if ((mCaptionSide == aNewData.mCaptionSide) &&
  1609. (mBorderSpacingCol == aNewData.mBorderSpacingCol) &&
  1610. (mBorderSpacingRow == aNewData.mBorderSpacingRow)) {
  1611. if (mEmptyCells == aNewData.mEmptyCells) {
  1612. return nsChangeHint(0);
  1613. }
  1614. return NS_STYLE_HINT_VISUAL;
  1615. } else {
  1616. return NS_STYLE_HINT_REFLOW;
  1617. }
  1618. }
  1619. // --------------------
  1620. // nsStyleColor
  1621. //
  1622. nsStyleColor::nsStyleColor(StyleStructContext aContext)
  1623. : mColor(aContext.DefaultColor())
  1624. {
  1625. MOZ_COUNT_CTOR(nsStyleColor);
  1626. }
  1627. nsStyleColor::nsStyleColor(const nsStyleColor& aSource)
  1628. : mColor(aSource.mColor)
  1629. {
  1630. MOZ_COUNT_CTOR(nsStyleColor);
  1631. }
  1632. nsChangeHint
  1633. nsStyleColor::CalcDifference(const nsStyleColor& aNewData) const
  1634. {
  1635. if (mColor == aNewData.mColor) {
  1636. return nsChangeHint(0);
  1637. }
  1638. return nsChangeHint_RepaintFrame;
  1639. }
  1640. // --------------------
  1641. // nsStyleGradient
  1642. //
  1643. bool
  1644. nsStyleGradient::operator==(const nsStyleGradient& aOther) const
  1645. {
  1646. MOZ_ASSERT(mSize == NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER ||
  1647. mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR,
  1648. "incorrect combination of shape and size");
  1649. MOZ_ASSERT(aOther.mSize == NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER ||
  1650. aOther.mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR,
  1651. "incorrect combination of shape and size");
  1652. if (mShape != aOther.mShape ||
  1653. mSize != aOther.mSize ||
  1654. mRepeating != aOther.mRepeating ||
  1655. mLegacySyntax != aOther.mLegacySyntax ||
  1656. mBgPosX != aOther.mBgPosX ||
  1657. mBgPosY != aOther.mBgPosY ||
  1658. mAngle != aOther.mAngle ||
  1659. mRadiusX != aOther.mRadiusX ||
  1660. mRadiusY != aOther.mRadiusY) {
  1661. return false;
  1662. }
  1663. if (mStops.Length() != aOther.mStops.Length()) {
  1664. return false;
  1665. }
  1666. for (uint32_t i = 0; i < mStops.Length(); i++) {
  1667. const auto& stop1 = mStops[i];
  1668. const auto& stop2 = aOther.mStops[i];
  1669. if (stop1.mLocation != stop2.mLocation ||
  1670. stop1.mIsInterpolationHint != stop2.mIsInterpolationHint ||
  1671. (!stop1.mIsInterpolationHint && stop1.mColor != stop2.mColor)) {
  1672. return false;
  1673. }
  1674. }
  1675. return true;
  1676. }
  1677. nsStyleGradient::nsStyleGradient()
  1678. : mShape(NS_STYLE_GRADIENT_SHAPE_LINEAR)
  1679. , mSize(NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER)
  1680. , mRepeating(false)
  1681. , mLegacySyntax(false)
  1682. {
  1683. }
  1684. bool
  1685. nsStyleGradient::IsOpaque()
  1686. {
  1687. for (uint32_t i = 0; i < mStops.Length(); i++) {
  1688. if (NS_GET_A(mStops[i].mColor) < 255) {
  1689. return false;
  1690. }
  1691. }
  1692. return true;
  1693. }
  1694. bool
  1695. nsStyleGradient::HasCalc()
  1696. {
  1697. for (uint32_t i = 0; i < mStops.Length(); i++) {
  1698. if (mStops[i].mLocation.IsCalcUnit()) {
  1699. return true;
  1700. }
  1701. }
  1702. return mBgPosX.IsCalcUnit() || mBgPosY.IsCalcUnit() || mAngle.IsCalcUnit() ||
  1703. mRadiusX.IsCalcUnit() || mRadiusY.IsCalcUnit();
  1704. }
  1705. // --------------------
  1706. // nsStyleImageRequest
  1707. /**
  1708. * Runnable to release the nsStyleImageRequest's mRequestProxy,
  1709. * mImageValue and mImageValue on the main thread, and to perform
  1710. * any necessary unlocking and untracking of the image.
  1711. */
  1712. class StyleImageRequestCleanupTask : public mozilla::Runnable
  1713. {
  1714. public:
  1715. typedef nsStyleImageRequest::Mode Mode;
  1716. StyleImageRequestCleanupTask(Mode aModeFlags,
  1717. already_AddRefed<imgRequestProxy> aRequestProxy,
  1718. already_AddRefed<css::ImageValue> aImageValue,
  1719. already_AddRefed<ImageTracker> aImageTracker)
  1720. : mModeFlags(aModeFlags)
  1721. , mRequestProxy(aRequestProxy)
  1722. , mImageValue(aImageValue)
  1723. , mImageTracker(aImageTracker)
  1724. {
  1725. }
  1726. NS_IMETHOD Run() final
  1727. {
  1728. MOZ_ASSERT(NS_IsMainThread());
  1729. if (!mRequestProxy) {
  1730. return NS_OK;
  1731. }
  1732. if (mModeFlags & Mode::Track) {
  1733. MOZ_ASSERT(mImageTracker);
  1734. mImageTracker->Remove(mRequestProxy);
  1735. } else {
  1736. mRequestProxy->UnlockImage();
  1737. }
  1738. if (mModeFlags & Mode::Discard) {
  1739. mRequestProxy->RequestDiscard();
  1740. }
  1741. return NS_OK;
  1742. }
  1743. protected:
  1744. virtual ~StyleImageRequestCleanupTask() { MOZ_ASSERT(NS_IsMainThread()); }
  1745. private:
  1746. Mode mModeFlags;
  1747. // Since we always dispatch this runnable to the main thread, these will be
  1748. // released on the main thread when the runnable itself is released.
  1749. RefPtr<imgRequestProxy> mRequestProxy;
  1750. RefPtr<css::ImageValue> mImageValue;
  1751. RefPtr<ImageTracker> mImageTracker;
  1752. };
  1753. nsStyleImageRequest::nsStyleImageRequest(Mode aModeFlags,
  1754. imgRequestProxy* aRequestProxy,
  1755. css::ImageValue* aImageValue,
  1756. ImageTracker* aImageTracker)
  1757. : mRequestProxy(aRequestProxy)
  1758. , mImageValue(aImageValue)
  1759. , mImageTracker(aImageTracker)
  1760. , mModeFlags(aModeFlags)
  1761. , mResolved(true)
  1762. {
  1763. MOZ_ASSERT(NS_IsMainThread());
  1764. MOZ_ASSERT(aRequestProxy);
  1765. MOZ_ASSERT(aImageValue);
  1766. MOZ_ASSERT(!!(aModeFlags & Mode::Track) == !!aImageTracker);
  1767. MaybeTrackAndLock();
  1768. }
  1769. nsStyleImageRequest::nsStyleImageRequest(
  1770. Mode aModeFlags,
  1771. nsStringBuffer* aURLBuffer,
  1772. already_AddRefed<PtrHolder<nsIURI>> aBaseURI,
  1773. already_AddRefed<PtrHolder<nsIURI>> aReferrer,
  1774. already_AddRefed<PtrHolder<nsIPrincipal>> aPrincipal)
  1775. : mModeFlags(aModeFlags)
  1776. , mResolved(false)
  1777. {
  1778. mImageValue = new css::ImageValue(aURLBuffer, Move(aBaseURI),
  1779. Move(aReferrer), Move(aPrincipal));
  1780. }
  1781. nsStyleImageRequest::~nsStyleImageRequest()
  1782. {
  1783. // We may or may not be being destroyed on the main thread. To clean
  1784. // up, we must untrack and unlock the image (depending on mModeFlags),
  1785. // and release mRequestProxy and mImageValue, all on the main thread.
  1786. {
  1787. RefPtr<StyleImageRequestCleanupTask> task =
  1788. new StyleImageRequestCleanupTask(mModeFlags,
  1789. mRequestProxy.forget(),
  1790. mImageValue.forget(),
  1791. mImageTracker.forget());
  1792. if (NS_IsMainThread()) {
  1793. task->Run();
  1794. } else {
  1795. NS_DispatchToMainThread(task.forget());
  1796. }
  1797. }
  1798. MOZ_ASSERT(!mRequestProxy);
  1799. MOZ_ASSERT(!mImageValue);
  1800. MOZ_ASSERT(!mImageTracker);
  1801. }
  1802. bool
  1803. nsStyleImageRequest::Resolve(nsPresContext* aPresContext)
  1804. {
  1805. MOZ_ASSERT(NS_IsMainThread());
  1806. MOZ_ASSERT(!IsResolved(), "already resolved");
  1807. mResolved = true;
  1808. // For now, just have unique nsCSSValue/ImageValue objects. We should
  1809. // really store the ImageValue on the Servo specified value, so that we can
  1810. // share imgRequestProxys that come from the same rule in the same
  1811. // document.
  1812. mImageValue->Initialize(aPresContext->Document());
  1813. nsCSSValue value;
  1814. value.SetImageValue(mImageValue);
  1815. mRequestProxy = value.GetPossiblyStaticImageValue(aPresContext->Document(),
  1816. aPresContext);
  1817. if (!mRequestProxy) {
  1818. // The URL resolution or image load failed.
  1819. return false;
  1820. }
  1821. if (mModeFlags & Mode::Track) {
  1822. mImageTracker = aPresContext->Document()->ImageTracker();
  1823. }
  1824. MaybeTrackAndLock();
  1825. return true;
  1826. }
  1827. void
  1828. nsStyleImageRequest::MaybeTrackAndLock()
  1829. {
  1830. MOZ_ASSERT(NS_IsMainThread());
  1831. MOZ_ASSERT(IsResolved());
  1832. MOZ_ASSERT(mRequestProxy);
  1833. if (mModeFlags & Mode::Track) {
  1834. MOZ_ASSERT(mImageTracker);
  1835. mImageTracker->Add(mRequestProxy);
  1836. } else {
  1837. MOZ_ASSERT(!mImageTracker);
  1838. mRequestProxy->LockImage();
  1839. }
  1840. }
  1841. bool
  1842. nsStyleImageRequest::DefinitelyEquals(const nsStyleImageRequest& aOther) const
  1843. {
  1844. return DefinitelyEqualURIs(mImageValue, aOther.mImageValue);
  1845. }
  1846. // --------------------
  1847. // CachedBorderImageData
  1848. //
  1849. void
  1850. CachedBorderImageData::SetCachedSVGViewportSize(
  1851. const mozilla::Maybe<nsSize>& aSVGViewportSize)
  1852. {
  1853. mCachedSVGViewportSize = aSVGViewportSize;
  1854. }
  1855. const mozilla::Maybe<nsSize>&
  1856. CachedBorderImageData::GetCachedSVGViewportSize()
  1857. {
  1858. return mCachedSVGViewportSize;
  1859. }
  1860. void
  1861. CachedBorderImageData::PurgeCachedImages()
  1862. {
  1863. mSubImages.Clear();
  1864. }
  1865. void
  1866. CachedBorderImageData::SetSubImage(uint8_t aIndex, imgIContainer* aSubImage)
  1867. {
  1868. mSubImages.ReplaceObjectAt(aSubImage, aIndex);
  1869. }
  1870. imgIContainer*
  1871. CachedBorderImageData::GetSubImage(uint8_t aIndex)
  1872. {
  1873. imgIContainer* subImage = nullptr;
  1874. if (aIndex < mSubImages.Count())
  1875. subImage = mSubImages[aIndex];
  1876. return subImage;
  1877. }
  1878. // --------------------
  1879. // nsStyleImage
  1880. //
  1881. nsStyleImage::nsStyleImage()
  1882. : mType(eStyleImageType_Null)
  1883. , mCropRect(nullptr)
  1884. {
  1885. MOZ_COUNT_CTOR(nsStyleImage);
  1886. }
  1887. nsStyleImage::~nsStyleImage()
  1888. {
  1889. MOZ_COUNT_DTOR(nsStyleImage);
  1890. if (mType != eStyleImageType_Null) {
  1891. SetNull();
  1892. }
  1893. }
  1894. nsStyleImage::nsStyleImage(const nsStyleImage& aOther)
  1895. : mType(eStyleImageType_Null)
  1896. , mCropRect(nullptr)
  1897. {
  1898. // We need our own copy constructor because we don't want
  1899. // to copy the reference count
  1900. MOZ_COUNT_CTOR(nsStyleImage);
  1901. DoCopy(aOther);
  1902. }
  1903. nsStyleImage&
  1904. nsStyleImage::operator=(const nsStyleImage& aOther)
  1905. {
  1906. if (this != &aOther) {
  1907. DoCopy(aOther);
  1908. }
  1909. return *this;
  1910. }
  1911. void
  1912. nsStyleImage::DoCopy(const nsStyleImage& aOther)
  1913. {
  1914. SetNull();
  1915. if (aOther.mType == eStyleImageType_Image) {
  1916. SetImageRequest(do_AddRef(aOther.mImage));
  1917. } else if (aOther.mType == eStyleImageType_Gradient) {
  1918. SetGradientData(aOther.mGradient);
  1919. } else if (aOther.mType == eStyleImageType_Element) {
  1920. SetElementId(aOther.mElementId);
  1921. }
  1922. UniquePtr<nsStyleSides> cropRectCopy;
  1923. if (aOther.mCropRect) {
  1924. cropRectCopy = MakeUnique<nsStyleSides>(*aOther.mCropRect.get());
  1925. }
  1926. SetCropRect(Move(cropRectCopy));
  1927. }
  1928. void
  1929. nsStyleImage::SetNull()
  1930. {
  1931. if (mType == eStyleImageType_Gradient) {
  1932. mGradient->Release();
  1933. } else if (mType == eStyleImageType_Image) {
  1934. NS_RELEASE(mImage);
  1935. } else if (mType == eStyleImageType_Element) {
  1936. free(mElementId);
  1937. }
  1938. mType = eStyleImageType_Null;
  1939. mCropRect = nullptr;
  1940. }
  1941. void
  1942. nsStyleImage::SetImageRequest(already_AddRefed<nsStyleImageRequest> aImage)
  1943. {
  1944. RefPtr<nsStyleImageRequest> image = aImage;
  1945. if (mType != eStyleImageType_Null) {
  1946. SetNull();
  1947. }
  1948. if (image) {
  1949. mImage = image.forget().take();
  1950. mType = eStyleImageType_Image;
  1951. }
  1952. if (mCachedBIData) {
  1953. mCachedBIData->PurgeCachedImages();
  1954. }
  1955. }
  1956. void
  1957. nsStyleImage::SetGradientData(nsStyleGradient* aGradient)
  1958. {
  1959. if (aGradient) {
  1960. aGradient->AddRef();
  1961. }
  1962. if (mType != eStyleImageType_Null) {
  1963. SetNull();
  1964. }
  1965. if (aGradient) {
  1966. mGradient = aGradient;
  1967. mType = eStyleImageType_Gradient;
  1968. }
  1969. }
  1970. void
  1971. nsStyleImage::SetElementId(const char16_t* aElementId)
  1972. {
  1973. if (mType != eStyleImageType_Null) {
  1974. SetNull();
  1975. }
  1976. if (aElementId) {
  1977. mElementId = NS_strdup(aElementId);
  1978. mType = eStyleImageType_Element;
  1979. }
  1980. }
  1981. void
  1982. nsStyleImage::SetCropRect(UniquePtr<nsStyleSides> aCropRect)
  1983. {
  1984. mCropRect = Move(aCropRect);
  1985. }
  1986. static int32_t
  1987. ConvertToPixelCoord(const nsStyleCoord& aCoord, int32_t aPercentScale)
  1988. {
  1989. double pixelValue;
  1990. switch (aCoord.GetUnit()) {
  1991. case eStyleUnit_Percent:
  1992. pixelValue = aCoord.GetPercentValue() * aPercentScale;
  1993. break;
  1994. case eStyleUnit_Factor:
  1995. pixelValue = aCoord.GetFactorValue();
  1996. break;
  1997. default:
  1998. NS_NOTREACHED("unexpected unit for image crop rect");
  1999. return 0;
  2000. }
  2001. MOZ_ASSERT(pixelValue >= 0, "we ensured non-negative while parsing");
  2002. pixelValue = std::min(pixelValue, double(INT32_MAX)); // avoid overflow
  2003. return NS_lround(pixelValue);
  2004. }
  2005. bool
  2006. nsStyleImage::ComputeActualCropRect(nsIntRect& aActualCropRect,
  2007. bool* aIsEntireImage) const
  2008. {
  2009. if (mType != eStyleImageType_Image) {
  2010. return false;
  2011. }
  2012. imgRequestProxy* req = GetImageData();
  2013. if (!req) {
  2014. return false;
  2015. }
  2016. nsCOMPtr<imgIContainer> imageContainer;
  2017. req->GetImage(getter_AddRefs(imageContainer));
  2018. if (!imageContainer) {
  2019. return false;
  2020. }
  2021. nsIntSize imageSize;
  2022. imageContainer->GetWidth(&imageSize.width);
  2023. imageContainer->GetHeight(&imageSize.height);
  2024. if (imageSize.width <= 0 || imageSize.height <= 0) {
  2025. return false;
  2026. }
  2027. int32_t left = ConvertToPixelCoord(mCropRect->GetLeft(), imageSize.width);
  2028. int32_t top = ConvertToPixelCoord(mCropRect->GetTop(), imageSize.height);
  2029. int32_t right = ConvertToPixelCoord(mCropRect->GetRight(), imageSize.width);
  2030. int32_t bottom = ConvertToPixelCoord(mCropRect->GetBottom(), imageSize.height);
  2031. // IntersectRect() returns an empty rect if we get negative width or height
  2032. nsIntRect cropRect(left, top, right - left, bottom - top);
  2033. nsIntRect imageRect(nsIntPoint(0, 0), imageSize);
  2034. aActualCropRect.IntersectRect(imageRect, cropRect);
  2035. if (aIsEntireImage) {
  2036. *aIsEntireImage = aActualCropRect.IsEqualInterior(imageRect);
  2037. }
  2038. return true;
  2039. }
  2040. nsresult
  2041. nsStyleImage::StartDecoding() const
  2042. {
  2043. if (mType == eStyleImageType_Image) {
  2044. imgRequestProxy* req = GetImageData();
  2045. if (!req) {
  2046. return NS_ERROR_FAILURE;
  2047. }
  2048. return req->StartDecoding();
  2049. }
  2050. return NS_OK;
  2051. }
  2052. bool
  2053. nsStyleImage::IsOpaque() const
  2054. {
  2055. if (!IsComplete()) {
  2056. return false;
  2057. }
  2058. if (mType == eStyleImageType_Gradient) {
  2059. return mGradient->IsOpaque();
  2060. }
  2061. if (mType == eStyleImageType_Element) {
  2062. return false;
  2063. }
  2064. MOZ_ASSERT(mType == eStyleImageType_Image, "unexpected image type");
  2065. MOZ_ASSERT(GetImageData(), "should've returned earlier above");
  2066. nsCOMPtr<imgIContainer> imageContainer;
  2067. GetImageData()->GetImage(getter_AddRefs(imageContainer));
  2068. MOZ_ASSERT(imageContainer, "IsComplete() said image container is ready");
  2069. // Check if the crop region of the image is opaque.
  2070. if (imageContainer->WillDrawOpaqueNow()) {
  2071. if (!mCropRect) {
  2072. return true;
  2073. }
  2074. // Must make sure if mCropRect contains at least a pixel.
  2075. // XXX Is this optimization worth it? Maybe I should just return false.
  2076. nsIntRect actualCropRect;
  2077. bool rv = ComputeActualCropRect(actualCropRect);
  2078. NS_ASSERTION(rv, "ComputeActualCropRect() can not fail here");
  2079. return rv && !actualCropRect.IsEmpty();
  2080. }
  2081. return false;
  2082. }
  2083. bool
  2084. nsStyleImage::IsComplete() const
  2085. {
  2086. switch (mType) {
  2087. case eStyleImageType_Null:
  2088. return false;
  2089. case eStyleImageType_Gradient:
  2090. case eStyleImageType_Element:
  2091. return true;
  2092. case eStyleImageType_Image: {
  2093. imgRequestProxy* req = GetImageData();
  2094. if (!req) {
  2095. return false;
  2096. }
  2097. uint32_t status = imgIRequest::STATUS_ERROR;
  2098. return NS_SUCCEEDED(req->GetImageStatus(&status)) &&
  2099. (status & imgIRequest::STATUS_SIZE_AVAILABLE) &&
  2100. (status & imgIRequest::STATUS_FRAME_COMPLETE);
  2101. }
  2102. default:
  2103. NS_NOTREACHED("unexpected image type");
  2104. return false;
  2105. }
  2106. }
  2107. bool
  2108. nsStyleImage::IsLoaded() const
  2109. {
  2110. switch (mType) {
  2111. case eStyleImageType_Null:
  2112. return false;
  2113. case eStyleImageType_Gradient:
  2114. case eStyleImageType_Element:
  2115. return true;
  2116. case eStyleImageType_Image: {
  2117. imgRequestProxy* req = GetImageData();
  2118. if (!req) {
  2119. return false;
  2120. }
  2121. uint32_t status = imgIRequest::STATUS_ERROR;
  2122. return NS_SUCCEEDED(req->GetImageStatus(&status)) &&
  2123. !(status & imgIRequest::STATUS_ERROR) &&
  2124. (status & imgIRequest::STATUS_LOAD_COMPLETE);
  2125. }
  2126. default:
  2127. NS_NOTREACHED("unexpected image type");
  2128. return false;
  2129. }
  2130. }
  2131. static inline bool
  2132. EqualRects(const UniquePtr<nsStyleSides>& aRect1, const UniquePtr<nsStyleSides>& aRect2)
  2133. {
  2134. return aRect1 == aRect2 || /* handles null== null, and optimize */
  2135. (aRect1 && aRect2 && *aRect1 == *aRect2);
  2136. }
  2137. bool
  2138. nsStyleImage::operator==(const nsStyleImage& aOther) const
  2139. {
  2140. if (mType != aOther.mType) {
  2141. return false;
  2142. }
  2143. if (!EqualRects(mCropRect, aOther.mCropRect)) {
  2144. return false;
  2145. }
  2146. if (mType == eStyleImageType_Image) {
  2147. return DefinitelyEqualImages(mImage, aOther.mImage);
  2148. }
  2149. if (mType == eStyleImageType_Gradient) {
  2150. return *mGradient == *aOther.mGradient;
  2151. }
  2152. if (mType == eStyleImageType_Element) {
  2153. return NS_strcmp(mElementId, aOther.mElementId) == 0;
  2154. }
  2155. return true;
  2156. }
  2157. void
  2158. nsStyleImage::PurgeCacheForViewportChange(
  2159. const mozilla::Maybe<nsSize>& aSVGViewportSize,
  2160. const bool aHasIntrinsicRatio) const
  2161. {
  2162. EnsureCachedBIData();
  2163. // If we're redrawing with a different viewport-size than we used for our
  2164. // cached subimages, then we can't trust that our subimages are valid;
  2165. // any percent sizes/positions in our SVG doc may be different now. Purge!
  2166. // (We don't have to purge if the SVG document has an intrinsic ratio,
  2167. // though, because the actual size of elements in SVG documant's coordinate
  2168. // axis are fixed in this case.)
  2169. if (aSVGViewportSize != mCachedBIData->GetCachedSVGViewportSize() &&
  2170. !aHasIntrinsicRatio) {
  2171. mCachedBIData->PurgeCachedImages();
  2172. mCachedBIData->SetCachedSVGViewportSize(aSVGViewportSize);
  2173. }
  2174. }
  2175. // --------------------
  2176. // nsStyleImageLayers
  2177. //
  2178. const nsCSSPropertyID nsStyleImageLayers::kBackgroundLayerTable[] = {
  2179. eCSSProperty_background, // shorthand
  2180. eCSSProperty_background_color, // color
  2181. eCSSProperty_background_image, // image
  2182. eCSSProperty_background_repeat, // repeat
  2183. eCSSProperty_background_position_x, // positionX
  2184. eCSSProperty_background_position_y, // positionY
  2185. eCSSProperty_background_clip, // clip
  2186. eCSSProperty_background_origin, // origin
  2187. eCSSProperty_background_size, // size
  2188. eCSSProperty_background_attachment, // attachment
  2189. eCSSProperty_UNKNOWN, // maskMode
  2190. eCSSProperty_UNKNOWN // composite
  2191. };
  2192. const nsCSSPropertyID nsStyleImageLayers::kMaskLayerTable[] = {
  2193. eCSSProperty_mask, // shorthand
  2194. eCSSProperty_UNKNOWN, // color
  2195. eCSSProperty_mask_image, // image
  2196. eCSSProperty_mask_repeat, // repeat
  2197. eCSSProperty_mask_position_x, // positionX
  2198. eCSSProperty_mask_position_y, // positionY
  2199. eCSSProperty_mask_clip, // clip
  2200. eCSSProperty_mask_origin, // origin
  2201. eCSSProperty_mask_size, // size
  2202. eCSSProperty_UNKNOWN, // attachment
  2203. eCSSProperty_mask_mode, // maskMode
  2204. eCSSProperty_mask_composite // composite
  2205. };
  2206. nsStyleImageLayers::nsStyleImageLayers(nsStyleImageLayers::LayerType aType)
  2207. : mAttachmentCount(1)
  2208. , mClipCount(1)
  2209. , mOriginCount(1)
  2210. , mRepeatCount(1)
  2211. , mPositionXCount(1)
  2212. , mPositionYCount(1)
  2213. , mImageCount(1)
  2214. , mSizeCount(1)
  2215. , mMaskModeCount(1)
  2216. , mBlendModeCount(1)
  2217. , mCompositeCount(1)
  2218. , mLayers(nsStyleAutoArray<Layer>::WITH_SINGLE_INITIAL_ELEMENT)
  2219. {
  2220. MOZ_COUNT_CTOR(nsStyleImageLayers);
  2221. // Ensure first layer is initialized as specified layer type
  2222. mLayers[0].Initialize(aType);
  2223. }
  2224. nsStyleImageLayers::nsStyleImageLayers(const nsStyleImageLayers &aSource)
  2225. : mAttachmentCount(aSource.mAttachmentCount)
  2226. , mClipCount(aSource.mClipCount)
  2227. , mOriginCount(aSource.mOriginCount)
  2228. , mRepeatCount(aSource.mRepeatCount)
  2229. , mPositionXCount(aSource.mPositionXCount)
  2230. , mPositionYCount(aSource.mPositionYCount)
  2231. , mImageCount(aSource.mImageCount)
  2232. , mSizeCount(aSource.mSizeCount)
  2233. , mMaskModeCount(aSource.mMaskModeCount)
  2234. , mBlendModeCount(aSource.mBlendModeCount)
  2235. , mCompositeCount(aSource.mCompositeCount)
  2236. , mLayers(aSource.mLayers) // deep copy
  2237. {
  2238. MOZ_COUNT_CTOR(nsStyleImageLayers);
  2239. // If the deep copy of mLayers failed, truncate the counts.
  2240. uint32_t count = mLayers.Length();
  2241. if (count != aSource.mLayers.Length()) {
  2242. NS_WARNING("truncating counts due to out-of-memory");
  2243. mAttachmentCount = std::max(mAttachmentCount, count);
  2244. mClipCount = std::max(mClipCount, count);
  2245. mOriginCount = std::max(mOriginCount, count);
  2246. mRepeatCount = std::max(mRepeatCount, count);
  2247. mPositionXCount = std::max(mPositionXCount, count);
  2248. mPositionYCount = std::max(mPositionYCount, count);
  2249. mImageCount = std::max(mImageCount, count);
  2250. mSizeCount = std::max(mSizeCount, count);
  2251. mMaskModeCount = std::max(mMaskModeCount, count);
  2252. mBlendModeCount = std::max(mBlendModeCount, count);
  2253. mCompositeCount = std::max(mCompositeCount, count);
  2254. }
  2255. }
  2256. nsChangeHint
  2257. nsStyleImageLayers::CalcDifference(const nsStyleImageLayers& aNewLayers,
  2258. nsStyleImageLayers::LayerType aType) const
  2259. {
  2260. nsChangeHint hint = nsChangeHint(0);
  2261. const nsStyleImageLayers& moreLayers =
  2262. mImageCount > aNewLayers.mImageCount ?
  2263. *this : aNewLayers;
  2264. const nsStyleImageLayers& lessLayers =
  2265. mImageCount > aNewLayers.mImageCount ?
  2266. aNewLayers : *this;
  2267. NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, moreLayers) {
  2268. if (i < lessLayers.mImageCount) {
  2269. nsChangeHint layerDifference =
  2270. moreLayers.mLayers[i].CalcDifference(lessLayers.mLayers[i]);
  2271. hint |= layerDifference;
  2272. if (layerDifference &&
  2273. ((moreLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element) ||
  2274. (lessLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element))) {
  2275. hint |= nsChangeHint_UpdateEffects | nsChangeHint_RepaintFrame;
  2276. }
  2277. } else {
  2278. hint |= nsChangeHint_RepaintFrame;
  2279. if (moreLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element) {
  2280. hint |= nsChangeHint_UpdateEffects | nsChangeHint_RepaintFrame;
  2281. }
  2282. }
  2283. }
  2284. if (aType == nsStyleImageLayers::LayerType::Mask &&
  2285. mImageCount != aNewLayers.mImageCount) {
  2286. hint |= nsChangeHint_UpdateEffects;
  2287. }
  2288. if (hint) {
  2289. return hint;
  2290. }
  2291. if (mAttachmentCount != aNewLayers.mAttachmentCount ||
  2292. mBlendModeCount != aNewLayers.mBlendModeCount ||
  2293. mClipCount != aNewLayers.mClipCount ||
  2294. mCompositeCount != aNewLayers.mCompositeCount ||
  2295. mMaskModeCount != aNewLayers.mMaskModeCount ||
  2296. mOriginCount != aNewLayers.mOriginCount ||
  2297. mRepeatCount != aNewLayers.mRepeatCount ||
  2298. mPositionXCount != aNewLayers.mPositionXCount ||
  2299. mPositionYCount != aNewLayers.mPositionYCount ||
  2300. mSizeCount != aNewLayers.mSizeCount) {
  2301. hint |= nsChangeHint_NeutralChange;
  2302. }
  2303. return hint;
  2304. }
  2305. bool
  2306. nsStyleImageLayers::HasLayerWithImage() const
  2307. {
  2308. for (uint32_t i = 0; i < mImageCount; i++) {
  2309. // mLayers[i].mSourceURI can be nullptr if mask-image prop value is
  2310. // <element-reference> or <gradient>
  2311. // mLayers[i].mImage can be empty if mask-image prop value is a reference
  2312. // to SVG mask element.
  2313. // So we need to test both mSourceURI and mImage.
  2314. if ((mLayers[i].mSourceURI && mLayers[i].mSourceURI->GetURI()) ||
  2315. !mLayers[i].mImage.IsEmpty()) {
  2316. return true;
  2317. }
  2318. }
  2319. return false;
  2320. }
  2321. nsStyleImageLayers&
  2322. nsStyleImageLayers::operator=(const nsStyleImageLayers& aOther)
  2323. {
  2324. mAttachmentCount = aOther.mAttachmentCount;
  2325. mClipCount = aOther.mClipCount;
  2326. mOriginCount = aOther.mOriginCount;
  2327. mRepeatCount = aOther.mRepeatCount;
  2328. mPositionXCount = aOther.mPositionXCount;
  2329. mPositionYCount = aOther.mPositionYCount;
  2330. mImageCount = aOther.mImageCount;
  2331. mSizeCount = aOther.mSizeCount;
  2332. mMaskModeCount = aOther.mMaskModeCount;
  2333. mBlendModeCount = aOther.mBlendModeCount;
  2334. mCompositeCount = aOther.mCompositeCount;
  2335. mLayers = aOther.mLayers;
  2336. uint32_t count = mLayers.Length();
  2337. if (count != aOther.mLayers.Length()) {
  2338. NS_WARNING("truncating counts due to out-of-memory");
  2339. mAttachmentCount = std::max(mAttachmentCount, count);
  2340. mClipCount = std::max(mClipCount, count);
  2341. mOriginCount = std::max(mOriginCount, count);
  2342. mRepeatCount = std::max(mRepeatCount, count);
  2343. mPositionXCount = std::max(mPositionXCount, count);
  2344. mPositionYCount = std::max(mPositionYCount, count);
  2345. mImageCount = std::max(mImageCount, count);
  2346. mSizeCount = std::max(mSizeCount, count);
  2347. mMaskModeCount = std::max(mMaskModeCount, count);
  2348. mBlendModeCount = std::max(mBlendModeCount, count);
  2349. mCompositeCount = std::max(mCompositeCount, count);
  2350. }
  2351. return *this;
  2352. }
  2353. bool
  2354. nsStyleImageLayers::IsInitialPositionForLayerType(Position aPosition, LayerType aType)
  2355. {
  2356. if (aPosition.mXPosition.mPercent == 0.0f &&
  2357. aPosition.mXPosition.mLength == 0 &&
  2358. aPosition.mXPosition.mHasPercent &&
  2359. aPosition.mYPosition.mPercent == 0.0f &&
  2360. aPosition.mYPosition.mLength == 0 &&
  2361. aPosition.mYPosition.mHasPercent) {
  2362. return true;
  2363. }
  2364. return false;
  2365. }
  2366. void
  2367. Position::SetInitialPercentValues(float aPercentVal)
  2368. {
  2369. mXPosition.mPercent = aPercentVal;
  2370. mXPosition.mLength = 0;
  2371. mXPosition.mHasPercent = true;
  2372. mYPosition.mPercent = aPercentVal;
  2373. mYPosition.mLength = 0;
  2374. mYPosition.mHasPercent = true;
  2375. }
  2376. void
  2377. Position::SetInitialZeroValues()
  2378. {
  2379. mXPosition.mPercent = 0;
  2380. mXPosition.mLength = 0;
  2381. mXPosition.mHasPercent = false;
  2382. mYPosition.mPercent = 0;
  2383. mYPosition.mLength = 0;
  2384. mYPosition.mHasPercent = false;
  2385. }
  2386. bool
  2387. nsStyleImageLayers::Size::DependsOnPositioningAreaSize(const nsStyleImage& aImage) const
  2388. {
  2389. MOZ_ASSERT(aImage.GetType() != eStyleImageType_Null,
  2390. "caller should have handled this");
  2391. // If either dimension contains a non-zero percentage, rendering for that
  2392. // dimension straightforwardly depends on frame size.
  2393. if ((mWidthType == eLengthPercentage && mWidth.mPercent != 0.0f) ||
  2394. (mHeightType == eLengthPercentage && mHeight.mPercent != 0.0f)) {
  2395. return true;
  2396. }
  2397. // So too for contain and cover.
  2398. if (mWidthType == eContain || mWidthType == eCover) {
  2399. return true;
  2400. }
  2401. // If both dimensions are fixed lengths, there's no dependency.
  2402. if (mWidthType == eLengthPercentage && mHeightType == eLengthPercentage) {
  2403. return false;
  2404. }
  2405. MOZ_ASSERT((mWidthType == eLengthPercentage && mHeightType == eAuto) ||
  2406. (mWidthType == eAuto && mHeightType == eLengthPercentage) ||
  2407. (mWidthType == eAuto && mHeightType == eAuto),
  2408. "logic error");
  2409. nsStyleImageType type = aImage.GetType();
  2410. // Gradient rendering depends on frame size when auto is involved because
  2411. // gradients have no intrinsic ratio or dimensions, and therefore the relevant
  2412. // dimension is "treat[ed] as 100%".
  2413. if (type == eStyleImageType_Gradient) {
  2414. return true;
  2415. }
  2416. // XXX Element rendering for auto or fixed length doesn't depend on frame size
  2417. // according to the spec. However, we don't implement the spec yet, so
  2418. // for now we bail and say element() plus auto affects ultimate size.
  2419. if (type == eStyleImageType_Element) {
  2420. return true;
  2421. }
  2422. if (type == eStyleImageType_Image) {
  2423. nsCOMPtr<imgIContainer> imgContainer;
  2424. if (imgRequestProxy* req = aImage.GetImageData()) {
  2425. req->GetImage(getter_AddRefs(imgContainer));
  2426. }
  2427. if (imgContainer) {
  2428. CSSIntSize imageSize;
  2429. AspectRatio imageRatio;
  2430. bool hasWidth, hasHeight;
  2431. nsLayoutUtils::ComputeSizeForDrawing(imgContainer, imageSize, imageRatio,
  2432. hasWidth, hasHeight);
  2433. // If the image has a fixed width and height, rendering never depends on
  2434. // the frame size.
  2435. if (hasWidth && hasHeight) {
  2436. return false;
  2437. }
  2438. // If the image has an intrinsic ratio, rendering will depend on frame
  2439. // size when background-size is all auto.
  2440. if (imageRatio) {
  2441. return mWidthType == mHeightType;
  2442. }
  2443. // Otherwise, rendering depends on frame size when the image dimensions
  2444. // and background-size don't complement each other.
  2445. return !(hasWidth && mHeightType == eLengthPercentage) &&
  2446. !(hasHeight && mWidthType == eLengthPercentage);
  2447. }
  2448. } else {
  2449. NS_NOTREACHED("missed an enum value");
  2450. }
  2451. // Passed the gauntlet: no dependency.
  2452. return false;
  2453. }
  2454. void
  2455. nsStyleImageLayers::Size::SetInitialValues()
  2456. {
  2457. mWidthType = mHeightType = eAuto;
  2458. }
  2459. bool
  2460. nsStyleImageLayers::Size::operator==(const Size& aOther) const
  2461. {
  2462. MOZ_ASSERT(mWidthType < eDimensionType_COUNT,
  2463. "bad mWidthType for this");
  2464. MOZ_ASSERT(mHeightType < eDimensionType_COUNT,
  2465. "bad mHeightType for this");
  2466. MOZ_ASSERT(aOther.mWidthType < eDimensionType_COUNT,
  2467. "bad mWidthType for aOther");
  2468. MOZ_ASSERT(aOther.mHeightType < eDimensionType_COUNT,
  2469. "bad mHeightType for aOther");
  2470. return mWidthType == aOther.mWidthType &&
  2471. mHeightType == aOther.mHeightType &&
  2472. (mWidthType != eLengthPercentage || mWidth == aOther.mWidth) &&
  2473. (mHeightType != eLengthPercentage || mHeight == aOther.mHeight);
  2474. }
  2475. nsStyleImageLayers::Layer::Layer()
  2476. : mClip(StyleGeometryBox::Border)
  2477. , mAttachment(NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL)
  2478. , mBlendMode(NS_STYLE_BLEND_NORMAL)
  2479. , mComposite(NS_STYLE_MASK_COMPOSITE_ADD)
  2480. , mMaskMode(NS_STYLE_MASK_MODE_MATCH_SOURCE)
  2481. {
  2482. mImage.SetNull();
  2483. mSize.SetInitialValues();
  2484. }
  2485. nsStyleImageLayers::Layer::~Layer()
  2486. {
  2487. }
  2488. void
  2489. nsStyleImageLayers::Layer::Initialize(nsStyleImageLayers::LayerType aType)
  2490. {
  2491. mRepeat.SetInitialValues();
  2492. mPosition.SetInitialPercentValues(0.0f);
  2493. if (aType == LayerType::Background) {
  2494. mOrigin = StyleGeometryBox::Padding;
  2495. } else {
  2496. MOZ_ASSERT(aType == LayerType::Mask, "unsupported layer type.");
  2497. mOrigin = StyleGeometryBox::Border;
  2498. }
  2499. }
  2500. bool
  2501. nsStyleImageLayers::Layer::RenderingMightDependOnPositioningAreaSizeChange() const
  2502. {
  2503. // Do we even have an image?
  2504. if (mImage.IsEmpty()) {
  2505. return false;
  2506. }
  2507. return mPosition.DependsOnPositioningAreaSize() ||
  2508. mSize.DependsOnPositioningAreaSize(mImage) ||
  2509. mRepeat.DependsOnPositioningAreaSize();
  2510. }
  2511. bool
  2512. nsStyleImageLayers::Layer::operator==(const Layer& aOther) const
  2513. {
  2514. return mAttachment == aOther.mAttachment &&
  2515. mClip == aOther.mClip &&
  2516. mOrigin == aOther.mOrigin &&
  2517. mRepeat == aOther.mRepeat &&
  2518. mBlendMode == aOther.mBlendMode &&
  2519. mPosition == aOther.mPosition &&
  2520. mSize == aOther.mSize &&
  2521. mImage == aOther.mImage &&
  2522. mMaskMode == aOther.mMaskMode &&
  2523. mComposite == aOther.mComposite &&
  2524. DefinitelyEqualURIs(mSourceURI, aOther.mSourceURI);
  2525. }
  2526. nsChangeHint
  2527. nsStyleImageLayers::Layer::CalcDifference(const nsStyleImageLayers::Layer& aNewLayer) const
  2528. {
  2529. nsChangeHint hint = nsChangeHint(0);
  2530. if (!DefinitelyEqualURIs(mSourceURI, aNewLayer.mSourceURI)) {
  2531. hint |= nsChangeHint_RepaintFrame | nsChangeHint_UpdateEffects;
  2532. // If Layer::mSourceURI links to a SVG mask, it has a fragment. Not vice
  2533. // versa. Here are examples of URI contains a fragment, two of them link
  2534. // to a SVG mask:
  2535. // mask:url(a.svg#maskID); // The fragment of this URI is an ID of a mask
  2536. // // element in a.svg.
  2537. // mask:url(#localMaskID); // The fragment of this URI is an ID of a mask
  2538. // // element in local document.
  2539. // mask:url(b.svg#viewBoxID); // The fragment of this URI is an ID of a
  2540. // // viewbox defined in b.svg.
  2541. // That is, if mSourceURI has a fragment, it may link to a SVG mask; If
  2542. // not, it "must" not link to a SVG mask.
  2543. bool maybeSVGMask = false;
  2544. if (mSourceURI) {
  2545. if (mSourceURI->IsLocalRef()) {
  2546. maybeSVGMask = true;
  2547. } else if (mSourceURI->GetURI()) {
  2548. mSourceURI->GetURI()->GetHasRef(&maybeSVGMask);
  2549. }
  2550. }
  2551. if (!maybeSVGMask) {
  2552. if (aNewLayer.mSourceURI) {
  2553. if (aNewLayer.mSourceURI->IsLocalRef()) {
  2554. maybeSVGMask = true;
  2555. } else if (aNewLayer.mSourceURI->GetURI()) {
  2556. aNewLayer.mSourceURI->GetURI()->GetHasRef(&maybeSVGMask);
  2557. }
  2558. }
  2559. }
  2560. // Return nsChangeHint_UpdateOverflow if either URI might link to an SVG
  2561. // mask.
  2562. if (maybeSVGMask) {
  2563. // Mask changes require that we update the PreEffectsBBoxProperty,
  2564. // which is done during overflow computation.
  2565. hint |= nsChangeHint_UpdateOverflow;
  2566. }
  2567. } else if (mAttachment != aNewLayer.mAttachment ||
  2568. mClip != aNewLayer.mClip ||
  2569. mOrigin != aNewLayer.mOrigin ||
  2570. mRepeat != aNewLayer.mRepeat ||
  2571. mBlendMode != aNewLayer.mBlendMode ||
  2572. mSize != aNewLayer.mSize ||
  2573. mImage != aNewLayer.mImage ||
  2574. mMaskMode != aNewLayer.mMaskMode ||
  2575. mComposite != aNewLayer.mComposite) {
  2576. hint |= nsChangeHint_RepaintFrame;
  2577. }
  2578. if (mPosition != aNewLayer.mPosition) {
  2579. hint |= nsChangeHint_UpdateBackgroundPosition;
  2580. }
  2581. return hint;
  2582. }
  2583. // --------------------
  2584. // nsStyleBackground
  2585. //
  2586. nsStyleBackground::nsStyleBackground(StyleStructContext aContext)
  2587. : mImage(nsStyleImageLayers::LayerType::Background)
  2588. , mBackgroundColor(NS_RGBA(0, 0, 0, 0))
  2589. {
  2590. MOZ_COUNT_CTOR(nsStyleBackground);
  2591. }
  2592. nsStyleBackground::nsStyleBackground(const nsStyleBackground& aSource)
  2593. : mImage(aSource.mImage)
  2594. , mBackgroundColor(aSource.mBackgroundColor)
  2595. {
  2596. MOZ_COUNT_CTOR(nsStyleBackground);
  2597. }
  2598. nsStyleBackground::~nsStyleBackground()
  2599. {
  2600. MOZ_COUNT_DTOR(nsStyleBackground);
  2601. }
  2602. void
  2603. nsStyleBackground::Destroy(nsPresContext* aContext)
  2604. {
  2605. this->~nsStyleBackground();
  2606. aContext->PresShell()->
  2607. FreeByObjectID(eArenaObjectID_nsStyleBackground, this);
  2608. }
  2609. void
  2610. nsStyleBackground::FinishStyle(nsPresContext* aPresContext)
  2611. {
  2612. MOZ_ASSERT(NS_IsMainThread());
  2613. MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
  2614. mImage.ResolveImages(aPresContext);
  2615. }
  2616. nsChangeHint
  2617. nsStyleBackground::CalcDifference(const nsStyleBackground& aNewData) const
  2618. {
  2619. nsChangeHint hint = nsChangeHint(0);
  2620. if (mBackgroundColor != aNewData.mBackgroundColor) {
  2621. hint |= nsChangeHint_RepaintFrame;
  2622. }
  2623. hint |= mImage.CalcDifference(aNewData.mImage,
  2624. nsStyleImageLayers::LayerType::Background);
  2625. return hint;
  2626. }
  2627. bool
  2628. nsStyleBackground::HasFixedBackground(nsIFrame* aFrame) const
  2629. {
  2630. NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, mImage) {
  2631. const nsStyleImageLayers::Layer &layer = mImage.mLayers[i];
  2632. if (layer.mAttachment == NS_STYLE_IMAGELAYER_ATTACHMENT_FIXED &&
  2633. !layer.mImage.IsEmpty() &&
  2634. !nsLayoutUtils::IsTransformed(aFrame)) {
  2635. return true;
  2636. }
  2637. }
  2638. return false;
  2639. }
  2640. bool
  2641. nsStyleBackground::IsTransparent() const
  2642. {
  2643. return BottomLayer().mImage.IsEmpty() &&
  2644. mImage.mImageCount == 1 &&
  2645. NS_GET_A(mBackgroundColor) == 0;
  2646. }
  2647. void
  2648. nsTimingFunction::AssignFromKeyword(int32_t aTimingFunctionType)
  2649. {
  2650. switch (aTimingFunctionType) {
  2651. case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START:
  2652. mType = Type::StepStart;
  2653. mSteps = 1;
  2654. return;
  2655. default:
  2656. MOZ_FALLTHROUGH_ASSERT("aTimingFunctionType must be a keyword value");
  2657. case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END:
  2658. mType = Type::StepEnd;
  2659. mSteps = 1;
  2660. return;
  2661. case NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE:
  2662. case NS_STYLE_TRANSITION_TIMING_FUNCTION_LINEAR:
  2663. case NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN:
  2664. case NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_OUT:
  2665. case NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN_OUT:
  2666. mType = static_cast<Type>(aTimingFunctionType);
  2667. break;
  2668. }
  2669. static_assert(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE == 0 &&
  2670. NS_STYLE_TRANSITION_TIMING_FUNCTION_LINEAR == 1 &&
  2671. NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN == 2 &&
  2672. NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_OUT == 3 &&
  2673. NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN_OUT == 4,
  2674. "transition timing function constants not as expected");
  2675. static const float timingFunctionValues[5][4] = {
  2676. { 0.25f, 0.10f, 0.25f, 1.00f }, // ease
  2677. { 0.00f, 0.00f, 1.00f, 1.00f }, // linear
  2678. { 0.42f, 0.00f, 1.00f, 1.00f }, // ease-in
  2679. { 0.00f, 0.00f, 0.58f, 1.00f }, // ease-out
  2680. { 0.42f, 0.00f, 0.58f, 1.00f } // ease-in-out
  2681. };
  2682. MOZ_ASSERT(0 <= aTimingFunctionType && aTimingFunctionType < 5,
  2683. "keyword out of range");
  2684. mFunc.mX1 = timingFunctionValues[aTimingFunctionType][0];
  2685. mFunc.mY1 = timingFunctionValues[aTimingFunctionType][1];
  2686. mFunc.mX2 = timingFunctionValues[aTimingFunctionType][2];
  2687. mFunc.mY2 = timingFunctionValues[aTimingFunctionType][3];
  2688. }
  2689. StyleTransition::StyleTransition(const StyleTransition& aCopy)
  2690. : mTimingFunction(aCopy.mTimingFunction)
  2691. , mDuration(aCopy.mDuration)
  2692. , mDelay(aCopy.mDelay)
  2693. , mProperty(aCopy.mProperty)
  2694. , mUnknownProperty(aCopy.mUnknownProperty)
  2695. {
  2696. }
  2697. void
  2698. StyleTransition::SetInitialValues()
  2699. {
  2700. mTimingFunction = nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE);
  2701. mDuration = 0.0;
  2702. mDelay = 0.0;
  2703. mProperty = eCSSPropertyExtra_all_properties;
  2704. }
  2705. void
  2706. StyleTransition::SetUnknownProperty(nsCSSPropertyID aProperty,
  2707. const nsAString& aPropertyString)
  2708. {
  2709. MOZ_ASSERT(nsCSSProps::LookupProperty(aPropertyString,
  2710. CSSEnabledState::eForAllContent) ==
  2711. aProperty,
  2712. "property and property string should match");
  2713. MOZ_ASSERT(aProperty == eCSSProperty_UNKNOWN ||
  2714. aProperty == eCSSPropertyExtra_variable,
  2715. "should be either unknown or custom property");
  2716. mProperty = aProperty;
  2717. mUnknownProperty = NS_Atomize(aPropertyString);
  2718. }
  2719. bool
  2720. StyleTransition::operator==(const StyleTransition& aOther) const
  2721. {
  2722. return mTimingFunction == aOther.mTimingFunction &&
  2723. mDuration == aOther.mDuration &&
  2724. mDelay == aOther.mDelay &&
  2725. mProperty == aOther.mProperty &&
  2726. (mProperty != eCSSProperty_UNKNOWN ||
  2727. mUnknownProperty == aOther.mUnknownProperty);
  2728. }
  2729. StyleAnimation::StyleAnimation(const StyleAnimation& aCopy)
  2730. : mTimingFunction(aCopy.mTimingFunction)
  2731. , mDuration(aCopy.mDuration)
  2732. , mDelay(aCopy.mDelay)
  2733. , mName(aCopy.mName)
  2734. , mDirection(aCopy.mDirection)
  2735. , mFillMode(aCopy.mFillMode)
  2736. , mPlayState(aCopy.mPlayState)
  2737. , mIterationCount(aCopy.mIterationCount)
  2738. {
  2739. }
  2740. void
  2741. StyleAnimation::SetInitialValues()
  2742. {
  2743. mTimingFunction = nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE);
  2744. mDuration = 0.0;
  2745. mDelay = 0.0;
  2746. mName = EmptyString();
  2747. mDirection = dom::PlaybackDirection::Normal;
  2748. mFillMode = dom::FillMode::None;
  2749. mPlayState = NS_STYLE_ANIMATION_PLAY_STATE_RUNNING;
  2750. mIterationCount = 1.0f;
  2751. }
  2752. bool
  2753. StyleAnimation::operator==(const StyleAnimation& aOther) const
  2754. {
  2755. return mTimingFunction == aOther.mTimingFunction &&
  2756. mDuration == aOther.mDuration &&
  2757. mDelay == aOther.mDelay &&
  2758. mName == aOther.mName &&
  2759. mDirection == aOther.mDirection &&
  2760. mFillMode == aOther.mFillMode &&
  2761. mPlayState == aOther.mPlayState &&
  2762. mIterationCount == aOther.mIterationCount;
  2763. }
  2764. // --------------------
  2765. // nsStyleDisplay
  2766. //
  2767. nsStyleDisplay::nsStyleDisplay(StyleStructContext aContext)
  2768. : mDisplay(StyleDisplay::Inline)
  2769. , mOriginalDisplay(StyleDisplay::Inline)
  2770. , mContain(NS_STYLE_CONTAIN_NONE)
  2771. , mAppearance(NS_THEME_NONE)
  2772. , mPosition(NS_STYLE_POSITION_STATIC)
  2773. , mFloat(StyleFloat::None)
  2774. , mOriginalFloat(StyleFloat::None)
  2775. , mBreakType(StyleClear::None)
  2776. , mBreakInside(NS_STYLE_PAGE_BREAK_AUTO)
  2777. , mBreakBefore(false)
  2778. , mBreakAfter(false)
  2779. , mOverflowX(NS_STYLE_OVERFLOW_VISIBLE)
  2780. , mOverflowY(NS_STYLE_OVERFLOW_VISIBLE)
  2781. , mOverflowClipBox(NS_STYLE_OVERFLOW_CLIP_BOX_PADDING_BOX)
  2782. , mResize(NS_STYLE_RESIZE_NONE)
  2783. , mOrient(StyleOrient::Inline)
  2784. , mIsolation(NS_STYLE_ISOLATION_AUTO)
  2785. , mTopLayer(NS_STYLE_TOP_LAYER_NONE)
  2786. , mWillChangeBitField(0)
  2787. , mTouchAction(NS_STYLE_TOUCH_ACTION_AUTO)
  2788. , mScrollBehavior(NS_STYLE_SCROLL_BEHAVIOR_AUTO)
  2789. , mScrollSnapTypeX(NS_STYLE_SCROLL_SNAP_TYPE_NONE)
  2790. , mScrollSnapTypeY(NS_STYLE_SCROLL_SNAP_TYPE_NONE)
  2791. , mScrollSnapPointsX(eStyleUnit_None)
  2792. , mScrollSnapPointsY(eStyleUnit_None)
  2793. , mBackfaceVisibility(NS_STYLE_BACKFACE_VISIBILITY_VISIBLE)
  2794. , mTransformStyle(NS_STYLE_TRANSFORM_STYLE_FLAT)
  2795. , mTransformBox(NS_STYLE_TRANSFORM_BOX_BORDER_BOX)
  2796. , mSpecifiedTransform(nullptr)
  2797. , mTransformOrigin{ {0.5f, eStyleUnit_Percent}, // Transform is centered on origin
  2798. {0.5f, eStyleUnit_Percent},
  2799. {0, nsStyleCoord::CoordConstructor} }
  2800. , mChildPerspective(eStyleUnit_None)
  2801. , mPerspectiveOrigin{ {0.5f, eStyleUnit_Percent},
  2802. {0.5f, eStyleUnit_Percent} }
  2803. , mVerticalAlign(NS_STYLE_VERTICAL_ALIGN_BASELINE, eStyleUnit_Enumerated)
  2804. , mTransitions(nsStyleAutoArray<StyleTransition>::WITH_SINGLE_INITIAL_ELEMENT)
  2805. , mTransitionTimingFunctionCount(1)
  2806. , mTransitionDurationCount(1)
  2807. , mTransitionDelayCount(1)
  2808. , mTransitionPropertyCount(1)
  2809. , mAnimations(nsStyleAutoArray<StyleAnimation>::WITH_SINGLE_INITIAL_ELEMENT)
  2810. , mAnimationTimingFunctionCount(1)
  2811. , mAnimationDurationCount(1)
  2812. , mAnimationDelayCount(1)
  2813. , mAnimationNameCount(1)
  2814. , mAnimationDirectionCount(1)
  2815. , mAnimationFillModeCount(1)
  2816. , mAnimationPlayStateCount(1)
  2817. , mAnimationIterationCountCount(1)
  2818. {
  2819. MOZ_COUNT_CTOR(nsStyleDisplay);
  2820. // Initial value for mScrollSnapDestination is "0px 0px"
  2821. mScrollSnapDestination.SetInitialZeroValues();
  2822. mTransitions[0].SetInitialValues();
  2823. mAnimations[0].SetInitialValues();
  2824. }
  2825. nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource)
  2826. : mBinding(aSource.mBinding)
  2827. , mDisplay(aSource.mDisplay)
  2828. , mOriginalDisplay(aSource.mOriginalDisplay)
  2829. , mContain(aSource.mContain)
  2830. , mAppearance(aSource.mAppearance)
  2831. , mPosition(aSource.mPosition)
  2832. , mFloat(aSource.mFloat)
  2833. , mOriginalFloat(aSource.mOriginalFloat)
  2834. , mBreakType(aSource.mBreakType)
  2835. , mBreakInside(aSource.mBreakInside)
  2836. , mBreakBefore(aSource.mBreakBefore)
  2837. , mBreakAfter(aSource.mBreakAfter)
  2838. , mOverflowX(aSource.mOverflowX)
  2839. , mOverflowY(aSource.mOverflowY)
  2840. , mOverflowClipBox(aSource.mOverflowClipBox)
  2841. , mResize(aSource.mResize)
  2842. , mOrient(aSource.mOrient)
  2843. , mIsolation(aSource.mIsolation)
  2844. , mTopLayer(aSource.mTopLayer)
  2845. , mWillChangeBitField(aSource.mWillChangeBitField)
  2846. , mWillChange(aSource.mWillChange)
  2847. , mTouchAction(aSource.mTouchAction)
  2848. , mScrollBehavior(aSource.mScrollBehavior)
  2849. , mScrollSnapTypeX(aSource.mScrollSnapTypeX)
  2850. , mScrollSnapTypeY(aSource.mScrollSnapTypeY)
  2851. , mScrollSnapPointsX(aSource.mScrollSnapPointsX)
  2852. , mScrollSnapPointsY(aSource.mScrollSnapPointsY)
  2853. , mScrollSnapDestination(aSource.mScrollSnapDestination)
  2854. , mScrollSnapCoordinate(aSource.mScrollSnapCoordinate)
  2855. , mBackfaceVisibility(aSource.mBackfaceVisibility)
  2856. , mTransformStyle(aSource.mTransformStyle)
  2857. , mTransformBox(aSource.mTransformBox)
  2858. , mSpecifiedTransform(aSource.mSpecifiedTransform)
  2859. , mTransformOrigin{ aSource.mTransformOrigin[0],
  2860. aSource.mTransformOrigin[1],
  2861. aSource.mTransformOrigin[2] }
  2862. , mChildPerspective(aSource.mChildPerspective)
  2863. , mPerspectiveOrigin{ aSource.mPerspectiveOrigin[0],
  2864. aSource.mPerspectiveOrigin[1] }
  2865. , mVerticalAlign(aSource.mVerticalAlign)
  2866. , mTransitions(aSource.mTransitions)
  2867. , mTransitionTimingFunctionCount(aSource.mTransitionTimingFunctionCount)
  2868. , mTransitionDurationCount(aSource.mTransitionDurationCount)
  2869. , mTransitionDelayCount(aSource.mTransitionDelayCount)
  2870. , mTransitionPropertyCount(aSource.mTransitionPropertyCount)
  2871. , mAnimations(aSource.mAnimations)
  2872. , mAnimationTimingFunctionCount(aSource.mAnimationTimingFunctionCount)
  2873. , mAnimationDurationCount(aSource.mAnimationDurationCount)
  2874. , mAnimationDelayCount(aSource.mAnimationDelayCount)
  2875. , mAnimationNameCount(aSource.mAnimationNameCount)
  2876. , mAnimationDirectionCount(aSource.mAnimationDirectionCount)
  2877. , mAnimationFillModeCount(aSource.mAnimationFillModeCount)
  2878. , mAnimationPlayStateCount(aSource.mAnimationPlayStateCount)
  2879. , mAnimationIterationCountCount(aSource.mAnimationIterationCountCount)
  2880. , mShapeOutside(aSource.mShapeOutside)
  2881. {
  2882. MOZ_COUNT_CTOR(nsStyleDisplay);
  2883. }
  2884. nsChangeHint
  2885. nsStyleDisplay::CalcDifference(const nsStyleDisplay& aNewData) const
  2886. {
  2887. nsChangeHint hint = nsChangeHint(0);
  2888. if (!DefinitelyEqualURIsAndPrincipal(mBinding, aNewData.mBinding)
  2889. || mPosition != aNewData.mPosition
  2890. || mDisplay != aNewData.mDisplay
  2891. || mContain != aNewData.mContain
  2892. || (mFloat == StyleFloat::None) != (aNewData.mFloat == StyleFloat::None)
  2893. || mScrollBehavior != aNewData.mScrollBehavior
  2894. || mScrollSnapTypeX != aNewData.mScrollSnapTypeX
  2895. || mScrollSnapTypeY != aNewData.mScrollSnapTypeY
  2896. || mScrollSnapPointsX != aNewData.mScrollSnapPointsX
  2897. || mScrollSnapPointsY != aNewData.mScrollSnapPointsY
  2898. || mScrollSnapDestination != aNewData.mScrollSnapDestination
  2899. || mTopLayer != aNewData.mTopLayer
  2900. || mResize != aNewData.mResize) {
  2901. hint |= nsChangeHint_ReconstructFrame;
  2902. }
  2903. if (mOverflowX != aNewData.mOverflowX
  2904. || mOverflowY != aNewData.mOverflowY) {
  2905. hint |= nsChangeHint_ScrollbarChange;
  2906. }
  2907. /* Note: When mScrollBehavior, mScrollSnapTypeX, mScrollSnapTypeY,
  2908. * mScrollSnapPointsX, mScrollSnapPointsY, or mScrollSnapDestination are
  2909. * changed, nsChangeHint_NeutralChange is not sufficient to enter
  2910. * nsCSSFrameConstructor::PropagateScrollToViewport. By using the same hint
  2911. * as used when the overflow css property changes,
  2912. * nsChangeHint_ReconstructFrame, PropagateScrollToViewport will be called.
  2913. *
  2914. * The scroll-behavior css property is not expected to change often (the
  2915. * CSSOM-View DOM methods are likely to be used in those cases); however,
  2916. * if this does become common perhaps a faster-path might be worth while.
  2917. */
  2918. if ((mAppearance == NS_THEME_TEXTFIELD &&
  2919. aNewData.mAppearance != NS_THEME_TEXTFIELD) ||
  2920. (mAppearance != NS_THEME_TEXTFIELD &&
  2921. aNewData.mAppearance == NS_THEME_TEXTFIELD)) {
  2922. // This is for <input type=number> where we allow authors to specify a
  2923. // |-moz-appearance:textfield| to get a control without a spinner. (The
  2924. // spinner is present for |-moz-appearance:number-input| but also other
  2925. // values such as 'none'.) We need to reframe since we want to use
  2926. // nsTextControlFrame instead of nsNumberControlFrame if the author
  2927. // specifies 'textfield'.
  2928. return nsChangeHint_ReconstructFrame;
  2929. }
  2930. if (mFloat != aNewData.mFloat) {
  2931. // Changing which side we float on doesn't affect descendants directly
  2932. hint |= nsChangeHint_AllReflowHints &
  2933. ~(nsChangeHint_ClearDescendantIntrinsics |
  2934. nsChangeHint_NeedDirtyReflow);
  2935. }
  2936. if (mVerticalAlign != aNewData.mVerticalAlign) {
  2937. // XXX Can this just be AllReflowHints + RepaintFrame, and be included in
  2938. // the block below?
  2939. hint |= NS_STYLE_HINT_REFLOW;
  2940. }
  2941. // XXX the following is conservative, for now: changing float breaking shouldn't
  2942. // necessarily require a repaint, reflow should suffice.
  2943. if (mBreakType != aNewData.mBreakType
  2944. || mBreakInside != aNewData.mBreakInside
  2945. || mBreakBefore != aNewData.mBreakBefore
  2946. || mBreakAfter != aNewData.mBreakAfter
  2947. || mAppearance != aNewData.mAppearance
  2948. || mOrient != aNewData.mOrient
  2949. || mOverflowClipBox != aNewData.mOverflowClipBox) {
  2950. hint |= nsChangeHint_AllReflowHints |
  2951. nsChangeHint_RepaintFrame;
  2952. }
  2953. if (mIsolation != aNewData.mIsolation) {
  2954. hint |= nsChangeHint_RepaintFrame;
  2955. }
  2956. /* If we've added or removed the transform property, we need to reconstruct the frame to add
  2957. * or remove the view object, and also to handle abs-pos and fixed-pos containers.
  2958. */
  2959. if (HasTransformStyle() != aNewData.HasTransformStyle()) {
  2960. // We do not need to apply nsChangeHint_UpdateTransformLayer since
  2961. // nsChangeHint_RepaintFrame will forcibly invalidate the frame area and
  2962. // ensure layers are rebuilt (or removed).
  2963. hint |= nsChangeHint_UpdateContainingBlock |
  2964. nsChangeHint_AddOrRemoveTransform |
  2965. nsChangeHint_UpdateOverflow |
  2966. nsChangeHint_RepaintFrame;
  2967. } else {
  2968. /* Otherwise, if we've kept the property lying around and we already had a
  2969. * transform, we need to see whether or not we've changed the transform.
  2970. * If so, we need to recompute its overflow rect (which probably changed
  2971. * if the transform changed) and to redraw within the bounds of that new
  2972. * overflow rect.
  2973. *
  2974. * If the property isn't present in either style struct, we still do the
  2975. * comparisons but turn all the resulting change hints into
  2976. * nsChangeHint_NeutralChange.
  2977. */
  2978. nsChangeHint transformHint = nsChangeHint(0);
  2979. if (!mSpecifiedTransform != !aNewData.mSpecifiedTransform ||
  2980. (mSpecifiedTransform &&
  2981. *mSpecifiedTransform != *aNewData.mSpecifiedTransform)) {
  2982. transformHint |= nsChangeHint_UpdateTransformLayer;
  2983. if (mSpecifiedTransform &&
  2984. aNewData.mSpecifiedTransform) {
  2985. transformHint |= nsChangeHint_UpdatePostTransformOverflow;
  2986. } else {
  2987. transformHint |= nsChangeHint_UpdateOverflow;
  2988. }
  2989. }
  2990. const nsChangeHint kUpdateOverflowAndRepaintHint =
  2991. nsChangeHint_UpdateOverflow | nsChangeHint_RepaintFrame;
  2992. for (uint8_t index = 0; index < 3; ++index) {
  2993. if (mTransformOrigin[index] != aNewData.mTransformOrigin[index]) {
  2994. transformHint |= nsChangeHint_UpdateTransformLayer |
  2995. nsChangeHint_UpdatePostTransformOverflow;
  2996. break;
  2997. }
  2998. }
  2999. for (uint8_t index = 0; index < 2; ++index) {
  3000. if (mPerspectiveOrigin[index] != aNewData.mPerspectiveOrigin[index]) {
  3001. transformHint |= kUpdateOverflowAndRepaintHint;
  3002. break;
  3003. }
  3004. }
  3005. if (HasPerspectiveStyle() != aNewData.HasPerspectiveStyle()) {
  3006. // A change from/to being a containing block for position:fixed.
  3007. hint |= nsChangeHint_UpdateContainingBlock;
  3008. }
  3009. if (mChildPerspective != aNewData.mChildPerspective ||
  3010. mTransformStyle != aNewData.mTransformStyle ||
  3011. mTransformBox != aNewData.mTransformBox) {
  3012. transformHint |= kUpdateOverflowAndRepaintHint;
  3013. }
  3014. if (mBackfaceVisibility != aNewData.mBackfaceVisibility) {
  3015. transformHint |= nsChangeHint_RepaintFrame;
  3016. }
  3017. if (transformHint) {
  3018. if (HasTransformStyle()) {
  3019. hint |= transformHint;
  3020. } else {
  3021. hint |= nsChangeHint_NeutralChange;
  3022. }
  3023. }
  3024. }
  3025. // Note that the HasTransformStyle() != aNewData.HasTransformStyle()
  3026. // test above handles relevant changes in the
  3027. // NS_STYLE_WILL_CHANGE_TRANSFORM bit, which in turn handles frame
  3028. // reconstruction for changes in the containing block of
  3029. // fixed-positioned elements.
  3030. uint8_t willChangeBitsChanged =
  3031. mWillChangeBitField ^ aNewData.mWillChangeBitField;
  3032. if (willChangeBitsChanged & (NS_STYLE_WILL_CHANGE_STACKING_CONTEXT |
  3033. NS_STYLE_WILL_CHANGE_SCROLL |
  3034. NS_STYLE_WILL_CHANGE_OPACITY)) {
  3035. hint |= nsChangeHint_RepaintFrame;
  3036. }
  3037. if (willChangeBitsChanged & NS_STYLE_WILL_CHANGE_FIXPOS_CB) {
  3038. hint |= nsChangeHint_UpdateContainingBlock;
  3039. }
  3040. // If touch-action is changed, we need to regenerate the event regions on
  3041. // the layers and send it over to the compositor for APZ to handle.
  3042. if (mTouchAction != aNewData.mTouchAction) {
  3043. hint |= nsChangeHint_RepaintFrame;
  3044. }
  3045. // Note: Our current behavior for handling changes to the
  3046. // transition-duration, transition-delay, and transition-timing-function
  3047. // properties is to do nothing. In other words, the transition
  3048. // property that matters is what it is when the transition begins, and
  3049. // we don't stop a transition later because the transition property
  3050. // changed.
  3051. // We do handle changes to transition-property, but we don't need to
  3052. // bother with anything here, since the transition manager is notified
  3053. // of any style context change anyway.
  3054. // Note: Likewise, for animation-*, the animation manager gets
  3055. // notified about every new style context constructed, and it uses
  3056. // that opportunity to handle dynamic changes appropriately.
  3057. // But we still need to return nsChangeHint_NeutralChange for these
  3058. // properties, since some data did change in the style struct.
  3059. if (!hint &&
  3060. (mOriginalDisplay != aNewData.mOriginalDisplay ||
  3061. mOriginalFloat != aNewData.mOriginalFloat ||
  3062. mTransitions != aNewData.mTransitions ||
  3063. mTransitionTimingFunctionCount !=
  3064. aNewData.mTransitionTimingFunctionCount ||
  3065. mTransitionDurationCount != aNewData.mTransitionDurationCount ||
  3066. mTransitionDelayCount != aNewData.mTransitionDelayCount ||
  3067. mTransitionPropertyCount != aNewData.mTransitionPropertyCount ||
  3068. mAnimations != aNewData.mAnimations ||
  3069. mAnimationTimingFunctionCount != aNewData.mAnimationTimingFunctionCount ||
  3070. mAnimationDurationCount != aNewData.mAnimationDurationCount ||
  3071. mAnimationDelayCount != aNewData.mAnimationDelayCount ||
  3072. mAnimationNameCount != aNewData.mAnimationNameCount ||
  3073. mAnimationDirectionCount != aNewData.mAnimationDirectionCount ||
  3074. mAnimationFillModeCount != aNewData.mAnimationFillModeCount ||
  3075. mAnimationPlayStateCount != aNewData.mAnimationPlayStateCount ||
  3076. mAnimationIterationCountCount != aNewData.mAnimationIterationCountCount ||
  3077. mScrollSnapCoordinate != aNewData.mScrollSnapCoordinate ||
  3078. mShapeOutside != aNewData.mShapeOutside)) {
  3079. hint |= nsChangeHint_NeutralChange;
  3080. }
  3081. return hint;
  3082. }
  3083. // --------------------
  3084. // nsStyleVisibility
  3085. //
  3086. nsStyleVisibility::nsStyleVisibility(StyleStructContext aContext)
  3087. : mDirection(aContext.GetBidi() == IBMBIDI_TEXTDIRECTION_RTL
  3088. ? NS_STYLE_DIRECTION_RTL
  3089. : NS_STYLE_DIRECTION_LTR)
  3090. , mVisible(NS_STYLE_VISIBILITY_VISIBLE)
  3091. , mImageRendering(NS_STYLE_IMAGE_RENDERING_AUTO)
  3092. , mWritingMode(NS_STYLE_WRITING_MODE_HORIZONTAL_TB)
  3093. , mTextOrientation(NS_STYLE_TEXT_ORIENTATION_MIXED)
  3094. , mColorAdjust(NS_STYLE_COLOR_ADJUST_ECONOMY)
  3095. {
  3096. MOZ_COUNT_CTOR(nsStyleVisibility);
  3097. }
  3098. nsStyleVisibility::nsStyleVisibility(const nsStyleVisibility& aSource)
  3099. : mImageOrientation(aSource.mImageOrientation)
  3100. , mDirection(aSource.mDirection)
  3101. , mVisible(aSource.mVisible)
  3102. , mImageRendering(aSource.mImageRendering)
  3103. , mWritingMode(aSource.mWritingMode)
  3104. , mTextOrientation(aSource.mTextOrientation)
  3105. , mColorAdjust(aSource.mColorAdjust)
  3106. {
  3107. MOZ_COUNT_CTOR(nsStyleVisibility);
  3108. }
  3109. nsChangeHint
  3110. nsStyleVisibility::CalcDifference(const nsStyleVisibility& aNewData) const
  3111. {
  3112. nsChangeHint hint = nsChangeHint(0);
  3113. if (mDirection != aNewData.mDirection || mWritingMode != aNewData.mWritingMode) {
  3114. // It's important that a change in mWritingMode results in frame
  3115. // reconstruction, because it may affect intrinsic size (see
  3116. // nsSubDocumentFrame::GetIntrinsicISize/BSize).
  3117. hint |= nsChangeHint_ReconstructFrame;
  3118. } else {
  3119. if ((mImageOrientation != aNewData.mImageOrientation)) {
  3120. hint |= nsChangeHint_AllReflowHints |
  3121. nsChangeHint_RepaintFrame;
  3122. }
  3123. if (mVisible != aNewData.mVisible) {
  3124. if ((NS_STYLE_VISIBILITY_COLLAPSE == mVisible) ||
  3125. (NS_STYLE_VISIBILITY_COLLAPSE == aNewData.mVisible)) {
  3126. hint |= NS_STYLE_HINT_REFLOW;
  3127. } else {
  3128. hint |= NS_STYLE_HINT_VISUAL;
  3129. }
  3130. }
  3131. if (mTextOrientation != aNewData.mTextOrientation) {
  3132. hint |= NS_STYLE_HINT_REFLOW;
  3133. }
  3134. if (mImageRendering != aNewData.mImageRendering) {
  3135. hint |= nsChangeHint_RepaintFrame;
  3136. }
  3137. if (mColorAdjust != aNewData.mColorAdjust) {
  3138. // color-adjust only affects media where dynamic changes can't happen.
  3139. hint |= nsChangeHint_NeutralChange;
  3140. }
  3141. }
  3142. return hint;
  3143. }
  3144. nsStyleContentData::~nsStyleContentData()
  3145. {
  3146. MOZ_COUNT_DTOR(nsStyleContentData);
  3147. MOZ_ASSERT(!mImageTracked,
  3148. "nsStyleContentData being destroyed while still tracking image!");
  3149. if (mType == eStyleContentType_Image) {
  3150. NS_IF_RELEASE(mContent.mImage);
  3151. } else if (mType == eStyleContentType_Counter ||
  3152. mType == eStyleContentType_Counters) {
  3153. mContent.mCounters->Release();
  3154. } else if (mContent.mString) {
  3155. free(mContent.mString);
  3156. }
  3157. }
  3158. nsStyleContentData::nsStyleContentData(const nsStyleContentData& aOther)
  3159. : mType(aOther.mType)
  3160. #ifdef DEBUG
  3161. , mImageTracked(false)
  3162. #endif
  3163. {
  3164. MOZ_COUNT_CTOR(nsStyleContentData);
  3165. if (mType == eStyleContentType_Image) {
  3166. mContent.mImage = aOther.mContent.mImage;
  3167. NS_IF_ADDREF(mContent.mImage);
  3168. } else if (mType == eStyleContentType_Counter ||
  3169. mType == eStyleContentType_Counters) {
  3170. mContent.mCounters = aOther.mContent.mCounters;
  3171. mContent.mCounters->AddRef();
  3172. } else if (aOther.mContent.mString) {
  3173. mContent.mString = NS_strdup(aOther.mContent.mString);
  3174. } else {
  3175. mContent.mString = nullptr;
  3176. }
  3177. }
  3178. nsStyleContentData&
  3179. nsStyleContentData::operator=(const nsStyleContentData& aOther)
  3180. {
  3181. if (this == &aOther) {
  3182. return *this;
  3183. }
  3184. this->~nsStyleContentData();
  3185. new (this) nsStyleContentData(aOther);
  3186. return *this;
  3187. }
  3188. bool
  3189. nsStyleContentData::operator==(const nsStyleContentData& aOther) const
  3190. {
  3191. if (mType != aOther.mType) {
  3192. return false;
  3193. }
  3194. if (mType == eStyleContentType_Image) {
  3195. if (!mContent.mImage || !aOther.mContent.mImage) {
  3196. return mContent.mImage == aOther.mContent.mImage;
  3197. }
  3198. bool eq;
  3199. nsCOMPtr<nsIURI> thisURI, otherURI;
  3200. mContent.mImage->GetURI(getter_AddRefs(thisURI));
  3201. aOther.mContent.mImage->GetURI(getter_AddRefs(otherURI));
  3202. return thisURI == otherURI || // handles null==null
  3203. (thisURI && otherURI &&
  3204. NS_SUCCEEDED(thisURI->Equals(otherURI, &eq)) &&
  3205. eq);
  3206. }
  3207. if (mType == eStyleContentType_Counter ||
  3208. mType == eStyleContentType_Counters) {
  3209. return *mContent.mCounters == *aOther.mContent.mCounters;
  3210. }
  3211. return safe_strcmp(mContent.mString, aOther.mContent.mString) == 0;
  3212. }
  3213. void
  3214. nsStyleContentData::TrackImage(ImageTracker* aImageTracker)
  3215. {
  3216. // Sanity
  3217. MOZ_ASSERT(!mImageTracked, "Already tracking image!");
  3218. MOZ_ASSERT(mType == eStyleContentType_Image,
  3219. "Trying to do image tracking on non-image!");
  3220. MOZ_ASSERT(mContent.mImage,
  3221. "Can't track image when there isn't one!");
  3222. aImageTracker->Add(mContent.mImage);
  3223. // Mark state
  3224. #ifdef DEBUG
  3225. mImageTracked = true;
  3226. #endif
  3227. }
  3228. void
  3229. nsStyleContentData::UntrackImage(ImageTracker* aImageTracker)
  3230. {
  3231. // Sanity
  3232. MOZ_ASSERT(mImageTracked, "Image not tracked!");
  3233. MOZ_ASSERT(mType == eStyleContentType_Image,
  3234. "Trying to do image tracking on non-image!");
  3235. MOZ_ASSERT(mContent.mImage,
  3236. "Can't untrack image when there isn't one!");
  3237. aImageTracker->Remove(mContent.mImage);
  3238. // Mark state
  3239. #ifdef DEBUG
  3240. mImageTracked = false;
  3241. #endif
  3242. }
  3243. //-----------------------
  3244. // nsStyleContent
  3245. //
  3246. nsStyleContent::nsStyleContent(StyleStructContext aContext)
  3247. {
  3248. MOZ_COUNT_CTOR(nsStyleContent);
  3249. }
  3250. nsStyleContent::~nsStyleContent()
  3251. {
  3252. MOZ_COUNT_DTOR(nsStyleContent);
  3253. }
  3254. void
  3255. nsStyleContent::Destroy(nsPresContext* aContext)
  3256. {
  3257. // Unregister any images we might have with the document.
  3258. for (auto& content : mContents) {
  3259. if (content.mType == eStyleContentType_Image && content.mContent.mImage) {
  3260. content.UntrackImage(aContext->Document()->ImageTracker());
  3261. }
  3262. }
  3263. this->~nsStyleContent();
  3264. aContext->PresShell()->FreeByObjectID(eArenaObjectID_nsStyleContent, this);
  3265. }
  3266. nsStyleContent::nsStyleContent(const nsStyleContent& aSource)
  3267. : mContents(aSource.mContents)
  3268. , mIncrements(aSource.mIncrements)
  3269. , mResets(aSource.mResets)
  3270. {
  3271. MOZ_COUNT_CTOR(nsStyleContent);
  3272. }
  3273. nsChangeHint
  3274. nsStyleContent::CalcDifference(const nsStyleContent& aNewData) const
  3275. {
  3276. // In ElementRestyler::Restyle we assume that if there's no existing
  3277. // ::before or ::after and we don't have to restyle children of the
  3278. // node then we can't end up with a ::before or ::after due to the
  3279. // restyle of the node itself. That's not quite true, but the only
  3280. // exception to the above is when the 'content' property of the node
  3281. // changes and the pseudo-element inherits the changed value. Since
  3282. // the code here triggers a frame change on the node in that case,
  3283. // the optimization in ElementRestyler::Restyle is ok. But if we ever
  3284. // change this code to not reconstruct frames on changes to the
  3285. // 'content' property, then we will need to revisit the optimization
  3286. // in ElementRestyler::Restyle.
  3287. // Unfortunately we need to reframe even if the content lengths are the same;
  3288. // a simple reflow will not pick up different text or different image URLs,
  3289. // since we set all that up in the CSSFrameConstructor
  3290. if (mContents != aNewData.mContents ||
  3291. mIncrements != aNewData.mIncrements ||
  3292. mResets != aNewData.mResets) {
  3293. return nsChangeHint_ReconstructFrame;
  3294. }
  3295. return nsChangeHint(0);
  3296. }
  3297. // --------------------
  3298. // nsStyleTextReset
  3299. //
  3300. nsStyleTextReset::nsStyleTextReset(StyleStructContext aContext)
  3301. : mTextDecorationLine(NS_STYLE_TEXT_DECORATION_LINE_NONE)
  3302. , mTextDecorationStyle(NS_STYLE_TEXT_DECORATION_STYLE_SOLID)
  3303. , mUnicodeBidi(NS_STYLE_UNICODE_BIDI_NORMAL)
  3304. , mInitialLetterSink(0)
  3305. , mInitialLetterSize(0.0f)
  3306. , mTextDecorationColor(StyleComplexColor::CurrentColor())
  3307. {
  3308. MOZ_COUNT_CTOR(nsStyleTextReset);
  3309. }
  3310. nsStyleTextReset::nsStyleTextReset(const nsStyleTextReset& aSource)
  3311. {
  3312. MOZ_COUNT_CTOR(nsStyleTextReset);
  3313. *this = aSource;
  3314. }
  3315. nsStyleTextReset::~nsStyleTextReset()
  3316. {
  3317. MOZ_COUNT_DTOR(nsStyleTextReset);
  3318. }
  3319. nsChangeHint
  3320. nsStyleTextReset::CalcDifference(const nsStyleTextReset& aNewData) const
  3321. {
  3322. if (mUnicodeBidi != aNewData.mUnicodeBidi ||
  3323. mInitialLetterSink != aNewData.mInitialLetterSink ||
  3324. mInitialLetterSize != aNewData.mInitialLetterSize) {
  3325. return NS_STYLE_HINT_REFLOW;
  3326. }
  3327. if (mTextDecorationLine != aNewData.mTextDecorationLine ||
  3328. mTextDecorationStyle != aNewData.mTextDecorationStyle) {
  3329. // Changes to our text-decoration line can impact our overflow area &
  3330. // also our descendants' overflow areas (particularly for text-frame
  3331. // descendants). So, we update those areas & trigger a repaint.
  3332. return nsChangeHint_RepaintFrame |
  3333. nsChangeHint_UpdateSubtreeOverflow |
  3334. nsChangeHint_SchedulePaint;
  3335. }
  3336. // Repaint for decoration color changes
  3337. if (mTextDecorationColor != aNewData.mTextDecorationColor) {
  3338. return nsChangeHint_RepaintFrame;
  3339. }
  3340. if (mTextOverflow != aNewData.mTextOverflow) {
  3341. return nsChangeHint_RepaintFrame;
  3342. }
  3343. return nsChangeHint(0);
  3344. }
  3345. // Returns true if the given shadow-arrays are equal.
  3346. static bool
  3347. AreShadowArraysEqual(nsCSSShadowArray* lhs,
  3348. nsCSSShadowArray* rhs)
  3349. {
  3350. if (lhs == rhs) {
  3351. return true;
  3352. }
  3353. if (!lhs || !rhs || lhs->Length() != rhs->Length()) {
  3354. return false;
  3355. }
  3356. for (uint32_t i = 0; i < lhs->Length(); ++i) {
  3357. if (*lhs->ShadowAt(i) != *rhs->ShadowAt(i)) {
  3358. return false;
  3359. }
  3360. }
  3361. return true;
  3362. }
  3363. // --------------------
  3364. // nsStyleText
  3365. //
  3366. nsStyleText::nsStyleText(StyleStructContext aContext)
  3367. : mTextAlign(NS_STYLE_TEXT_ALIGN_START)
  3368. , mTextAlignLast(NS_STYLE_TEXT_ALIGN_AUTO)
  3369. , mTextAlignTrue(false)
  3370. , mTextAlignLastTrue(false)
  3371. , mTextJustify(StyleTextJustify::Auto)
  3372. , mTextTransform(NS_STYLE_TEXT_TRANSFORM_NONE)
  3373. , mWhiteSpace(NS_STYLE_WHITESPACE_NORMAL)
  3374. , mWordBreak(NS_STYLE_WORDBREAK_NORMAL)
  3375. , mOverflowWrap(NS_STYLE_OVERFLOWWRAP_NORMAL)
  3376. , mHyphens(NS_STYLE_HYPHENS_MANUAL)
  3377. , mRubyAlign(NS_STYLE_RUBY_ALIGN_SPACE_AROUND)
  3378. , mRubyPosition(NS_STYLE_RUBY_POSITION_OVER)
  3379. , mTextSizeAdjust(NS_STYLE_TEXT_SIZE_ADJUST_AUTO)
  3380. , mTextCombineUpright(NS_STYLE_TEXT_COMBINE_UPRIGHT_NONE)
  3381. , mControlCharacterVisibility(nsCSSParser::ControlCharVisibilityDefault())
  3382. , mTextEmphasisStyle(NS_STYLE_TEXT_EMPHASIS_STYLE_NONE)
  3383. , mTextRendering(NS_STYLE_TEXT_RENDERING_AUTO)
  3384. , mTextEmphasisColor(StyleComplexColor::CurrentColor())
  3385. , mWebkitTextFillColor(StyleComplexColor::CurrentColor())
  3386. , mWebkitTextStrokeColor(StyleComplexColor::CurrentColor())
  3387. , mTabSize(float(NS_STYLE_TABSIZE_INITIAL), eStyleUnit_Factor)
  3388. , mWordSpacing(0, nsStyleCoord::CoordConstructor)
  3389. , mLetterSpacing(eStyleUnit_Normal)
  3390. , mLineHeight(eStyleUnit_Normal)
  3391. , mTextIndent(0, nsStyleCoord::CoordConstructor)
  3392. , mWebkitTextStrokeWidth(0, nsStyleCoord::CoordConstructor)
  3393. , mTextShadow(nullptr)
  3394. {
  3395. MOZ_COUNT_CTOR(nsStyleText);
  3396. nsCOMPtr<nsIAtom> language = aContext.GetContentLanguage();
  3397. mTextEmphasisPosition = language &&
  3398. nsStyleUtil::MatchesLanguagePrefix(language, u"zh") ?
  3399. NS_STYLE_TEXT_EMPHASIS_POSITION_DEFAULT_ZH :
  3400. NS_STYLE_TEXT_EMPHASIS_POSITION_DEFAULT;
  3401. }
  3402. nsStyleText::nsStyleText(const nsStyleText& aSource)
  3403. : mTextAlign(aSource.mTextAlign)
  3404. , mTextAlignLast(aSource.mTextAlignLast)
  3405. , mTextAlignTrue(false)
  3406. , mTextAlignLastTrue(false)
  3407. , mTextJustify(aSource.mTextJustify)
  3408. , mTextTransform(aSource.mTextTransform)
  3409. , mWhiteSpace(aSource.mWhiteSpace)
  3410. , mWordBreak(aSource.mWordBreak)
  3411. , mOverflowWrap(aSource.mOverflowWrap)
  3412. , mHyphens(aSource.mHyphens)
  3413. , mRubyAlign(aSource.mRubyAlign)
  3414. , mRubyPosition(aSource.mRubyPosition)
  3415. , mTextSizeAdjust(aSource.mTextSizeAdjust)
  3416. , mTextCombineUpright(aSource.mTextCombineUpright)
  3417. , mControlCharacterVisibility(aSource.mControlCharacterVisibility)
  3418. , mTextEmphasisPosition(aSource.mTextEmphasisPosition)
  3419. , mTextEmphasisStyle(aSource.mTextEmphasisStyle)
  3420. , mTextRendering(aSource.mTextRendering)
  3421. , mTextEmphasisColor(aSource.mTextEmphasisColor)
  3422. , mWebkitTextFillColor(aSource.mWebkitTextFillColor)
  3423. , mWebkitTextStrokeColor(aSource.mWebkitTextStrokeColor)
  3424. , mTabSize(aSource.mTabSize)
  3425. , mWordSpacing(aSource.mWordSpacing)
  3426. , mLetterSpacing(aSource.mLetterSpacing)
  3427. , mLineHeight(aSource.mLineHeight)
  3428. , mTextIndent(aSource.mTextIndent)
  3429. , mWebkitTextStrokeWidth(aSource.mWebkitTextStrokeWidth)
  3430. , mTextShadow(aSource.mTextShadow)
  3431. , mTextEmphasisStyleString(aSource.mTextEmphasisStyleString)
  3432. {
  3433. MOZ_COUNT_CTOR(nsStyleText);
  3434. }
  3435. nsStyleText::~nsStyleText()
  3436. {
  3437. MOZ_COUNT_DTOR(nsStyleText);
  3438. }
  3439. nsChangeHint
  3440. nsStyleText::CalcDifference(const nsStyleText& aNewData) const
  3441. {
  3442. if (WhiteSpaceOrNewlineIsSignificant() !=
  3443. aNewData.WhiteSpaceOrNewlineIsSignificant()) {
  3444. // This may require construction of suppressed text frames
  3445. return nsChangeHint_ReconstructFrame;
  3446. }
  3447. if (mTextCombineUpright != aNewData.mTextCombineUpright ||
  3448. mControlCharacterVisibility != aNewData.mControlCharacterVisibility) {
  3449. return nsChangeHint_ReconstructFrame;
  3450. }
  3451. if ((mTextAlign != aNewData.mTextAlign) ||
  3452. (mTextAlignLast != aNewData.mTextAlignLast) ||
  3453. (mTextAlignTrue != aNewData.mTextAlignTrue) ||
  3454. (mTextAlignLastTrue != aNewData.mTextAlignLastTrue) ||
  3455. (mTextTransform != aNewData.mTextTransform) ||
  3456. (mWhiteSpace != aNewData.mWhiteSpace) ||
  3457. (mWordBreak != aNewData.mWordBreak) ||
  3458. (mOverflowWrap != aNewData.mOverflowWrap) ||
  3459. (mHyphens != aNewData.mHyphens) ||
  3460. (mRubyAlign != aNewData.mRubyAlign) ||
  3461. (mRubyPosition != aNewData.mRubyPosition) ||
  3462. (mTextSizeAdjust != aNewData.mTextSizeAdjust) ||
  3463. (mLetterSpacing != aNewData.mLetterSpacing) ||
  3464. (mLineHeight != aNewData.mLineHeight) ||
  3465. (mTextJustify != aNewData.mTextJustify) ||
  3466. (mTextIndent != aNewData.mTextIndent) ||
  3467. (mWordSpacing != aNewData.mWordSpacing) ||
  3468. (mTabSize != aNewData.mTabSize)) {
  3469. return NS_STYLE_HINT_REFLOW;
  3470. }
  3471. if (HasTextEmphasis() != aNewData.HasTextEmphasis() ||
  3472. (HasTextEmphasis() &&
  3473. mTextEmphasisPosition != aNewData.mTextEmphasisPosition)) {
  3474. // Text emphasis position change could affect line height calculation.
  3475. return nsChangeHint_AllReflowHints |
  3476. nsChangeHint_RepaintFrame;
  3477. }
  3478. nsChangeHint hint = nsChangeHint(0);
  3479. // text-rendering changes require a reflow since they change SVG
  3480. // frames' rects.
  3481. if (mTextRendering != aNewData.mTextRendering) {
  3482. hint |= nsChangeHint_NeedReflow |
  3483. nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
  3484. nsChangeHint_RepaintFrame;
  3485. }
  3486. if (!AreShadowArraysEqual(mTextShadow, aNewData.mTextShadow) ||
  3487. mTextEmphasisStyle != aNewData.mTextEmphasisStyle ||
  3488. mTextEmphasisStyleString != aNewData.mTextEmphasisStyleString ||
  3489. mWebkitTextStrokeWidth != aNewData.mWebkitTextStrokeWidth) {
  3490. hint |= nsChangeHint_UpdateSubtreeOverflow |
  3491. nsChangeHint_SchedulePaint |
  3492. nsChangeHint_RepaintFrame;
  3493. // We don't add any other hints below.
  3494. return hint;
  3495. }
  3496. if (mTextEmphasisColor != aNewData.mTextEmphasisColor ||
  3497. mWebkitTextFillColor != aNewData.mWebkitTextFillColor ||
  3498. mWebkitTextStrokeColor != aNewData.mWebkitTextStrokeColor) {
  3499. hint |= nsChangeHint_SchedulePaint |
  3500. nsChangeHint_RepaintFrame;
  3501. }
  3502. if (hint) {
  3503. return hint;
  3504. }
  3505. if (mTextEmphasisPosition != aNewData.mTextEmphasisPosition) {
  3506. return nsChangeHint_NeutralChange;
  3507. }
  3508. return nsChangeHint(0);
  3509. }
  3510. LogicalSide
  3511. nsStyleText::TextEmphasisSide(WritingMode aWM) const
  3512. {
  3513. MOZ_ASSERT(
  3514. (!(mTextEmphasisPosition & NS_STYLE_TEXT_EMPHASIS_POSITION_LEFT) !=
  3515. !(mTextEmphasisPosition & NS_STYLE_TEXT_EMPHASIS_POSITION_RIGHT)) &&
  3516. (!(mTextEmphasisPosition & NS_STYLE_TEXT_EMPHASIS_POSITION_OVER) !=
  3517. !(mTextEmphasisPosition & NS_STYLE_TEXT_EMPHASIS_POSITION_UNDER)));
  3518. mozilla::Side side = aWM.IsVertical() ?
  3519. (mTextEmphasisPosition & NS_STYLE_TEXT_EMPHASIS_POSITION_LEFT
  3520. ? eSideLeft : eSideRight) :
  3521. (mTextEmphasisPosition & NS_STYLE_TEXT_EMPHASIS_POSITION_OVER
  3522. ? eSideTop : eSideBottom);
  3523. LogicalSide result = aWM.LogicalSideForPhysicalSide(side);
  3524. MOZ_ASSERT(IsBlock(result));
  3525. return result;
  3526. }
  3527. //-----------------------
  3528. // nsStyleUserInterface
  3529. //
  3530. nsCursorImage::nsCursorImage()
  3531. : mHaveHotspot(false)
  3532. , mHotspotX(0.0f)
  3533. , mHotspotY(0.0f)
  3534. {
  3535. }
  3536. nsCursorImage::nsCursorImage(const nsCursorImage& aOther)
  3537. : mHaveHotspot(aOther.mHaveHotspot)
  3538. , mHotspotX(aOther.mHotspotX)
  3539. , mHotspotY(aOther.mHotspotY)
  3540. {
  3541. SetImage(aOther.GetImage());
  3542. }
  3543. nsCursorImage::~nsCursorImage()
  3544. {
  3545. SetImage(nullptr);
  3546. }
  3547. nsCursorImage&
  3548. nsCursorImage::operator=(const nsCursorImage& aOther)
  3549. {
  3550. if (this != &aOther) {
  3551. mHaveHotspot = aOther.mHaveHotspot;
  3552. mHotspotX = aOther.mHotspotX;
  3553. mHotspotY = aOther.mHotspotY;
  3554. SetImage(aOther.GetImage());
  3555. }
  3556. return *this;
  3557. }
  3558. bool
  3559. nsCursorImage::operator==(const nsCursorImage& aOther) const
  3560. {
  3561. NS_ASSERTION(mHaveHotspot ||
  3562. (mHotspotX == 0 && mHotspotY == 0),
  3563. "expected mHotspot{X,Y} to be 0 when mHaveHotspot is false");
  3564. NS_ASSERTION(aOther.mHaveHotspot ||
  3565. (aOther.mHotspotX == 0 && aOther.mHotspotY == 0),
  3566. "expected mHotspot{X,Y} to be 0 when mHaveHotspot is false");
  3567. return mHaveHotspot == aOther.mHaveHotspot &&
  3568. mHotspotX == aOther.mHotspotX &&
  3569. mHotspotY == aOther.mHotspotY &&
  3570. EqualImages(mImage, aOther.mImage);
  3571. }
  3572. nsStyleUserInterface::nsStyleUserInterface(StyleStructContext aContext)
  3573. : mUserInput(StyleUserInput::Auto)
  3574. , mUserModify(StyleUserModify::ReadOnly)
  3575. , mUserFocus(StyleUserFocus::None)
  3576. , mPointerEvents(NS_STYLE_POINTER_EVENTS_AUTO)
  3577. , mCursor(NS_STYLE_CURSOR_AUTO)
  3578. , mCaretColor(StyleComplexColor::Auto())
  3579. , mScrollbarWidth(StyleScrollbarWidth::Auto)
  3580. {
  3581. MOZ_COUNT_CTOR(nsStyleUserInterface);
  3582. }
  3583. nsStyleUserInterface::nsStyleUserInterface(const nsStyleUserInterface& aSource)
  3584. : mUserInput(aSource.mUserInput)
  3585. , mUserModify(aSource.mUserModify)
  3586. , mUserFocus(aSource.mUserFocus)
  3587. , mPointerEvents(aSource.mPointerEvents)
  3588. , mCursor(aSource.mCursor)
  3589. , mCursorImages(aSource.mCursorImages)
  3590. , mCaretColor(aSource.mCaretColor)
  3591. , mScrollbarWidth(aSource.mScrollbarWidth)
  3592. {
  3593. MOZ_COUNT_CTOR(nsStyleUserInterface);
  3594. }
  3595. nsStyleUserInterface::~nsStyleUserInterface()
  3596. {
  3597. MOZ_COUNT_DTOR(nsStyleUserInterface);
  3598. }
  3599. nsChangeHint
  3600. nsStyleUserInterface::CalcDifference(const nsStyleUserInterface& aNewData) const
  3601. {
  3602. nsChangeHint hint = nsChangeHint(0);
  3603. if (mCursor != aNewData.mCursor) {
  3604. hint |= nsChangeHint_UpdateCursor;
  3605. }
  3606. // We could do better. But it wouldn't be worth it, URL-specified cursors are
  3607. // rare.
  3608. if (mCursorImages != aNewData.mCursorImages) {
  3609. hint |= nsChangeHint_UpdateCursor;
  3610. }
  3611. if (mPointerEvents != aNewData.mPointerEvents) {
  3612. // nsSVGPathGeometryFrame's mRect depends on stroke _and_ on the value
  3613. // of pointer-events. See nsSVGPathGeometryFrame::ReflowSVG's use of
  3614. // GetHitTestFlags. (Only a reflow, no visual change.)
  3615. hint |= nsChangeHint_NeedReflow |
  3616. nsChangeHint_NeedDirtyReflow; // XXX remove me: bug 876085
  3617. }
  3618. if (mUserModify != aNewData.mUserModify) {
  3619. hint |= NS_STYLE_HINT_VISUAL;
  3620. }
  3621. if (mUserInput != aNewData.mUserInput) {
  3622. if (StyleUserInput::None == mUserInput ||
  3623. StyleUserInput::None == aNewData.mUserInput) {
  3624. hint |= nsChangeHint_ReconstructFrame;
  3625. } else {
  3626. hint |= nsChangeHint_NeutralChange;
  3627. }
  3628. }
  3629. if (mUserFocus != aNewData.mUserFocus) {
  3630. hint |= nsChangeHint_NeutralChange;
  3631. }
  3632. if (mCaretColor != aNewData.mCaretColor) {
  3633. hint |= nsChangeHint_RepaintFrame;
  3634. }
  3635. if (mScrollbarWidth != aNewData.mScrollbarWidth) {
  3636. // For scrollbar-width change, we need some special handling similar
  3637. // to overflow properties. Specifically, we may need to reconstruct
  3638. // the scrollbar or force reflow of the viewport scrollbar.
  3639. hint |= nsChangeHint_ScrollbarChange;
  3640. }
  3641. return hint;
  3642. }
  3643. //-----------------------
  3644. // nsStyleUIReset
  3645. //
  3646. nsStyleUIReset::nsStyleUIReset(StyleStructContext aContext)
  3647. : mUserSelect(StyleUserSelect::Auto)
  3648. , mForceBrokenImageIcon(0)
  3649. , mIMEMode(NS_STYLE_IME_MODE_AUTO)
  3650. , mWindowDragging(StyleWindowDragging::Default)
  3651. , mWindowShadow(NS_STYLE_WINDOW_SHADOW_DEFAULT)
  3652. {
  3653. MOZ_COUNT_CTOR(nsStyleUIReset);
  3654. }
  3655. nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset& aSource)
  3656. : mUserSelect(aSource.mUserSelect)
  3657. , mForceBrokenImageIcon(aSource.mForceBrokenImageIcon)
  3658. , mIMEMode(aSource.mIMEMode)
  3659. , mWindowDragging(aSource.mWindowDragging)
  3660. , mWindowShadow(aSource.mWindowShadow)
  3661. {
  3662. MOZ_COUNT_CTOR(nsStyleUIReset);
  3663. }
  3664. nsStyleUIReset::~nsStyleUIReset()
  3665. {
  3666. MOZ_COUNT_DTOR(nsStyleUIReset);
  3667. }
  3668. nsChangeHint
  3669. nsStyleUIReset::CalcDifference(const nsStyleUIReset& aNewData) const
  3670. {
  3671. // ignore mIMEMode
  3672. if (mForceBrokenImageIcon != aNewData.mForceBrokenImageIcon) {
  3673. return nsChangeHint_ReconstructFrame;
  3674. }
  3675. if (mWindowShadow != aNewData.mWindowShadow) {
  3676. // We really need just an nsChangeHint_SyncFrameView, except
  3677. // on an ancestor of the frame, so we get that by doing a
  3678. // reflow.
  3679. return NS_STYLE_HINT_REFLOW;
  3680. }
  3681. if (mUserSelect != aNewData.mUserSelect) {
  3682. return NS_STYLE_HINT_VISUAL;
  3683. }
  3684. if (mWindowDragging != aNewData.mWindowDragging) {
  3685. return nsChangeHint_SchedulePaint;
  3686. }
  3687. return nsChangeHint(0);
  3688. }
  3689. //-----------------------
  3690. // nsStyleVariables
  3691. //
  3692. nsStyleVariables::nsStyleVariables(StyleStructContext aContext)
  3693. {
  3694. MOZ_COUNT_CTOR(nsStyleVariables);
  3695. }
  3696. nsStyleVariables::nsStyleVariables(const nsStyleVariables& aSource)
  3697. : mVariables(aSource.mVariables)
  3698. {
  3699. MOZ_COUNT_CTOR(nsStyleVariables);
  3700. }
  3701. nsStyleVariables::~nsStyleVariables()
  3702. {
  3703. MOZ_COUNT_DTOR(nsStyleVariables);
  3704. }
  3705. nsChangeHint
  3706. nsStyleVariables::CalcDifference(const nsStyleVariables& aNewData) const
  3707. {
  3708. return nsChangeHint(0);
  3709. }
  3710. //-----------------------
  3711. // nsStyleEffects
  3712. //
  3713. nsStyleEffects::nsStyleEffects(StyleStructContext aContext)
  3714. : mBoxShadow(nullptr)
  3715. , mClip(0, 0, 0, 0)
  3716. , mOpacity(1.0f)
  3717. , mClipFlags(NS_STYLE_CLIP_AUTO)
  3718. , mMixBlendMode(NS_STYLE_BLEND_NORMAL)
  3719. {
  3720. MOZ_COUNT_CTOR(nsStyleEffects);
  3721. }
  3722. nsStyleEffects::nsStyleEffects(const nsStyleEffects& aSource)
  3723. : mFilters(aSource.mFilters)
  3724. , mBoxShadow(aSource.mBoxShadow)
  3725. , mClip(aSource.mClip)
  3726. , mOpacity(aSource.mOpacity)
  3727. , mClipFlags(aSource.mClipFlags)
  3728. , mMixBlendMode(aSource.mMixBlendMode)
  3729. {
  3730. MOZ_COUNT_CTOR(nsStyleEffects);
  3731. }
  3732. nsStyleEffects::~nsStyleEffects()
  3733. {
  3734. MOZ_COUNT_DTOR(nsStyleEffects);
  3735. }
  3736. nsChangeHint
  3737. nsStyleEffects::CalcDifference(const nsStyleEffects& aNewData) const
  3738. {
  3739. nsChangeHint hint = nsChangeHint(0);
  3740. if (!AreShadowArraysEqual(mBoxShadow, aNewData.mBoxShadow)) {
  3741. // Update overflow regions & trigger DLBI to be sure it's noticed.
  3742. // Also request a repaint, since it's possible that only the color
  3743. // of the shadow is changing (and UpdateOverflow/SchedulePaint won't
  3744. // repaint for that, since they won't know what needs invalidating.)
  3745. hint |= nsChangeHint_UpdateOverflow |
  3746. nsChangeHint_SchedulePaint |
  3747. nsChangeHint_RepaintFrame;
  3748. }
  3749. if (mClipFlags != aNewData.mClipFlags) {
  3750. hint |= nsChangeHint_AllReflowHints |
  3751. nsChangeHint_RepaintFrame;
  3752. }
  3753. if (!mClip.IsEqualInterior(aNewData.mClip)) {
  3754. // If the clip has changed, we just need to update overflow areas. DLBI
  3755. // will handle the invalidation.
  3756. hint |= nsChangeHint_UpdateOverflow |
  3757. nsChangeHint_SchedulePaint;
  3758. }
  3759. if (mOpacity != aNewData.mOpacity) {
  3760. // If we're going from the optimized >=0.99 opacity value to 1.0 or back, then
  3761. // repaint the frame because DLBI will not catch the invalidation. Otherwise,
  3762. // just update the opacity layer.
  3763. if ((mOpacity >= 0.99f && mOpacity < 1.0f && aNewData.mOpacity == 1.0f) ||
  3764. (aNewData.mOpacity >= 0.99f && aNewData.mOpacity < 1.0f && mOpacity == 1.0f)) {
  3765. hint |= nsChangeHint_RepaintFrame;
  3766. } else {
  3767. hint |= nsChangeHint_UpdateOpacityLayer;
  3768. if ((mOpacity == 1.0f) != (aNewData.mOpacity == 1.0f)) {
  3769. hint |= nsChangeHint_UpdateUsesOpacity;
  3770. }
  3771. }
  3772. }
  3773. if (HasFilters() != aNewData.HasFilters()) {
  3774. // A change from/to being a containing block for position:fixed.
  3775. hint |= nsChangeHint_UpdateContainingBlock;
  3776. }
  3777. if (mFilters != aNewData.mFilters) {
  3778. hint |= nsChangeHint_UpdateEffects |
  3779. nsChangeHint_RepaintFrame |
  3780. nsChangeHint_UpdateOverflow;
  3781. }
  3782. if (mMixBlendMode != aNewData.mMixBlendMode) {
  3783. hint |= nsChangeHint_RepaintFrame;
  3784. }
  3785. if (!hint &&
  3786. !mClip.IsEqualEdges(aNewData.mClip)) {
  3787. hint |= nsChangeHint_NeutralChange;
  3788. }
  3789. return hint;
  3790. }