Firefox: lo SpaceManager di Gecko

Firefox: lo SpaceManager di Gecko

Lo SpaceManager era un componente fondamentale di Gecko che è stato rimosso solo nelle ultime versioni di Firefox. Quella che segue è la traduzione del documento originale che ne illustra il design.

Introduzione

Lo Space Manager (e classi e strutture associate) vengono usati dal layout Block e Line per controllare le zone rettangolari che sono occupate o disponibili, per la corretta gestione degli elementi flottati e degli elementi che fluiscono intorno a questi ultimi. Quando gli elementi sono flottati a destra o a sinistra in un layout, essi occupano spazio ed influenzano il posizionamento degli altri elementi. Lo Space Manager ha il compito di registrare dove viene occupato spazio e dove invece è disponibile. Questa informazione viene usata dal layout di blocco per calcolare correttamente dove devono essere posizionati altri elementi flottati, e quanto spazio resta disponibile per i normali elementi nel flusso che scorrono attorno alle parti flottate.

Lo Space Manager lavora congiuntamente con diverse altre classi. Le classi che vengono considerate parte dello Space Manager sono:

  • nsSpaceManager
  • nsBandData
  • nsBlockBandData
  • BandRect / BandList (private)
  • FrameInfo (private)
  • nsBandtrapezoid

Al di fuori dello Space Manager stesso, i client dello Space Manager rivestono un ruolo importante nella gestione dello spazio disponibile ed in uso. Le classi principali che interagiscono con lo Space Manager sono:

  • nsBlockReflowState
  • nsBlockFrame
  • nsBoxToBlockAdaptor

Il modello di interazione generico consiste nel creare uno Space Manager per un frame di blocco nel contesto di un Reflow, e di associarlo con il BlockReflowState in modo che venga passato ai metodi di reflow dei frame figli. Dopo il reflow, lo Space Manager viene distrutto. Durante il reflow, lo Space Manager memorizza lo spazio occupato dai float (UpdateSpaceManager in nsBlockFrame) e fornisce informazioni sullo spazio disponibile per gli altri elementi (GetAvailableSpace in nsBlockReflowState).

Inoltre vi è il bisogno di gestire l'impatto sulle righe causato dai cambiamenti agli elementi flottati. Questo viene detto Propagation of Float Damage e viene gestito dal Block Frame, che fa uso dello Space Manager. Quando un float viene risistemato in modo incrementale, lo Space Manager si accorge se la zona del float è cambiata. Se ciò avviene, lo spazio verticale (che comprende la precendente zona del float e la sua nuova zona) viene segnalato nell' nsIntervalSet interno come "danno potenziale del float" (il metodo è IncludeInDamage). Durante la risistemazione incrementale delle righe "sporche" il frame di blocco può incontrare righe che NON sono sporche. In questo caso viene chiesto allo Space Manager se vi è un danno dei float, e in caso affermativo il blocco prosegue verificando se il danno interseca l'area della riga non-sporca, rendendola sporca se vi è un'intersezione. In questo modo i cambiamenti ai float su altre righe possono avere un impatto su righe altrimenti "pulite", e lo Space Manager ne facilita l'individuazione.

Modello di dati

Diagramma classi/componenti

Diagramma delle classi di Space Manager

  • nsSpaceManager: Il punto centrale della gestione dello spazio occupato dai float in un blocco.
  • nsBandData: Fornisce informazioni sui frame che occupano una zona di spazio occupato o disponibile.
  • nsBlockBandData: Una specializzazione di nsBandData usata da nsBlockReflowState per determinare lo spazio disponibile, l'impatto dei float e il punto in cui i float ricevono il clear. Essenzialmente un contenitore specifico per nsBandData generico.
  • BandRect: Conserva i confini di una zona, insieme con i frame associati alla zona. I BandRect sono un elenco linkato (fornito dalla super-classe PRCListStr) che forniscono anche alcuni metodi geometrici (SplitVertically, SplitHorizontally) e alcuni metodi che interrogano o manipolano i frame associati alla zona (IsOccupiedBy, AddFrame, RemoveFrame).
  • BandList: Una sottoclasse di BandRect che fornisce un elenco di interfacce - Head(), Tail(), IsEmpty(), ecc.
  • FrameInfo: Una struttura che conserva le informazioni sul rettangolo associato con uno specifico frame, in un elenco linkato.
  • nsBandTrapezoid: Rappresenta le regioni discrete all'interno di una zona che sono Available, Occupied da un singolo frame o Occupied da diversi frame. Viene usato per comunicare le informazioni sullo spazio nella zona ai client di Space Manager. Non vi è un uso interno di nsBandTrapezoid da parte dello Space Manager, piuttosto esso usa il suo BandList interno per creare una collezione BandData, costituita soprattutto da dati nsTrapezoid.

Casi d'uso

Caso d'uso 1: Space Manager viene creato/distrutto

Le istanze di Space Manager vengono create nel metodo Reflow di nsBlockFrame.

  • Viene creata un'istanza.
  • Il precedente Space Manager di BlockReflowState viene salvato.
  • La nuova istanza di Space Manager viene associata al BlockReflowState.
  • Dopo che il Reflow del frame è completo, la precedente istanza di Space Manager viene ri-associata con il BlockReflowState.
  • Il nuovo Space Manager viene distrutto.

Se il BlockReflowState ha già un'istanza di Space Manager ad esso associata, viene memorizzata prima di essere sostituita e quindi restituita all'istanza di dopo che la nuova è stata distrutta. Di fatto gli Space Manager sono "annidati" durante il reflow, con ciascun blocco che introduce il proprio Space Manager.

Caso d'uso 2: Un float viene aggiunto allo Space Manager

Dopo che uno Space Manager è stato creato per un reflow di blocco, si può aggiungere un float ad esso. Ciò avviene nel metodo nsBlockReflowState::RecoverFloats e nsBlockReflowState::FlowAndPlaceFloat (prima veniva fatto in nsBlockFrame::UpdateSpaceManager).

L'algoritmo generale in nsBlockReflowState::RecoverFloats è:

  • Per ogni riga nel blocco, verificare se ha blocchi flottati.
  • Se i float sono sulla riga, eseguire una reiterazione sui float aggiungendoli tutti allo Space Manager tramite il metodo AddRectRegion. Il rettangolo effettivo per il frame viene memorizzato in nsFloatCache, e così non deve essere ricalcolato.
  • Se il blocco ha dei figli di blocco, si trasferisca lo Space Manager all'origine del blocco figlio, e si aggiorni lo Space Manager nel contesto del blocco figlio, ricorsivamente. Una volta compiuta questa operazione, si ripristinino le coordinate dello Space Manager trasferendo il negativo dell'origine del blocco figlio.

L'algoritmo generale in nsBlockReflowState::FlowAndPlaceFloat è:

  • Viene registrata la regione che il float occupa attualmente.
  • Viene ricercata la zona di spazio disponibile (con nsBlockReflowState::GetAvailableSpace).
  • Il frame del float ottenuto dall'argomento di nsFloatCache viene risistemato e il suo rettangolo è ottenuto con GetRect.
  • Vengono aggiunti i margini del float.
  • Verificare se il float può essere posizionato nella zona corrente. In caso contrario, passare alla zona successiva.
  • Verificare il tipo di float e se questo può essere aggiunto allo Space Manager.
  • Allineare il float alla parte superiore del suo blocco contenitore se la regola CSS2/9.5.1/4 non viene rispettata.
  • Aggiungere il float usando nsSpaceManager::AddRectRegion.
  • Confrontare l'area che il float occupava con l'area che occupa ora: se è diversa, memorizzare l'intervallo verticale interessato usando nsSpaceManager::IncludeInDamage.

Caso d'uso 3: Space Manager viene usato per trovare lo spazio disponibile per il reflow

nsBlockFrame fa uso dello Space Manager per ottenere lo spazio disponibile per il reflow di un figlio di blocco o inline. Il frame di blocco usa un metodo helper sulla classe nsBlockReflowState per effettuare il calcolo effettivo dello spazio disponibile sulla base dei dati dello Space Manager. Ecco il suo funzionamento nel caso di un reflow di un frame inline all'interno di un blocco (e anche nel caso del reflow di un frame di blocco e, parzialmente, per la preparazione di un ridimensionamento).

  • nsBlockFrame libera prima tutte le informazioni sui float per la riga da risistemare.
  • GetAvailableSpace viene chiamato su BlockReflowState.
  • BlockReflowState chiama GetAvailableSpace sulla sua istanza BlockBandData (preparata nel costruttore di BlockReflowState in base allo SpaceManager e all'area di contenuto calcolata).
  • BlockBandData ottiene i dati della zona dallo Space Manager con una chiamata allo Space Manager associato con l'istanza BlockBandData.
  • BlockBandData passa in rassegna la collezione dei trapezoid restituiti dal metodo GetBandData dello Space Manager (in forma di contenitori nsBandData) e determina il limite destro dello spazio disponibile.
  • BlockReflowState memorizza il rettangolo di spazio disponibile per l'uso nel resto della sequenza di reflow.

Caso d'uso 4: Propagazione del Float Damage: individuare e gestire il danno dei float

Questo processo è gestito dal Block Frame.

  • Una riga non-sporca viene trovata dal Block Frame in ReflowDirtyLines.
  • Block Frame chiama il suo metodo PropagateFloatDamage.
  • Space Manager deve stabilire se vi è un danno dei float.
  • In caso affermativo, Block Frame chiede a Space Manager se la riga in questione interseca il danno dei float.
  • Se la riga non lo interseca, allora la riga viene marcata come sporca.
  • La riga viene ancora marcata come sporca se:
    • è stata influenzata dai float, ma non lo è più.
    • non è stata influenzata dai float, ma ora lo è.
    • è influenzata dai float ed è un blocco.

Problemi/bug riscontrati durante la documentazione:

  • BandRect e BandList sono public in nsSpaceManager.h - dovrebbero essere private (compilare bene)
  • i dati membri di nsSpaceManager vengono dichiarati protected, ma non ci sono sottoclassi. Dovrebbero essere private (compilare bene).
  • nsBlockFrame::Paint si confonde con nsBlockBandData e il blocco #if 0 - rimuovere questo e l'include (compilare bene).
  • nsSpaceManager non ha modo di dare il clear all'intervallo del Float Damage impostato - ce ne sarebbe bisogno se SpaceManager persistesse oltre un Reflow.
Torna su