1 // This may look like C code, but it's really -*- C++ -*- 2 /* 3 * Copyright (C) 2010 Emweb bv, Herent, Belgium. 4 * 5 * See the LICENSE file for terms of use. 6 */ 7 #ifndef RENDER_BLOCK_H_ 8 #define RENDER_BLOCK_H_ 9 10 #include <Wt/WFont.h> 11 #include <Wt/WGlobal.h> 12 #include <Wt/WWebWidget.h> 13 #include <Wt/WPainter.h> 14 15 #include "web/DomElement.h" 16 #include "LayoutBox.h" 17 #include "3rdparty/rapidxml/rapidxml.hpp" 18 #include "Wt/Render/Specificity.h" 19 20 namespace Wt { 21 namespace Render { 22 23 class WTextRenderer; 24 class Block; 25 class Line; 26 class StyleSheet; 27 28 typedef std::vector<Block *> BlockList; 29 30 struct PageState 31 { PageStatePageState32 PageState() 33 : y(0), minX(0), maxX(0), page(0) 34 { } 35 36 double y; 37 double minX, maxX; 38 BlockList floats; 39 int page; 40 }; 41 42 struct CellState : public PageState 43 { 44 int lastRow; 45 double x; 46 Block *cell; 47 }; 48 49 struct Range 50 { RangeRange51 Range(double start, double end) 52 : start(start), end(end) 53 { } 54 55 double start, end; 56 }; 57 58 enum class FloatSide { 59 None, 60 Left, 61 Right 62 }; 63 64 // exported for test.exe 65 class WT_API Block 66 { 67 public: 68 Block(Wt::rapidxml::xml_node<> *node, Block *parent); 69 virtual ~Block(); 70 parent()71 const Block* parent() const { return parent_; } children()72 BlockList children() const { return children_; } 73 void determineDisplay(); 74 bool normalizeWhitespace(bool haveWhitespace, 75 Wt::rapidxml::xml_document<> &doc); 76 isFloat()77 bool isFloat() const { return float_ != FloatSide::None; } isInline()78 bool isInline() const { return inline_; } type()79 DomElementType type() const { return type_; } 80 bool isText() const; 81 std::string text() const; 82 bool inlineChildren() const; 83 AlignmentFlag horizontalAlignment() const; 84 AlignmentFlag verticalAlignment() const; floatSide()85 FloatSide floatSide() const { return float_; } 86 isTableCell()87 bool isTableCell() const 88 { return type_ == DomElementType::TD || type_ == DomElementType::TH; } 89 isTable()90 bool isTable() const 91 { return type_ == DomElementType::TABLE; } 92 93 Block *table() const; 94 bool tableCollapseBorders() const; 95 96 double layoutBlock(PageState &ps, 97 bool canIncreaseWidth, 98 const WTextRenderer& renderer, 99 double collapseMarginTop, 100 double collapseMarginBottom, 101 double cellHeight = -1); 102 103 void collectStyles(WStringStream& ss); 104 void setStyleSheet(StyleSheet* styleSheet); 105 void actualRender(WTextRenderer& renderer, WPainter& painter, LayoutBox& lb); 106 107 void render(WTextRenderer& renderer, WPainter& painter, int page); 108 109 static void clearFloats(PageState &ps); 110 static void clearFloats(PageState &ps, 111 double minWidth); 112 113 std::vector<InlineBox> inlineLayout; // for inline elements, one per line 114 std::vector<BlockBox> blockLayout; // otherwise, one per page 115 116 static void adjustAvailableWidth(double y, int page, 117 const BlockList& floats, 118 Range &rangeX); 119 120 static bool isWhitespace(char c); 121 122 std::string id() const; classes()123 const std::vector<std::string>& classes() const { return classes_; } 124 std::string cssProperty(Property property) const; 125 std::string attributeValue(const char *attribute) const; 126 127 private: 128 struct CssLength { 129 double length; 130 bool defined; 131 }; 132 133 enum class PercentageRule { 134 PercentageOfFontSize, 135 PercentageOfParentSize, 136 IgnorePercentage 137 }; 138 139 struct PropertyValue 140 { PropertyValuePropertyValue141 PropertyValue() { } PropertyValuePropertyValue142 PropertyValue(const std::string& value, const Specificity& s) 143 : value_(value), s_(s) { } 144 145 std::string value_; 146 Specificity s_; 147 }; 148 149 enum Corner { TopLeft, TopRight, BottomLeft, BottomRight }; 150 151 enum class WidthType { 152 AsSetWidth, 153 MinimumWidth, 154 MaximumWidth 155 }; 156 157 struct BorderElement { 158 const Block *block; 159 Side side; 160 BorderElementBorderElement161 BorderElement() : block(nullptr), side(Side::Left) { } BorderElementBorderElement162 BorderElement(const Block *aBlock, Side aSide) 163 : block(aBlock), side(aSide) { } 164 }; 165 166 Wt::rapidxml::xml_node<> *node_; 167 Block *parent_; 168 BlockList offsetChildren_; 169 Block *offsetParent_; 170 DomElementType type_; 171 std::vector<std::string> classes_; 172 FloatSide float_; 173 bool inline_; 174 BlockList children_; 175 const LayoutBox *currentTheadBlock_; 176 double currentWidth_; 177 double contentsHeight_; 178 mutable std::map<std::string, PropertyValue> css_; 179 mutable WFont font_; 180 StyleSheet* styleSheet_; 181 mutable std::set<Property> noPropertyCache_; 182 183 /* For table */ 184 int tableRowCount_, tableColCount_; 185 186 /* For table cell */ 187 int cellRow_, cellCol_; 188 189 int attributeValue(const char *attribute, int defaultValue) const; 190 191 void updateAggregateProperty(const std::string& property, 192 const std::string& aggregate, 193 const Specificity& spec, 194 const std::string& value) const; 195 void fillinStyle(const std::string& style, 196 const Specificity &specificity) const; 197 bool isPositionedAbsolutely() const; 198 std::string inheritedCssProperty(Property property) const; 199 double cssWidth(double fontScale) const; 200 double cssHeight(double fontScale) const; 201 CssLength cssLength(Property top, Side side, double fontScale) const; 202 double cssMargin(Side side, double fontScale) const; 203 double cssPadding(Side side, double fontScale) const; 204 double cssBorderSpacing(double fontScale) const; 205 206 double cssBorderWidth(Side side, double fontScale) const; 207 double collapsedBorderWidth(Side side, double fontScale) const; 208 double rawCssBorderWidth(Side side, double fontScale, 209 bool indicateHidden = false) const; 210 WColor cssBorderColor(Side side) const; 211 WColor collapsedBorderColor(Side side) const; 212 WColor rawCssBorderColor(Side side) const; 213 214 WColor cssColor() const; 215 AlignmentFlag cssTextAlign() const; 216 double cssBoxMargin(Side side, double fontScale) const; 217 double cssLineHeight(double fontLineHeight, double fontScale) const; 218 double cssFontSize(double fontScale = 1) const; 219 std::string cssPosition() const; 220 FontStyle cssFontStyle() const; 221 int cssFontWeight() const; 222 WFont cssFont(double fontScale) const; 223 std::string cssTextDecoration() const; 224 double cssDecodeLength(const std::string& length, double fontScale, 225 double defaultValue, 226 PercentageRule percentage = 227 PercentageRule::PercentageOfFontSize, 228 double parentSize = 0) 229 const; 230 static bool isPercentageLength(const std::string& length); 231 232 double currentParentWidth() const; 233 234 bool isInside(DomElementType type) const; 235 236 void pageBreak(PageState& ps); 237 void inlinePageBreak(const std::string& pageBreak, 238 Line& line, BlockList& floats, 239 double minX, double maxX, 240 const WTextRenderer& renderer); 241 double layoutInline(Line& line, BlockList& floats, 242 double minX, double maxX, bool canIncreaseWidth, 243 const WTextRenderer& renderer); 244 void layoutTable(PageState &ps, 245 bool canIncreaseWidth, 246 const WTextRenderer& renderer, 247 double cssSetWidth); 248 double layoutFloat(double y, int page, BlockList& floats, 249 double lineX, double lineHeight, 250 double minX, double maxX, 251 bool canIncreaseWidth, 252 const WTextRenderer& renderer); 253 void layoutAbsolute(const WTextRenderer& renderer); 254 255 void tableDoLayout(double x, PageState &ps, double cellSpacing, 256 const std::vector<double>& widths, 257 std::vector<CellState>& rowSpanBackLog, 258 bool protectRows, Block *repeatHead, 259 const WTextRenderer& renderer); 260 void tableRowDoLayout(double x, PageState &ps, 261 double cellSpacing, 262 const std::vector<double>& widths, 263 std::vector<CellState>& rowSpanBackLog, 264 const WTextRenderer& renderer, 265 double rowHeight); 266 void tableCellDoLayout(double x, const PageState &ps, 267 double cellSpacing, PageState& rowEnd, 268 const std::vector<double>& widths, 269 const WTextRenderer& renderer, 270 double rowHeight); 271 double tableCellX(const std::vector<double>& widths, 272 double cellSpacing) const; 273 double tableCellWidth(const std::vector<double>& widths, 274 double cellSpacing) const; 275 void tableComputeColumnWidths(std::vector<double>& minima, 276 std::vector<double>& maxima, 277 std::vector<double>& asSet, 278 const WTextRenderer& renderer, 279 Block *table); 280 281 BorderElement collapseCellBorders(Side side) const; 282 int numberTableCells(int row, std::vector<int>& rowSpan); 283 Block *findTableCell(int row, int col) const; 284 Block *siblingTableCell(Side side) const; 285 286 void cellComputeColumnWidths(WidthType type, 287 std::vector<double>& values, 288 const WTextRenderer& renderer, 289 Block *table); 290 291 void setOffsetParent(); 292 Block *findOffsetParent(); 293 LayoutBox layoutTotal(); 294 LayoutBox firstInlineLayoutBox(); 295 296 LayoutBox toBorderBox(const LayoutBox& bb, double fontScale) const; 297 double maxLayoutY(int page) const; 298 double minLayoutY(int page) const; 299 double maxChildrenLayoutY(int page) const; 300 double minChildrenLayoutY(int page) const; 301 double childrenLayoutHeight(int page) const; 302 void reLayout(const LayoutBox& from, const LayoutBox& to); 303 304 void renderText(const std::string& text, WTextRenderer& renderer, 305 WPainter& painter, int page); 306 void renderBorders(const LayoutBox& bb, WTextRenderer& renderer, WPainter &painter, 307 WFlags<Side> verticals); 308 309 WString generateItem() const; 310 311 int firstLayoutPage() const; 312 313 int lastLayoutPage() const; 314 315 static void advance(PageState &ps, double height, 316 const WTextRenderer& renderer); 317 static double diff(double y, int page, double startY, int startPage, 318 const WTextRenderer& renderer); 319 320 static double positionFloat(double x, 321 PageState &ps, 322 double lineHeight, double width, 323 bool canIncreaseWidth, 324 const WTextRenderer& renderer, 325 FloatSide floatSide); 326 327 static void unsupportedAttributeValue(const char *attribute, 328 const std::string& value); 329 static void unsupportedCssValue(Property property, 330 const std::string& value); 331 332 static bool isAggregate(const std::string& cssProperty); 333 334 static double maxBorderWidth(Block *b1, Side s1, 335 Block *b2, Side s2, 336 Block *b3, Side s3, 337 Block *b4, Side s4, 338 double fontScale); 339 340 friend class Line; 341 }; 342 343 } 344 } 345 346 #endif // RENDER_BLOCK_H_ 347