LayoutBlockBox.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  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 layout_engine[in] The layout engine that created this block box.
  55. /// @param parent[in] The parent of this block box. This will be nullptr for the root element.
  56. /// @param element[in] The element this block box is laying out.
  57. LayoutBlockBox(LayoutBlockBox* parent, Element* element, bool allow_shrink = true);
  58. /// Creates a new block box in an inline context.
  59. /// @param layout_engine[in] The layout engine that created this block box.
  60. /// @param parent[in] The parent of this block box.
  61. LayoutBlockBox(LayoutBlockBox* parent, bool allow_shrink = true);
  62. /// Releases the block box.
  63. ~LayoutBlockBox();
  64. /// Closes the box. This will determine the element's height (if it was unspecified).
  65. /// @return The result of the close; this may request a reformat of this element or our parent.
  66. CloseResult Close();
  67. /// Called by a closing block box child. Increments the cursor.
  68. /// @param child[in] The closing child block box.
  69. /// @return False if the block box caused an automatic vertical scrollbar to appear, forcing an entire reformat of the block box.
  70. bool CloseBlockBox(LayoutBlockBox* child);
  71. /// Called by a closing line box child. Increments the cursor, and creates a new line box to fit the overflow
  72. /// (if any).
  73. /// @param child[in] The closing child line box.
  74. /// @param overflow[in] The overflow from the closing line box. May be nullptr if there was no overflow.
  75. /// @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).
  76. /// @return If the line box had overflow, this will be the last inline box created by the overflow.
  77. LayoutInlineBox* CloseLineBox(LayoutLineBox* child, UniquePtr<LayoutInlineBox> overflow, LayoutInlineBox* overflow_chain);
  78. /// Adds a new block element to this block-context box.
  79. /// @param element[in] The new block element.
  80. /// @param placed[in] True if the element is to be placed, false otherwise.
  81. /// @return The block box representing the element. Once the element's children have been positioned, Close() must be called on it.
  82. LayoutBlockBox* AddBlockElement(Element* element, bool allow_shrink = true);
  83. /// Adds a new inline element to this inline-context box.
  84. /// @param element[in] The new inline element.
  85. /// @param box[in] The box defining the element's bounds.
  86. /// @return The inline box representing the element. Once the element's children have been positioned, Close() must be called on it.
  87. LayoutInlineBox* AddInlineElement(Element* element, const Box& box);
  88. /// Adds a line-break to this block box.
  89. void AddBreak();
  90. /// Adds an element to this block box to be handled as a floating element.
  91. bool AddFloatElement(Element* element);
  92. /// Adds an element to this block box to be handled as an absolutely-positioned element. This element will be
  93. /// laid out, sized and positioned appropriately once this box is finished. This should only be called on boxes
  94. /// rendering in a block-context.
  95. /// @param element[in] The element to be positioned absolutely within this block box.
  96. void AddAbsoluteElement(Element* element);
  97. /// Formats, sizes, and positions all absolute elements in this block.
  98. void CloseAbsoluteElements();
  99. /// Returns the offset from the top-left corner of this box's offset element the next child box will be
  100. /// positioned at.
  101. /// @param[out] box_position The box cursor position.
  102. /// @param[in] top_margin The top margin of the box. This will be collapsed as appropriate against other block boxes.
  103. /// @param[in] clear_property The value of the underlying element's clear property.
  104. void PositionBox(Vector2f& box_position, float top_margin = 0, Style::Clear clear_property = Style::Clear::None) const;
  105. /// Returns the offset from the top-left corner of this box's offset element the next child block box, of the
  106. /// given dimensions, will be positioned at. This will include the margins on the new block box.
  107. /// @param[out] box_position The block box cursor position.
  108. /// @param[in] box The dimensions of the new box.
  109. /// @param[in] clear_property The value of the underlying element's clear property.
  110. void PositionBlockBox(Vector2f& box_position, const Box& box, Style::Clear clear_property) const;
  111. /// Returns the offset from the top-left corner of this box for the next line.
  112. /// @param box_position[out] The line box position.
  113. /// @param box_width[out] The available width for the line box.
  114. /// @param wrap_content[out] Set to true if the line box should grow to fit inline boxes, false if it should wrap them.
  115. /// @param dimensions[in] The minimum dimensions of the line.
  116. void PositionLineBox(Vector2f& box_position, float& box_width, bool& wrap_content, const Vector2f& dimensions) const;
  117. /// Calculate the dimensions of the box's internal content width; i.e. the size used to calculate the shrink-to-fit width.
  118. float GetShrinkToFitWidth() const;
  119. /// Returns the block box's element.
  120. /// @return The block box's element.
  121. Element* GetElement() const;
  122. /// Returns the block box's parent.
  123. /// @return The block box's parent.
  124. LayoutBlockBox* GetParent() const;
  125. /// Returns the position of the block box, relative to its parent's content area.
  126. /// @return The relative position of the block box.
  127. const Vector2f& GetPosition() const;
  128. /// Returns the block box against which all positions of boxes in the hierarchy are set relative to.
  129. /// @return This box's offset parent.
  130. const LayoutBlockBox* GetOffsetParent() const;
  131. /// Returns the block box against which all positions of boxes in the hierarchy are calculated relative to.
  132. /// @return This box's offset root.
  133. const LayoutBlockBox* GetOffsetRoot() const;
  134. /// Returns the block box's dimension box.
  135. /// @return The block box's dimension box.
  136. Box& GetBox();
  137. /// Returns the block box's dimension box.
  138. /// @return The block box's dimension box.
  139. const Box& GetBox() const;
  140. void* operator new(size_t size);
  141. void operator delete(void* chunk);
  142. private:
  143. struct AbsoluteElement
  144. {
  145. Element* element;
  146. Vector2f position;
  147. };
  148. // Closes our last block box, if it is an open inline block box.
  149. CloseResult CloseInlineBlockBox();
  150. // Positions a floating element within this block box.
  151. void PositionFloat(Element* element, float offset = 0);
  152. // Checks if we have a new vertical overflow on an auto-scrolling element. If so, our vertical scrollbar will
  153. // be enabled and our block boxes will be destroyed. All content will need to re-formatted. Returns true if no
  154. // overflow occured, false if it did.
  155. bool CatchVerticalOverflow(float cursor = -1);
  156. using AbsoluteElementList = Vector< AbsoluteElement >;
  157. using BlockBoxList = Vector< UniquePtr<LayoutBlockBox> >;
  158. using LineBoxList = Vector< UniquePtr<LayoutLineBox> >;
  159. // The object managing our space, as occupied by floating elements of this box and our ancestors.
  160. LayoutBlockBoxSpace* space;
  161. // The element this box represents. This will be nullptr for boxes rendering in an inline context.
  162. Element* element;
  163. // The element we'll be computing our offset relative to during layout.
  164. const LayoutBlockBox* offset_root;
  165. // The element this block box's children are to be offset from.
  166. const LayoutBlockBox* offset_parent;
  167. // The box's block parent. This will be nullptr for the root of the box tree.
  168. LayoutBlockBox* parent;
  169. // The context of the box's context; either block or inline.
  170. FormattingContext context;
  171. // The block box's position.
  172. Vector2f position;
  173. // The block box's size.
  174. Box box;
  175. float min_height;
  176. float max_height;
  177. // 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.
  178. bool wrap_content;
  179. // The vertical position of the next block box to be added to this box, relative to the top of this box.
  180. float box_cursor;
  181. // Used by block contexts only; stores the list of block boxes under this box.
  182. BlockBoxList block_boxes;
  183. // Used by block contexts only; stores any elements that are to be absolutely positioned within this block box.
  184. AbsoluteElementList absolute_elements;
  185. // Used by block contexts only; stores the block box space pointed to by the 'space' member.
  186. UniquePtr<LayoutBlockBoxSpace> space_owner;
  187. // Used by block contexts only; stores an inline element hierarchy that was interrupted by a child block box.
  188. // The hierarchy will be resumed in an inline-context box once the intervening block box is completed.
  189. LayoutInlineBox* interrupted_chain;
  190. // Used by block contexts only; stores the value of the overflow property for the element.
  191. Style::Overflow overflow_x_property;
  192. Style::Overflow overflow_y_property;
  193. // Used by block contexts only; the content width as visible from the parent. Similar to scroll width, but shrinked if overflow is caught here.
  194. // This can be wider than the box if we are overflowing. Only available after the box has been closed.
  195. float visible_outer_width;
  196. // Used by block contexts only; if true, we've enabled our vertical scrollbar.
  197. bool vertical_overflow;
  198. // Used by inline contexts only; stores the list of line boxes flowing inline content.
  199. LineBoxList line_boxes;
  200. // Used by inline contexts only; stores any floating elements that are waiting for a line break to be positioned.
  201. ElementList float_elements;
  202. };
  203. } // namespace Rml
  204. #endif