LayoutBlockBox.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /*
  2. * This source file is part of RmlUi, the HTML/CSS Interface Middleware
  3. *
  4. * For the latest information, see http://github.com/mikke89/RmlUi
  5. *
  6. * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
  7. * Copyright (c) 2019 The RmlUi Team, and contributors
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a copy
  10. * of this software and associated documentation files (the "Software"), to deal
  11. * in the Software without restriction, including without limitation the rights
  12. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. * copies of the Software, and to permit persons to whom the Software is
  14. * furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. * THE SOFTWARE.
  26. *
  27. */
  28. #ifndef RMLUI_CORE_LAYOUTBLOCKBOX_H
  29. #define RMLUI_CORE_LAYOUTBLOCKBOX_H
  30. #include "LayoutLineBox.h"
  31. #include "../../Include/RmlUi/Core/Box.h"
  32. #include "../../Include/RmlUi/Core/Types.h"
  33. namespace Rml {
  34. class LayoutBlockBoxSpace;
  35. class LayoutEngine;
  36. /**
  37. @author Peter Curry
  38. */
  39. class LayoutBlockBox
  40. {
  41. public:
  42. enum FormattingContext
  43. {
  44. BLOCK,
  45. INLINE
  46. };
  47. enum CloseResult
  48. {
  49. OK,
  50. LAYOUT_SELF,
  51. LAYOUT_PARENT
  52. };
  53. /// Creates a new block box for rendering a block element.
  54. /// @param parent[in] The parent of this block box. This will be nullptr for the root element.
  55. /// @param element[in] The element this block box is laying out.
  56. /// @param box[in] The box used for this block box.
  57. /// @param min_height[in] The minimum height of the content box.
  58. /// @param max_height[in] The maximum height of the content box.
  59. LayoutBlockBox(LayoutBlockBox* parent, Element* element, const Box& box, float min_height, float max_height);
  60. /// Creates a new block box in an inline context.
  61. /// @param parent[in] The parent of this block box.
  62. LayoutBlockBox(LayoutBlockBox* parent);
  63. /// Releases the block box.
  64. ~LayoutBlockBox();
  65. /// Closes the box. This will determine the element's height (if it was unspecified).
  66. /// @return The result of the close; this may request a reformat of this element or our parent.
  67. CloseResult Close();
  68. /// Called by a closing block box child. Increments the cursor.
  69. /// @param child[in] The closing child block box.
  70. /// @return False if the block box caused an automatic vertical scrollbar to appear, forcing an entire reformat of the block box.
  71. bool CloseBlockBox(LayoutBlockBox* child);
  72. /// Called by a closing line box child. Increments the cursor, and creates a new line box to fit the overflow
  73. /// (if any).
  74. /// @param child[in] The closing child line box.
  75. /// @param overflow[in] The overflow from the closing line box. May be nullptr if there was no overflow.
  76. /// @param overflow_chain[in] The end of the chained hierarchy to be spilled over to the new line, as the parent to the overflow box (if one exists).
  77. /// @return If the line box had overflow, this will be the last inline box created by the overflow.
  78. LayoutInlineBox* CloseLineBox(LayoutLineBox* child, UniquePtr<LayoutInlineBox> overflow, LayoutInlineBox* overflow_chain);
  79. /// Adds a new block element to this block-context box.
  80. /// @param element[in] The new block element.
  81. /// @param box[in] The box used for the new block box.
  82. /// @param min_height[in] The minimum height of the content box.
  83. /// @param max_height[in] The maximum height of the content box.
  84. /// @return The block box representing the element. Once the element's children have been positioned, Close() must be called on it.
  85. LayoutBlockBox* AddBlockElement(Element* element, const Box& box, float min_height, float max_height);
  86. /// Adds a new inline element to this inline-context box.
  87. /// @param element[in] The new inline element.
  88. /// @param box[in] The box defining the element's bounds.
  89. /// @return The inline box representing the element. Once the element's children have been positioned, Close() must be called on it.
  90. LayoutInlineBox* AddInlineElement(Element* element, const Box& box);
  91. /// Adds a line-break to this block box.
  92. void AddBreak();
  93. /// Adds an element to this block box to be handled as a floating element.
  94. bool AddFloatElement(Element* element);
  95. /// Adds an element to this block box to be handled as an absolutely-positioned element. This element will be
  96. /// laid out, sized and positioned appropriately once this box is finished. This should only be called on boxes
  97. /// rendering in a block-context.
  98. /// @param element[in] The element to be positioned absolutely within this block box.
  99. void AddAbsoluteElement(Element* element);
  100. /// Formats, sizes, and positions all absolute elements in this block.
  101. void CloseAbsoluteElements();
  102. /// Returns the offset from the top-left corner of this box's offset element the next child box will be
  103. /// positioned at.
  104. /// @param[out] box_position The box cursor position.
  105. /// @param[in] top_margin The top margin of the box. This will be collapsed as appropriate against other block boxes.
  106. /// @param[in] clear_property The value of the underlying element's clear property.
  107. void PositionBox(Vector2f& box_position, float top_margin = 0, Style::Clear clear_property = Style::Clear::None) const;
  108. /// Returns the offset from the top-left corner of this box's offset element the next child block box, of the
  109. /// given dimensions, will be positioned at. This will include the margins on the new block box.
  110. /// @param[out] box_position The block box cursor position.
  111. /// @param[in] box The dimensions of the new box.
  112. /// @param[in] clear_property The value of the underlying element's clear property.
  113. void PositionBlockBox(Vector2f& box_position, const Box& box, Style::Clear clear_property) const;
  114. /// Returns the offset from the top-left corner of this box for the next line.
  115. /// @param box_position[out] The line box position.
  116. /// @param box_width[out] The available width for the line box.
  117. /// @param wrap_content[out] Set to true if the line box should grow to fit inline boxes, false if it should wrap them.
  118. /// @param dimensions[in] The minimum dimensions of the line.
  119. void PositionLineBox(Vector2f& box_position, float& box_width, bool& wrap_content, Vector2f dimensions) const;
  120. /// Calculate the dimensions of the box's internal content width; i.e. the size used to calculate the shrink-to-fit width.
  121. float GetShrinkToFitWidth() const;
  122. /// Get the visible overflow size. Note: This is only well-defined after the layout box has been closed.
  123. Vector2f GetVisibleOverflowSize() const;
  124. /// Set the inner content size if it is larger than the current value on each axis individually.
  125. void ExtendInnerContentSize(Vector2f inner_content_size);
  126. /// Returns the block box's element.
  127. /// @return The block box's element.
  128. Element* GetElement() const;
  129. /// Returns the block box's parent.
  130. /// @return The block box's parent.
  131. LayoutBlockBox* GetParent() const;
  132. /// Returns the position of the block box, relative to its parent's content area.
  133. /// @return The relative position of the block box.
  134. Vector2f GetPosition() const;
  135. /// Returns the block box against which all positions of boxes in the hierarchy are set relative to.
  136. /// @return This box's offset parent.
  137. const LayoutBlockBox* GetOffsetParent() const;
  138. /// Returns the block box against which all positions of boxes in the hierarchy are calculated relative to.
  139. /// @return This box's offset root.
  140. const LayoutBlockBox* GetOffsetRoot() const;
  141. /// Returns the block box's dimension box.
  142. Box& GetBox();
  143. /// Returns the block box's dimension box.
  144. const Box& GetBox() const;
  145. void* operator new(size_t size);
  146. void operator delete(void* chunk, size_t size);
  147. private:
  148. struct AbsoluteElement
  149. {
  150. Element* element;
  151. Vector2f position;
  152. };
  153. // Closes our last block box, if it is an open inline block box.
  154. CloseResult CloseInlineBlockBox();
  155. // Positions a floating element within this block box.
  156. void PositionFloat(Element* element, float offset = 0);
  157. // Checks if we have a new vertical overflow on an auto-scrolling element. If so, our vertical scrollbar will
  158. // be enabled and our block boxes will be destroyed. All content will need to re-formatted. Returns true if no
  159. // overflow occured, false if it did.
  160. bool CatchVerticalOverflow(float cursor = -1);
  161. using AbsoluteElementList = Vector< AbsoluteElement >;
  162. using BlockBoxList = Vector< UniquePtr<LayoutBlockBox> >;
  163. using LineBoxList = Vector< UniquePtr<LayoutLineBox> >;
  164. // The object managing our space, as occupied by floating elements of this box and our ancestors.
  165. LayoutBlockBoxSpace* space;
  166. // The element this box represents. This will be nullptr for boxes rendering in an inline context.
  167. Element* element;
  168. // The element we'll be computing our offset relative to during layout.
  169. const LayoutBlockBox* offset_root;
  170. // The element this block box's children are to be offset from.
  171. LayoutBlockBox* offset_parent;
  172. // The box's block parent. This will be nullptr for the root of the box tree.
  173. LayoutBlockBox* parent;
  174. // The context of the box's context; either block or inline.
  175. FormattingContext context;
  176. // The block box's position.
  177. Vector2f position;
  178. // The block box's size.
  179. Box box;
  180. float min_height;
  181. float max_height;
  182. // Used by inline contexts only; set to true if the block box's line boxes should stretch to fit their inline content instead of wrapping.
  183. bool wrap_content;
  184. // The vertical position of the next block box to be added to this box, relative to the top of this box.
  185. float box_cursor;
  186. // Used by block contexts only; stores the list of block boxes under this box.
  187. BlockBoxList block_boxes;
  188. // Used by block contexts only; stores any elements that are to be absolutely positioned within this block box.
  189. AbsoluteElementList absolute_elements;
  190. // Used by block contexts only; stores any elements that are relatively positioned and whose containing block is this.
  191. ElementList relative_elements;
  192. // Used by block contexts only; stores the block box space pointed to by the 'space' member.
  193. UniquePtr<LayoutBlockBoxSpace> space_owner;
  194. // Used by block contexts only; stores an inline element hierarchy that was interrupted by a child block box.
  195. // The hierarchy will be resumed in an inline-context box once the intervening block box is completed.
  196. LayoutInlineBox* interrupted_chain;
  197. // Used by block contexts only; stores the value of the overflow property for the element.
  198. Style::Overflow overflow_x_property;
  199. Style::Overflow overflow_y_property;
  200. // The outer size of this box including overflowing content. Similar to scroll width, but shrinked if overflow is caught here.
  201. // This can be wider than the box if we are overflowing. Only available after the box has been closed.
  202. Vector2f visible_overflow_size;
  203. // The inner content size (excluding any padding/border/margins).
  204. // This is extended as child block boxes are closed, or from external formatting contexts.
  205. Vector2f inner_content_size;
  206. // Used by block contexts only; if true, we've enabled our vertical scrollbar.
  207. bool vertical_overflow;
  208. // Used by inline contexts only; stores the list of line boxes flowing inline content.
  209. LineBoxList line_boxes;
  210. // Used by inline contexts only; stores any floating elements that are waiting for a line break to be positioned.
  211. ElementList float_elements;
  212. };
  213. } // namespace Rml
  214. #endif