Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(206)

Side by Side Diff: third_party/WebKit/Source/core/paint/TableCollapsedBorderPainter.cpp

Issue 1781463002: Fix table background painting (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Sample code for improved collapsed border painting Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "core/paint/TableCollapsedBorderPainter.h"
6
7 #include "core/layout/LayoutTableCell.h"
8 #include "core/layout/LayoutTableCol.h"
9 #include "core/paint/BlockPainter.h"
10 #include "core/paint/BoxPainter.h"
11 #include "core/paint/LayoutObjectDrawingRecorder.h"
12 #include "core/paint/PaintInfo.h"
13 #include "platform/graphics/GraphicsContextStateSaver.h"
14 #include <algorithm>
15
16 namespace blink {
17
18 // Comparator: returns
19 // -1 => e1 < e2
20 // 0 => e1 == e2
21 // 1 => e1 > e2
22 static int compareEdges(const TableCollapsedBorderPainter::EdgeRecord& e1, const TableCollapsedBorderPainter::EdgeRecord& e2)
23 {
24
25 // if (!e1.m_border) {
26 // if (!e2.m_border)
27 // return 0;
28 // else
29 // return -1;
30 // }
31 // if (!e2.m_border)
32 // return 1;
33
34 EBorderStyle e1Style = e1.m_border.style();
35 EBorderStyle e2Style = e2.m_border.style();
36
37 // RULES: https://www.w3.org/TR/CSS2/tables.html#border-conflict-resolution
38 // 1) Hidden edges win
39 // 2) None edges lose
40 // 3) Wider border-width win
41 // 4) Louder border-style win
42 // 5) Higher precedence wins
43
44 // Rule #1
45 if (e1Style == BorderStyleHidden) {
46 if (e2Style == BorderStyleHidden)
47 return 0;
48 // else
49 return 1;
50 }
51 if (e2Style == BorderStyleHidden)
52 return -1;
53
54 // Rule #2
55 if (e1Style == BorderStyleNone) {
56 if (e2Style == BorderStyleNone)
57 return 0;
58 // else
59 return -1;
60 }
61 if (e2Style == BorderStyleNone)
62 return 1;
63
64 // Rule #3
65 if (e1.m_border.width() < e2.m_border.width())
66 return -1;
67 // else
68 if (e2.m_border.width() < e1.m_border.width())
69 return 1;
70
71 // Rule #4
72 if (e1Style > e2Style)
73 return 1;
74 // else
75 if (e2Style > e1Style)
76 return -1;
77
78 // Rule #5
79 if (e1.m_precedence != e2.m_precedence)
80 return e1.m_precedence < e2.m_precedence ? -1 : 1;
81
82 return 0;
83 }
84
85 // Like compareEdges, except that HIDDEN edges lose
86 static int compareIntersectionEdges(const TableCollapsedBorderPainter::EdgeRecor d& e1, const TableCollapsedBorderPainter::EdgeRecord& e2)
87 {
88 EBorderStyle e1Style = e1.m_border.style();
89 EBorderStyle e2Style = e2.m_border.style();
90 // Rule #1
91 if (e1Style == BorderStyleHidden) {
92 if (e2Style == BorderStyleHidden)
93 return 0;
94 // else
95 return -1;
96 }
97 if (e2Style == BorderStyleHidden)
98 return 1;
99 return compareEdges(e1, e2);
100 }
101
102 #ifndef NDEBUG
103
104 static std::string directionToStr(TableCollapsedBorderPainter::EdgeDirection dir )
105 {
106 switch (dir) {
107 case TableCollapsedBorderPainter::North: return "North";
108 case TableCollapsedBorderPainter::West: return "West";
109 case TableCollapsedBorderPainter::East: return "East";
110 case TableCollapsedBorderPainter::South: return "South";
111 case TableCollapsedBorderPainter::None: return "None";
112 }
113 }
114
115 static std::string precedenceToStr(EBorderPrecedence p)
116 {
117 switch (p) {
118 case BorderPrecedenceOff: return "OFF";
119 case BorderPrecedenceTable: return "TABLE";
120 case BorderPrecedenceColumnGroup: return "COLGROUP";
121 case BorderPrecedenceColumn: return "COL";
122 case BorderPrecedenceRowGroup: return "ROWGROUP";
123 case BorderPrecedenceRow: return "ROW";
124 case BorderPrecedenceCell: return "CELL";
125 }
126 }
127
128 void TableCollapsedBorderPainter::showEdge(unsigned row, unsigned col, EdgeDirec tion direction, EBorderPrecedence precedence, const BorderValue& border, Color r esolvedColor) const
129 {
130 Color c = border.color().resolve(resolvedColor);
131 LOG(INFO) << "[" << row << " " << col << " " << directionToStr(direction)
132 << "] " << precedenceToStr(precedence) << " "
133 << border.width() << " " << c.serializedAsCSSComponentValue().ascii().da ta();
134 }
135
136 void TableCollapsedBorderPainter::showEdges(bool showHidden) const
137 {
138 LOG(INFO) << "edges";
139 for (auto r = m_startVisibleRow; r <= m_endVisibleRow; r++) {
140 LOG(INFO) << "row:" << r;
141 for (auto c = m_startVisibleColumn; c < m_endVisibleColumn; c++) {
142 auto edgeIdx = edgeToIndex(r, c, East);
143 if (edgeIdx != npos) {
144 EdgeRecord edge = m_edges[edgeIdx];
145 if (showHidden || edge.m_precedence != BorderPrecedenceOff)
146 showEdge(r, c, East, edge.m_precedence, edge.m_border, edge. m_resolvedColor);
147 }
148 edgeIdx = edgeToIndex(r, c, South);
149 if (edgeIdx != npos) {
150 EdgeRecord edge = m_edges[edgeIdx];
151 if (showHidden || edge.m_precedence != BorderPrecedenceOff)
152 showEdge(r, c, South, edge.m_precedence, edge.m_border, edge .m_resolvedColor);
153 }
154 }
155 }
156 }
157 void TableCollapsedBorderPainter::showVisibleEdges(const VisibleEdgeContainer& e dges) const
158 {
159 LOG(INFO) << "visedges";
160 for (auto edge = edges.begin() ; edge < edges.end(); edge++) {
161 showEdge((*edge).m_row, (*edge).m_column, (*edge).m_direction, (*edge).m _precedence, (*edge).m_border, (*edge).m_resolvedColor);
162 }
163 }
164
165 void TableCollapsedBorderPainter::showIntersection(unsigned row, unsigned col) c onst
166 {
167 auto i = intersectionToIndex(row, col);
168 if (i != npos) {
169 const Intersection in = m_intersections[i];
170 if (in.m_direction != None) {
171 LOG(INFO) << "[" << row << ", " << col << "] "
172 << in.m_width.toInt() << " " << in.m_height.toInt() << " Win:" < < directionToStr(in.m_direction);
173 }
174 }
175 }
176
177 void TableCollapsedBorderPainter::showIntersections() const
178 {
179 LOG(INFO) << "intersections";
180 for (auto r = m_startVisibleRow; r <= m_endVisibleRow; r++) {
181 for (auto c = m_startVisibleColumn; c < m_endVisibleColumn; c++) {
182 showIntersection(r, c);
183 }
184 }
185 }
186
187 #endif
188
189
190 void TableCollapsedBorderPainter::paintBorders(const PaintInfo& paintInfo, const LayoutPoint& paintOffset, const CellSpan& dirtyRows, const CellSpan& dirtyColum ns, const TableCollapsedBorderPainter& previousPainter)
191 {
192 initEdges(dirtyRows, dirtyColumns, previousPainter);
193 // draw all the edges
194 // initial algorithm: just draw everything
195 // later algorithms: draw continuous lines if possible
196 initIntersections();
197
198 paintEdges(paintInfo, paintOffset, dirtyRows, dirtyColumns);
199 }
200
201 void TableCollapsedBorderPainter::initEdges(const CellSpan& dirtyRows, const Cel lSpan& dirtyColumns, const TableCollapsedBorderPainter& previousPainter)
202 {
203 // Initialize sizes
204 // number of rows/cols in the section
205 m_numRows = m_layoutTableSection->numRows();
206 m_numEffectiveColumns = m_layoutTableSection->table()->numEffectiveColumns() ;
207
208 // Coordinates of intersections whose edges we'd like to measure.
209 // Measurement area is dirtyRows x dirtyCols + single-cell wide border zone above/left
210 // of dirty area.
211 //
212 // Border zone is needed to measure intersections inside dirty area correctl y.
213 //
214 // Number of intersections inside n-rows is n+1, inside m-cols is m+1
215 // start and end. End points to one beyond, equivalent to iterator's .end()
216 m_startVisibleRow = dirtyRows.start() == 0 ? 0 : dirtyRows.start() - 1;
217 m_startVisibleColumn = dirtyColumns.start() == 0 ? 0 : dirtyColumns.start() - 1;
218 m_endVisibleRow = dirtyRows.end() + 1;
219 m_endVisibleColumn = dirtyColumns.end() + 1;
220
221 unsigned edgeRowCount = m_endVisibleRow - m_startVisibleRow;
222 unsigned edgeColumnCount = m_endVisibleColumn - m_startVisibleColumn;
223 m_edges.resize(2 * edgeRowCount * edgeColumnCount);
224 populateEdges(dirtyRows, dirtyColumns, previousPainter);
225 #ifndef NDEBUG
226 // showEdges();
227 #endif
228 }
229
230 void TableCollapsedBorderPainter::initIntersections()
231 {
232 m_maxIntersectionWidth = 0;
233 m_maxIntersectionHeight = 0;
234 m_intersections.resize((m_endVisibleRow - m_startVisibleRow) * (m_endVisible Column - m_startVisibleColumn));
235 for (unsigned r = m_startVisibleRow; r < m_endVisibleRow; r++) {
236 for (unsigned c = m_startVisibleColumn; c < m_endVisibleColumn; c++) {
237 initIntersection(r, c);
238 }
239 }
240 #ifndef NDEBUG
241 // showIntersections();
242 #endif
243 }
244
245 void TableCollapsedBorderPainter::initIntersection(unsigned row, unsigned col)
246 {
247 EdgeRecord edges[None];
248
249 for (int d = North; d < None; d++) {
250 unsigned index = edgeToIndex(row, col, (EdgeDirection)d);
251 if (index != npos)
252 edges[d] = m_edges[index];
253 }
254
255 EdgeDirection winner = North;
256 for (int d = West; d < None; d++) {
257 if (compareIntersectionEdges(edges[winner], edges[d]) == -1)
258 winner = (EdgeDirection)d;
259 }
260
261 unsigned index = intersectionToIndex(row, col);
262 // only set if our winner is really an edge
263 if (edges[winner].m_precedence != BorderPrecedenceOff) {
264 unsigned width = 0;
265 unsigned height = 0;
266 if (winner == North || winner == South) {
267 width = edges[winner].m_border.width();
268 if (compareIntersectionEdges(edges[East], edges[West]) < 1) // West won
269 height = edges[West].m_border.width();
270 else
271 height = edges[East].m_border.width();
272 } else { // winner == East || West
273 height = edges[winner].m_border.width();
274 if (compareIntersectionEdges(edges[North], edges[South]) < 1) // Sou th won
275 width = edges[South].m_border.width();
276 else
277 width = edges[North].m_border.width();
278 }
279 m_maxIntersectionHeight = std::max(m_maxIntersectionHeight, height);
280 m_maxIntersectionWidth = std::max(m_maxIntersectionWidth, width);
281 m_intersections[index] = Intersection(LayoutUnit(width), LayoutUnit(heig ht), winner);
282 // LOG(INFO) << "In: " << row << " " << col << ": " << width << "px " << height << "px " << directionToStr(winner);
283 }
284 }
285
286 void TableCollapsedBorderPainter::populateEdges(const CellSpan& dirtyRows, const CellSpan& dirtyColumns, const TableCollapsedBorderPainter& previousPainter)
287 {
288 VisibleEdgeContainer edges;
289
290 // Iterate everything in reverse priority order
291
292 // populate adjacent edges from adjacent section
293 getVisibleEdgesSiblingSection(edges, previousPainter);
294 mergeVisibleEdges(edges);
295
296 LayoutTable * table = m_layoutTableSection->table();
297 // populate <table>
298 getVisibleEdgesTable(edges, m_layoutTableSection->table());
299 mergeVisibleEdges(edges);
300
301 // populate <colgroup>
302 Vector<const LayoutTableCol*>colgroups;
303 for (LayoutTableCol* colgroup = table->firstColumn(); colgroup; colgroup = c olgroup->nextColumn())
304 colgroups.append(colgroup);
305
306 for (auto colGroup = colgroups.rbegin(); colGroup != colgroups.rend(); colGr oup++) {
307 if ((*colGroup)->isTableColumnGroup()) {
308 getVisibleEdgesColgroup(edges, *colGroup);
309 mergeVisibleEdges(edges);
310 }
311 }
312 // populate <col>
313 for (auto col = colgroups.rbegin(); col != colgroups.rend(); col++) {
314 if ((*col)->isTableColumn()) {
315 getVisibleEdgesCol(edges, *col);
316 mergeVisibleEdges(edges);
317 }
318 }
319
320 // populate <tbody>
321 getVisibleEdgesSection(edges);
322 mergeVisibleEdges(edges);
323 // populate <tr>
324 for (int r = dirtyRows.end() - 1; r >= (int) dirtyRows.start(); r--) {
325 const LayoutTableRow * row = m_layoutTableSection->rowLayoutObjectAt(r);
326 if (row) {
327 getVisibleEdgesRow(edges, row);
328 mergeVisibleEdges(edges);
329 }
330 }
331 // populate <td>, iterate in reverse
332 TextDirection direction = m_layoutTableSection->style()->direction();
333 for (int r = dirtyRows.end() - 1; r >= (int) dirtyRows.start(); r--) {
334 for (int c = dirtyColumns.end() - 1; c >= (int)dirtyColumns.start(); c-- ) {
335 // HashSet for primary cell to eliminate duplicates
336 const LayoutTableCell * cell = m_layoutTableSection->primaryCellAt(r , c);
337 if (cell) {
338 getVisibleEdgesCell(edges, cell, direction);
339 mergeVisibleEdges(edges);
340 }
341 }
342 }
343 #ifndef NDEBUG
344 // showEdges();
345 #endif
346 }
347
348 // Gets edges of the neighboring section
349 void TableCollapsedBorderPainter::getVisibleEdgesSiblingSection(VisibleEdgeConta iner& edges, const TableCollapsedBorderPainter& previousPainter)
350 {
351 edges.clear();
352
353 bool isAbove = previousPainter.m_layoutTableSection == m_layoutTableSection- >table()->sectionAbove(m_layoutTableSection);
354
355 bool isBelow = previousPainter.m_layoutTableSection == m_layoutTableSection- >table()->sectionBelow(m_layoutTableSection);
356
357 if (!isAbove && !isBelow) {
358 // Happens if we are the first section
359 // LOG(INFO) << "not sure where sibling section is";
360 return;
361 }
362
363 unsigned siblingRow = isAbove ? previousPainter.m_numRows : 0;
364 unsigned myRow = isAbove ? 0 : m_numRows;
365 for (unsigned c = previousPainter.m_startVisibleColumn; c <= previousPainter .m_endVisibleColumn; c++) {
366 auto siblingIndex = previousPainter.edgeToIndex(siblingRow, c, East);
367 auto myIndex = edgeToIndex(myRow, c, East);
368 if (siblingIndex != npos && myIndex != npos) {
369 EdgeRecord siblingEdge = previousPainter.m_edges[siblingIndex];
370 edges.append(VisibleEdgeRecord(myRow, c, East, siblingEdge.m_border, siblingEdge.m_precedence, siblingEdge.m_resolvedColor));
371 }
372 }
373 }
374
375 void TableCollapsedBorderPainter::getVisibleEdgesTable(VisibleEdgeContainer& edg es, const LayoutTable * table)
376 {
377 edges.clear();
378 Color resolvedColor = table->resolveColor(CSSPropertyColor);
379 const ComputedStyle* borderStyle = table->style();
380 const BorderValue* topBorder = &borderStyle->borderTop();
381 const BorderValue* rightBorder = &borderStyle->borderRight();
382 const BorderValue* bottomBorder = &borderStyle->borderBottom();
383 const BorderValue* leftBorder = &borderStyle->borderLeft();
384
385 rotateBorders(m_layoutTableSection->style()->direction(), table->style()->ge tWritingMode(), &topBorder, &rightBorder, &bottomBorder, &leftBorder);
386
387 // top row, only if we abut table top
388 if (this->m_layoutTableSection == table->topNonEmptySection()) {
389 fillHorizontalEdges(edges, 0, 0, m_numEffectiveColumns, *topBorder, Bord erPrecedenceTable, resolvedColor);
390 }
391 // bottom row, only if we abut table bottom
392 if (this->m_layoutTableSection == table->bottomNonEmptySection()) {
393 fillHorizontalEdges(edges, m_numRows, 0, m_numEffectiveColumns, *bottomB order, BorderPrecedenceTable, resolvedColor);
394 }
395 fillVerticalEdges(edges, 0, 0, m_numRows, *leftBorder, BorderPrecedenceTable , resolvedColor);
396 fillVerticalEdges(edges, m_numEffectiveColumns, 0, m_numRows, *rightBorder, BorderPrecedenceTable, resolvedColor);
397 }
398
399 void TableCollapsedBorderPainter::getVisibleEdgesSection(VisibleEdgeContainer& e dges)
400 {
401 edges.clear();
402 Color resolvedColor = m_layoutTableSection->resolveColor(CSSPropertyColor);
403 // Traverse all the section edges, and assign them
404 fillVisibleRect(edges, 0, 0, m_numRows, m_numEffectiveColumns, m_layoutTable Section->style(),
405 LTR, m_layoutTableSection->style()->getWritingMode(), resolvedColor, Bo rderPrecedenceRowGroup);
406 }
407
408 void TableCollapsedBorderPainter::getVisibleEdgesColgroup(VisibleEdgeContainer& edges, const LayoutTableCol * colgroup)
409 {
410 edges.clear();
411 Color resolvedColor = colgroup->resolveColor(CSSPropertyColor);
412 Vector<unsigned> indexes = colgroup->getEffectiveColumnIndexes();
413 if (indexes.size() > 0) {
414 unsigned startColIndex = indexes[0];
415 unsigned endColIndex = indexes.last() + 1;
416 fillVisibleRect(edges, 0, startColIndex, m_numRows, endColIndex, colgrou p->style(),
417 colgroup->style()->direction(), colgroup->style()->getWritingMode(), resolvedColor, BorderPrecedenceColumnGroup);
418 }
419 }
420
421 void TableCollapsedBorderPainter::getVisibleEdgesCol(VisibleEdgeContainer& edges , const LayoutTableCol * col)
422 {
423 edges.clear();
424 Color resolvedColor = col->resolveColor(CSSPropertyColor);
425 LayoutTable* table = m_layoutTableSection->table();
426 if (!table)
427 return;
428
429 Vector<unsigned> indexes = col->getEffectiveColumnIndexes();
430 if (indexes.size() > 0) {
431 // fill multiple virtual columns
432 for (auto idx = indexes.rbegin(); idx!= indexes.rend(); ++idx) {
433 fillVisibleRect(edges, 0, *idx, m_numRows, *idx + 1, col->style(),
434 col->style()->direction(), col->style()->getWritingMode(), resol vedColor, BorderPrecedenceColumn);
435 }
436 }
437 // unsigned startAbsoluteColIndex = table->colElementToAbsoluteColumn(col);
438 // unsigned endAbsoluteColIndex = startAbsoluteColIndex + col->span();
439 // unsigned startColIndex = table->absoluteColumnToEffectiveColumn(startAbso luteColIndex);
440 // unsigned endColIndex = table->absoluteColumnToEffectiveColumn(endAbsolute ColIndex);
441
442 // // We replicat column span times. Weird, but that is the standard:
443 // // "For the purposes of the CSS table model, the col element is expected to be treated as if it was present as many times as its span attribute specifies ."
444 // for (auto tmpEnd = endColIndex; tmpEnd > startColIndex; tmpEnd--) {
445 // fillVisibleRect(edges, 0, tmpEnd - 1, m_numRows, tmpEnd, col->style() ,
446 // col->style()->direction(), col->style()->getWritingMode(), resolv edColor, BorderPrecedenceColumn);
447 // }
448 }
449
450 void TableCollapsedBorderPainter::getVisibleEdgesRow(VisibleEdgeContainer& edges , const LayoutTableRow * row)
451 {
452 edges.clear();
453 Color resolvedColor = row->resolveColor(CSSPropertyColor);
454 unsigned rowIndex = row->rowIndex();
455 // We get direction from section because row direction only applies to cells ,
456 // not the entire row.
457 fillVisibleRect(edges, rowIndex, 0, rowIndex + 1, m_numEffectiveColumns, row ->style(),
458 m_layoutTableSection->style()->direction(), row->style()->getWritingMode (), resolvedColor, BorderPrecedenceRow);
459 }
460
461 void TableCollapsedBorderPainter::getVisibleEdgesCell(VisibleEdgeContainer& edge s, const LayoutTableCell * cell, TextDirection direction)
462 {
463 edges.clear();
464 Color resolvedColor = cell->resolveColor(CSSPropertyColor);
465
466 if (!cell->parent()) {
467 LOG(INFO) << "DETACHED CELL";
468 return;
469 }
470
471 const LayoutTable * table = m_layoutTableSection->table();
472 unsigned startRow = cell->parent() ? cell->rowIndex() : 65000;
473 unsigned absoluteCol = cell->absoluteColumnIndex();
474
475
476 unsigned effStartCol = table->absoluteColumnToEffectiveColumn(absoluteCol);
477 unsigned effEndCol = table->absoluteColumnToEffectiveColumn(absoluteCol + ce ll->colSpan());
478 unsigned endRow = std::min(startRow + cell->rowSpan(), m_numRows);
479
480 // LOG(INFO) << "m_columns: " << table->effectiveColumns().size()
481 // << " startRow: " << startRow << " endRow: " << endRow
482 // << " startCol: " << effStartCol << " endCol:" << effEndCol
483 // << " abscol:" << absoluteCol;
484
485 // Fill border
486 // cell's direction is LTR because we do not rotate cell's borders
487 fillVisibleRect(edges, startRow, effStartCol, endRow, effEndCol, cell->style (),
488 direction, cell->style()->getWritingMode(), resolvedColor, BorderPrecede nceCell);
489
490 // Hide row inner edges
491 for (unsigned row = startRow + 1; row < endRow; row++) {
492 if (row >= m_startVisibleRow && row < m_endVisibleRow) {
493 for (unsigned effCol = effStartCol; effCol < effEndCol; effCol++) {
494 if (effCol >= m_startVisibleColumn && effCol < m_endVisibleColum n) {
495 edges.append(VisibleEdgeRecord(row, effCol, East, m_hiddenBo rder, BorderPrecedenceCell, resolvedColor, true));
496 }
497 }
498 }
499 }
500 // Hide col inner edges
501 for (unsigned effCol = effStartCol + 1; effCol < effEndCol; effCol++) {
502 if (effCol >= m_startVisibleColumn && effCol < m_endVisibleColumn) {
503 for (unsigned row = startRow; row < endRow; row++) {
504 if (row >= m_startVisibleRow && row < m_endVisibleRow) {
505 edges.append(VisibleEdgeRecord(row, effCol, South, m_hiddenB order, BorderPrecedenceCell, resolvedColor, true));
506 }
507 }
508 }
509 }
510 #ifdef NDEBUG
511 // showVisibleEdges(edges);
512 #endif
513 }
514
515
516 void TableCollapsedBorderPainter::rotateBorders(TextDirection textDirection, Wri tingMode writingMode,
517 const BorderValue** top, const BorderValue** right, const BorderValue** bott om, const BorderValue** left) const
518 {
519 bool isLTR = blink::isLeftToRightDirection(textDirection);
520 if (blink::isHorizontalWritingMode(writingMode)) {
521 if (isLTR)
522 {} // do nothing
523 else {
524 std::swap(*right, *left);
525 }
526 } else if (blink::isFlippedBlocksWritingMode(writingMode)) {
527 if (isLTR) {
528 auto tmp = *top;
529 *top = *right;
530 *right = *bottom;
531 *bottom = *left;
532 *left = tmp;
533 } else {
534 std::swap(*top, *right);
535 std::swap(*bottom, *left);
536 }
537 } else { // isFlippedLinesWritingMode
538 if (isLTR) {
539 std::swap(*bottom, *right);
540 std::swap(*left, *top);
541 } else {
542 auto tmp = *top;
543 *top = *left;
544 *left = *bottom;
545 *bottom = *right;
546 *right = tmp;
547 }
548 }
549 }
550
551 void TableCollapsedBorderPainter::fillVisibleRect(VisibleEdgeContainer& edges,
552 unsigned startRow, unsigned startColumn, unsigned endRow, unsigned endColumn ,
553 const ComputedStyle* borderStyle, TextDirection textDirection, WritingMode w ritingMode,
554 Color resolvedColor, EBorderPrecedence precedence)
555 {
556 const BorderValue* topBorder = &borderStyle->borderTop();
557 const BorderValue* bottomBorder = &borderStyle->borderBottom();
558 const BorderValue* rightBorder = &borderStyle->borderRight();
559 const BorderValue* leftBorder = &borderStyle->borderLeft();
560
561 rotateBorders(textDirection, writingMode, &topBorder, &rightBorder, &bottomB order, &leftBorder);
562
563 fillHorizontalEdges(edges, startRow, startColumn, endColumn, *topBorder, pre cedence, resolvedColor);
564 fillHorizontalEdges(edges, endRow, startColumn, endColumn, *bottomBorder, pr ecedence, resolvedColor);
565 fillVerticalEdges(edges, startColumn, startRow, endRow, *leftBorder, precede nce, resolvedColor);
566 fillVerticalEdges(edges, endColumn, startRow, endRow, *rightBorder, preceden ce, resolvedColor);
567 }
568
569 void TableCollapsedBorderPainter::fillHorizontalEdges(VisibleEdgeContainer& edge s, unsigned row, unsigned startColumn, unsigned endColumn,
570 const BorderValue &border, EBorderPrecedence precedence, Color resolvedColor )
571 {
572 if (border.style() == BorderStyleNone)
573 return;
574
575 if (row >= m_startVisibleRow && row < m_endVisibleRow) {
576 for (unsigned c = startColumn; c < endColumn; c++) {
577 // FIXME: modify for loop instead of comparing guard
578 if (c >= m_startVisibleColumn && c < m_endVisibleColumn)
579 edges.append(VisibleEdgeRecord(row, c, East, border, precedence, resolvedColor));
580 }
581 }
582 }
583
584 void TableCollapsedBorderPainter::fillVerticalEdges(VisibleEdgeContainer& edges, unsigned column, unsigned startRow, unsigned endRow, const BorderValue &border, EBorderPrecedence precedence, Color resolvedColor)
585 {
586 if (border.style() == BorderStyleNone)
587 return;
588
589 if (column >= m_startVisibleColumn && column < m_endVisibleColumn) {
590 for (unsigned r = startRow; r < endRow; r++) {
591 // FIXME: modify for loop instead of comparing guard
592 if (r >= m_startVisibleRow && r < m_endVisibleRow)
593 edges.append(VisibleEdgeRecord(r, column, South, border, precede nce, resolvedColor));
594 }
595 }
596 }
597
598 void TableCollapsedBorderPainter::mergeVisibleEdges(VisibleEdgeContainer& edges)
599 {
600 for (auto edge = edges.begin(); edge < edges.end(); edge++) {
601 unsigned idx = edgeToIndex((*edge).m_row, (*edge).m_column, (*edge).m_di rection);
602 ASSERT(idx != npos);
603 EdgeRecord edgeRecord((*edge).m_border, (*edge).m_precedence, (*edge).m_ resolvedColor);
604 if ((*edge).m_forceRemoval)
605 m_edges[idx] = edgeRecord;
606 // if both edges are same priority, new edge wins
607 if (compareEdges(m_edges[idx], edgeRecord ) != 1)
608 m_edges[idx] = edgeRecord;
609 }
610 }
611
612 static EBorderStyle collapsedBorderStyle(EBorderStyle style)
613 {
614 if (style == BorderStyleOutset)
615 return BorderStyleGroove;
616 if (style == BorderStyleInset)
617 return BorderStyleRidge;
618 return style;
619 }
620
621 void TableCollapsedBorderPainter::paintEdges(const PaintInfo& paintInfo, const L ayoutPoint& paintOffset, const CellSpan& rows, const CellSpan& cols)
622 {
623 // see TableCellPainter::paintCollapsedBorders
624 LayoutRect paintRect = m_layoutTableSection->getCellPhysicalPosition(rows.st art(), cols.start());
625 paintRect.unite(m_layoutTableSection->getCellPhysicalPosition(rows.end() > 0 ? rows.end() - 1 : 0, cols.end() > 0 ? cols.end() - 1 : 0));
626
627 // paintRect size calculation is not exact, we expand by maxborder, instead of exact border
628 paintRect.expand(LayoutSize(LayoutUnit(m_maxIntersectionWidth * 2), LayoutUn it(m_maxIntersectionHeight * 2)));
629 paintRect.moveBy(paintOffset);
630
631 LayoutPoint location = m_layoutTableSection->location();
632 paintRect.moveBy(location);
633
634 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(
635 paintInfo.context,
636 *m_layoutTableSection,
637 DisplayItem::TableCollapsedBorderBase))
638 return;
639 LayoutObjectDrawingRecorder recorder(
640 paintInfo.context,
641 *m_layoutTableSection,
642 DisplayItem::TableCollapsedBorderBase,
643 paintRect);
644
645 // Paint edges carefully to get them all
646 // Every row paint : ┌┌┌┌┌, then |
647 // Bottom border paint: _____
648 WritingMode writingMode = m_layoutTableSection->style()->getWritingMode();
649 TextDirection textDirection = m_layoutTableSection->style()->direction();
650 for (unsigned r = rows.start(); r < rows.end(); r++) {
651 // const LayoutTableRow * row = m_layoutTableSection->rowLayoutObjectAt( r);
652 // if (row)
653 // textDirection = row->style()->direction();
654 for (unsigned c = cols.start(); c < cols.end(); c++) {
655 paintOneEdge(paintInfo, paintOffset, r, c, East, writingMode, textDi rection);
656 paintOneEdge(paintInfo, paintOffset, r, c, South, writingMode, textD irection);
657 }
658 // paint the last column on edge
659 paintOneEdge(paintInfo, paintOffset, r, cols.end(), South, writingMode, textDirection);
660 }
661 // Paint the last row
662 for (unsigned c = cols.start(); c < cols.end(); c++)
663 paintOneEdge(paintInfo, paintOffset, rows.end(), c, East, writingMode, t extDirection);
664 }
665
666 // Returns a rect that encloses 'direction' border of the cellRect
667 LayoutRect TableCollapsedBorderPainter::cellRectAsBorder(const LayoutRect& cellR ect, BoxSide side, unsigned borderWidth, WritingMode writingMode, TextDirection textDirection)
668 {
669
670 unsigned smallHalf = borderWidth / 2; // C++ always rounds down
671 unsigned bigHalf = borderWidth - smallHalf;
672
673 unsigned topOffset;
674 unsigned leftOffset;
675
676 /* Tricky: if the border width is odd, we need a consistent way of
677 distributing the extra pixel. The rule is:
678 - south and east edges always get the extra pixel on the inside
679 of the cell
680 */
681
682 bool isLTR = blink::isLeftToRightDirection(textDirection);
683 if (blink::isHorizontalWritingMode(writingMode)) {
684 if (isLTR) {
685 topOffset = smallHalf;
686 leftOffset = smallHalf;
687 } else {
688 topOffset = smallHalf;
689 leftOffset = bigHalf;
690 }
691 } else { // vertical
692 if (blink::isFlippedBlocksWritingMode(writingMode)) {
693 if (isLTR) {
694 topOffset = smallHalf;
695 leftOffset = bigHalf;
696 } else {
697 topOffset = bigHalf;
698 leftOffset = bigHalf;
699 }
700 } else { // flippedLines
701 if (isLTR) {
702 topOffset = smallHalf;
703 leftOffset = smallHalf;
704 } else {
705 topOffset = bigHalf;
706 leftOffset = smallHalf;
707 }
708 }
709 }
710 switch (side) {
711 case BSTop:
712 return LayoutRect(
713 LayoutPoint(cellRect.x(), cellRect.y() - topOffset),
714 LayoutSize(cellRect.width(), LayoutUnit(borderWidth)));
715 case BSBottom:
716 return LayoutRect(
717 LayoutPoint(cellRect.x(), cellRect.maxY() - topOffset),
718 LayoutSize(cellRect.width(), LayoutUnit(borderWidth)));
719 case BSLeft:
720 return LayoutRect(
721 LayoutPoint(cellRect.x() - leftOffset, cellRect.y()),
722 LayoutSize(LayoutUnit(borderWidth), cellRect.height()));
723 case BSRight:
724 return LayoutRect(
725 LayoutPoint(cellRect.maxX() - leftOffset, cellRect.y()),
726 LayoutSize(LayoutUnit(borderWidth), cellRect.height()));
727 }
728
729 }
730 //
731 LayoutRect TableCollapsedBorderPainter::edgePaintPosition(unsigned row, unsigned col, unsigned borderWidth, EdgeDirection direction, WritingMode writingMode, Te xtDirection textDirection)
732 {
733 // Compute edge's size from size of the cell
734 LayoutRect position;
735
736 bool isLTR = blink::isLeftToRightDirection(textDirection);
737 BoxSide side = BSLeft;
738 LayoutRect cellRect;
739 // If this is the last row intersection, get size from cell in next to last
740 if (row == m_numRows) {
741 ASSERT(direction == East);
742 cellRect = getCellPhysicalPosition(row - 1, col);
743 if (blink::isHorizontalWritingMode(writingMode)) {
744 side = BSBottom;
745 } else if (blink::isFlippedBlocksWritingMode(writingMode)) {
746 side = BSLeft;
747 } else {
748 side = BSRight;
749 }
750 } else if (col == m_numEffectiveColumns) {
751 // If this is the last column, get size from the cell before
752 ASSERT(direction == South);
753 cellRect = getCellPhysicalPosition(row, col - 1);
754 if (blink::isHorizontalWritingMode(writingMode)) {
755 side = isLTR ? BSRight : BSLeft;
756 } else if (blink::isFlippedBlocksWritingMode(writingMode)) {
757 side = isLTR ? BSBottom : BSTop;
758 } else {
759 side = isLTR ? BSBottom : BSTop;
760 }
761 } else {
762 cellRect = getCellPhysicalPosition(row, col);
763 if (direction == East) {
764 if (blink::isHorizontalWritingMode(writingMode)) {
765 side = BSTop;
766 } else if (blink::isFlippedBlocksWritingMode(writingMode)) {
767 side = BSRight;
768 } else {
769 side = BSLeft;
770 }
771 } else { // direction == South
772 if (blink::isHorizontalWritingMode(writingMode)) {
773 side = isLTR ? BSLeft : BSRight;
774 } else if (blink::isFlippedBlocksWritingMode(writingMode)) {
775 side = isLTR ? BSTop : BSBottom;
776 } else { // flippedLines
777 side = isLTR ? BSTop : BSBottom;
778 }
779 }
780 }
781 return cellRectAsBorder(cellRect, side, borderWidth, writingMode, textDirect ion);
782 }
783
784 // Paints an edge starting from intersection[row, col] in direction
785 void TableCollapsedBorderPainter::paintOneEdge(
786 const PaintInfo& paintInfo, const LayoutPoint& paintOffset,
787 unsigned row, unsigned col, EdgeDirection direction,
788 WritingMode writingMode, TextDirection textDirection)
789 {
790 ASSERT(direction == South || direction == East);
791
792 unsigned idx = edgeToIndex(row, col, direction);
793 ASSERT(idx != npos);
794 const BorderValue& border = m_edges[idx].m_border;
795
796 if (border.style() == BorderStyleHidden || !border.nonZero())
797 return;
798
799 #ifndef NDEBUG
800 // LOG(INFO) << "painting";
801 // EdgeRecord edge = m_edges[idx];
802 // showEdge(row, col, direction, edge.m_precedence, edge.m_border, border->c olor().resolve(m_edges[idx].m_resolvedColor));
803 #endif
804 LayoutRect position = edgePaintPosition(row, col, border.width(), direction, writingMode, textDirection);
805
806 // LOG(INFO) << "paint " << position.x().toInt() << ", " << position.y().toI nt() << "; "
807 // << position.width().toInt() << ", " << position.height().toInt();
808
809 adjustForIntersections(position, row, col, direction, writingMode, textDirec tion);
810
811 // LOG(INFO) << "intersection " << position.x().toInt() << ", " << position. y().toInt() << "; "
812 // << position.width().toInt() << ", " << position.height().toInt();
813
814 // Offset by sectionLocation
815 LayoutPoint sectionLocation = m_layoutTableSection->location();
816 position.moveBy(sectionLocation);
817 position.moveBy(paintOffset);
818
819 BoxSide side;
820 if (blink::isHorizontalWritingMode(writingMode))
821 side = direction == East ? BSTop : BSLeft;
822 else
823 side = direction == East ? BSLeft : BSTop;
824
825 ObjectPainter::drawLineForBoxSide(
826 paintInfo.context,
827 position.x(), position.y(), position.maxX(), position.maxY(), // left, t op, right, bottom,
828 side,
829 border.color().resolve(m_edges[idx].m_resolvedColor),
830 collapsedBorderStyle(border.style()),
831 0, 0, true);
832 }
833
834 void TableCollapsedBorderPainter::adjustForIntersections(LayoutRect& position, u nsigned row, unsigned col, EdgeDirection direction, WritingMode writingMode, Tex tDirection textDirection)
835 {
836
837 ASSERT(direction == South || direction == East);
838
839 const Intersection * startIntersection = nullptr;
840 const Intersection * endIntersection = nullptr;
841 bool winnerStart = false;
842 bool winnerEnd = false;
843 // START intersection
844 unsigned index = intersectionToIndex(row, col);
845 if (index != npos) {
846 startIntersection = &m_intersections[index];
847 winnerStart = startIntersection->m_direction == direction;
848 }
849 // END intersection
850 if (direction == South)
851 row += 1;
852 else
853 col += 1;
854 index = intersectionToIndex(row, col);
855 if (index != npos) {
856 endIntersection = &m_intersections[index];
857 if (direction == South)
858 winnerEnd = endIntersection->m_direction == North;
859 else
860 winnerEnd = endIntersection->m_direction == West;
861 }
862
863 bool isLTR = blink::isLeftToRightDirection(textDirection);
864
865 if (blink::isHorizontalWritingMode(writingMode))
866 adjustForIntersectionsHorizontal(position, direction, isLTR, startInters ection, winnerStart, endIntersection, winnerEnd);
867 else if (blink::isFlippedBlocksWritingMode(writingMode))
868 adjustForIntersectionsFlippedBlocks(position, direction, isLTR, startInt ersection, winnerStart, endIntersection, winnerEnd);
869 else if (blink::isFlippedLinesWritingMode(writingMode))
870 adjustForIntersectionsFlippedLines(position, direction, isLTR, startInte rsection, winnerStart, endIntersection, winnerEnd);
871 else
872 ASSERT(false);
873 }
874
875 /*
876 writing-mode: HORIZONTAL-TB
877 N
878 compass: W--+--E intersection: <--width -->
879 S
880 start intersection
881 South edge, win : expand top by height/2
882 South edge, lose: shrink top by height/2
883 East edge, win : expand left by width/2
884 East edge, lose : shrink left by width/2
885 end intersection
886 South edge, win : expand bottom by height/2
887 South edge lose : shrink bottom by height/2
888 East edge, win : expand right by width/2
889 East edge, lose : shrink right by width/2
890
891 writing-mode: HORIZONTAL(RTL)
892 N
893 compass: E--+--W intersection: <-- width -->
894 S
895 same as HORIZONTAL-TB in South direction
896 start intersection
897 South: same as LTR
898 East edge, win : expand right by width/2
899 East edge, lose : shrink right by width/2
900 end intersection
901 South: same as LTR
902 East edge, win : expand left by width/2
903 East edge, lose : shrink left by width/2
904 */
905 void TableCollapsedBorderPainter::adjustForIntersectionsHorizontal(LayoutRect& p osition, EdgeDirection direction, bool isLTR,
906 const Intersection* startIntersection, bool winnerStart,
907 const Intersection* endIntersection, bool winnerEnd)
908 {
909 if (startIntersection) {
910
911 if (direction == South) {
912 unsigned smallDelta = startIntersection->m_height.toUnsigned() / 2;
913 unsigned bigDelta = startIntersection->m_height.toUnsigned() - small Delta;
914 if (winnerStart)
915 position.expandEdges(LayoutUnit(smallDelta), LayoutUnit(0), Layo utUnit(0), LayoutUnit(0));
916 else
917 position.contractEdges(LayoutUnit(bigDelta), LayoutUnit(0), Layo utUnit(0), LayoutUnit(0));
918 } else { // East
919 unsigned smallDelta = startIntersection->m_width.toUnsigned() / 2;
920 unsigned bigDelta = startIntersection->m_width.toUnsigned() - smallD elta;
921 if (isLTR) {
922 if (winnerStart) {
923 position.expandEdges(LayoutUnit(0), LayoutUnit(0), LayoutUni t(0), LayoutUnit(smallDelta));
924 } else {
925 position.contractEdges(LayoutUnit(0), LayoutUnit(0), LayoutU nit(0), LayoutUnit(bigDelta));
926 }
927 } else { // RTL
928 if (winnerStart) {
929 position.expandEdges(LayoutUnit(0), LayoutUnit(smallDelta), LayoutUnit(0), LayoutUnit(0));
930 } else {
931 position.contractEdges(LayoutUnit(0), LayoutUnit(bigDelta), LayoutUnit(0), LayoutUnit(0));
932 }
933 }
934 }
935 }
936 if (endIntersection) {
937 if (direction == South) {
938 unsigned smallDelta = endIntersection->m_height.toUnsigned() / 2;
939 unsigned bigDelta = endIntersection->m_height.toUnsigned() - smallDe lta;
940 if (winnerEnd)
941 position.expandEdges(LayoutUnit(0), LayoutUnit(0), LayoutUnit(bi gDelta), LayoutUnit(0));
942 else
943 position.contractEdges(LayoutUnit(0), LayoutUnit(0), LayoutUnit( smallDelta), LayoutUnit(0));
944 } else { // East
945 unsigned smallDelta = endIntersection->m_width.toUnsigned() / 2;
946 unsigned bigDelta = endIntersection->m_width.toUnsigned() - smallDel ta;
947 if (isLTR) {
948 if (winnerEnd) {
949 position.expandEdges(LayoutUnit(0), LayoutUnit(bigDelta), La youtUnit(0), LayoutUnit(0));
950 } else { // loser
951 position.contractEdges(LayoutUnit(0), LayoutUnit(smallDelta) , LayoutUnit(0), LayoutUnit(0));
952 }
953 } else { // RTL
954 if (winnerEnd)
955 position.expandEdges(LayoutUnit(0), LayoutUnit(0), LayoutUni t(0), LayoutUnit(bigDelta));
956 else
957 position.contractEdges(LayoutUnit(0), LayoutUnit(0), LayoutU nit(0), LayoutUnit(smallDelta));
958 }
959 }
960 }
961 }
962
963 /*
964 writing-mode: VERTICAL-RL (flipped blocks)
965 W
966 compass: vertical: S--+--N intersection: <--- height ---->
967 E
968
969 start intersection
970 South edge, win : expand right by height/2
971 South edge, lose: shrink right by height/2
972 East edge, win : expand top by width/2
973 East edge, lose : shrink top by width/2
974 end intersection
975 South edge, win : expand left by height/2
976 South edge, lose: shrink left by height/2
977 East edge, win : expand bottom by width/2
978 East edge, lose : shrink bottom by width/2
979
980 writing-mode: VERTICAL-RL RTL
981 E
982 compass: vertical: S--+--N intersection: <--- height ---->
983 W
984 start intersection
985 South edge, win : expand right by height/2
986 South edge, lose: shrink right by height/2
987 East edge, win : expand bottom by width/2
988 East edge, lose : shrink bottom by width/2
989 end intersection
990 South edge, win : expand left by height/2
991 South edge, lose: shrink left by height/2
992 East edge, win : expand top by width/2
993 East edge, lose : shrink top by width/2
994
995 */
996 void TableCollapsedBorderPainter::adjustForIntersectionsFlippedBlocks(LayoutRect & position, EdgeDirection direction, bool isLTR,
997 const Intersection* startIntersection, bool winnerStart,
998 const Intersection* endIntersection, bool winnerEnd)
999 {
1000 if (startIntersection) {
1001
1002 if (direction == South) {
1003 unsigned smallDelta = startIntersection->m_height.toUnsigned() / 2;
1004 unsigned bigDelta = startIntersection->m_height.toUnsigned() - small Delta;
1005 if (winnerStart)
1006 position.expandEdges(LayoutUnit(0), LayoutUnit(smallDelta), Layo utUnit(0), LayoutUnit(0));
1007 else
1008 position.contractEdges(LayoutUnit(0), LayoutUnit(bigDelta), Layo utUnit(0), LayoutUnit(0));
1009 } else { // East
1010 unsigned smallDelta = startIntersection->m_width.toUnsigned() / 2;
1011 unsigned bigDelta = startIntersection->m_width.toUnsigned() - smallD elta;
1012 if (isLTR) {
1013 if (winnerStart) {
1014 position.expandEdges(LayoutUnit(smallDelta), LayoutUnit(0), LayoutUnit(0), LayoutUnit(0));
1015 } else {
1016 position.contractEdges(LayoutUnit(bigDelta), LayoutUnit(0), LayoutUnit(0), LayoutUnit(0));
1017 }
1018 } else { // RTL
1019 if (winnerStart) {
1020 position.expandEdges(LayoutUnit(0), LayoutUnit(0), LayoutUni t(bigDelta), LayoutUnit(0));
1021 } else {
1022 position.contractEdges(LayoutUnit(0), LayoutUnit(0), LayoutU nit(smallDelta), LayoutUnit(0));
1023 }
1024 }
1025 }
1026 }
1027 if (endIntersection) {
1028 if (direction == South) {
1029 unsigned smallDelta = endIntersection->m_height.toUnsigned() / 2;
1030 unsigned bigDelta = endIntersection->m_height.toUnsigned() - smallDe lta;
1031 if (winnerEnd)
1032 position.expandEdges(LayoutUnit(0), LayoutUnit(0), LayoutUnit(0) , LayoutUnit(bigDelta));
1033 else
1034 position.contractEdges(LayoutUnit(0), LayoutUnit(0), LayoutUnit( 0), LayoutUnit(smallDelta));
1035 } else { // East
1036 unsigned smallDelta = endIntersection->m_width.toUnsigned() / 2;
1037 unsigned bigDelta = endIntersection->m_width.toUnsigned() - smallDel ta;
1038 if (isLTR) {
1039 if (winnerEnd)
1040 position.expandEdges(LayoutUnit(0), LayoutUnit(0), LayoutUni t(bigDelta), LayoutUnit(0));
1041 else // loser
1042 position.contractEdges(LayoutUnit(0), LayoutUnit(0), LayoutU nit(smallDelta), LayoutUnit(0));
1043 } else { // RTL
1044 if (winnerEnd)
1045 position.expandEdges(LayoutUnit(bigDelta), LayoutUnit(0), La youtUnit(0), LayoutUnit(0));
1046 else
1047 position.contractEdges(LayoutUnit(smallDelta), LayoutUnit(0) , LayoutUnit(0), LayoutUnit(0));
1048 }
1049 }
1050 }
1051 }
1052
1053 /*
1054 writing-mode: VERTICAL-LR (flipped lines)
1055 W
1056 compass: rotated N--+--S
1057 E
1058 start intersection
1059 East edge, win : expand top by width/2
1060 East edge, lose : shrink top by width/2
1061 South edge, win : expand left by height/2
1062 South edge, lose: shrink left by height/2
1063 end intersection
1064 East edge, win : expand bottom by width/2
1065 East edge, lose : shrink bottom by width/2
1066 South edge, win : expand right by height/2
1067 South edge lose : shrink right by height/2
1068
1069 writing-mode: VERTICAL-LR, DIRECTION RTL
1070 E
1071 compass: N-+-S intersection <--height -->
1072 W
1073 start intersection
1074 East edge. win : expand bottom by width / 2
1075 East edge, lose: shrink bottom by width / 2
1076 end intersection
1077 East edge, win : expand top by width / 2
1078 East edge, lose: expand top by width / 2
1079 */
1080
1081 void TableCollapsedBorderPainter::adjustForIntersectionsFlippedLines(LayoutRect& position, EdgeDirection direction, bool isLTR,
1082 const Intersection* startIntersection, bool winnerStart,
1083 const Intersection* endIntersection, bool winnerEnd)
1084 {
1085 if (startIntersection) {
1086
1087 if (direction == South) {
1088 unsigned smallDelta = startIntersection->m_height.toUnsigned() / 2;
1089 unsigned bigDelta = startIntersection->m_height.toUnsigned() - small Delta;
1090 if (winnerStart)
1091 position.expandEdges(LayoutUnit(0), LayoutUnit(0), LayoutUnit(0) , LayoutUnit(smallDelta));
1092 else
1093 position.contractEdges(LayoutUnit(0), LayoutUnit(0), LayoutUnit( 0), LayoutUnit(bigDelta));
1094 } else { // East
1095 unsigned smallDelta = startIntersection->m_width.toUnsigned() / 2;
1096 unsigned bigDelta = startIntersection->m_width.toUnsigned() - smallD elta;
1097 if (isLTR) {
1098 if (winnerStart) {
1099 position.expandEdges(LayoutUnit(smallDelta), LayoutUnit(0), LayoutUnit(0), LayoutUnit(0));
1100 } else {
1101 position.contractEdges(LayoutUnit(bigDelta), LayoutUnit(0), LayoutUnit(0), LayoutUnit(0));
1102 }
1103 } else { // RTL
1104 if (winnerStart) {
1105 position.expandEdges(LayoutUnit(0), LayoutUnit(0), LayoutUni t(smallDelta), LayoutUnit(0));
1106 } else {
1107 position.contractEdges(LayoutUnit(0), LayoutUnit(0), LayoutU nit(bigDelta), LayoutUnit(0));
1108 }
1109 }
1110 }
1111 }
1112 if (endIntersection) {
1113 if (direction == South) {
1114 unsigned smallDelta = endIntersection->m_height.toUnsigned() / 2;
1115 unsigned bigDelta = endIntersection->m_height.toUnsigned() - smallDe lta;
1116 if (winnerEnd)
1117 position.expandEdges(LayoutUnit(0), LayoutUnit(bigDelta), Layout Unit(0), LayoutUnit(0));
1118 else
1119 position.contractEdges(LayoutUnit(0), LayoutUnit(smallDelta), La youtUnit(0), LayoutUnit(0));
1120 } else { // East
1121 unsigned smallDelta = endIntersection->m_width.toUnsigned() / 2;
1122 unsigned bigDelta = endIntersection->m_width.toUnsigned() - smallDel ta;
1123 if (isLTR) {
1124 if (winnerEnd) {
1125 position.expandEdges(LayoutUnit(0), LayoutUnit(0), LayoutUni t(bigDelta), LayoutUnit(0));
1126 } else { // loser
1127 position.contractEdges(LayoutUnit(0), LayoutUnit(0), LayoutU nit(smallDelta), LayoutUnit(0));
1128 }
1129 } else { // RTL
1130 if (winnerEnd) {
1131 position.expandEdges(LayoutUnit(bigDelta), LayoutUnit(0), La youtUnit(0), LayoutUnit(0));
1132 } else {
1133 position.contractEdges(LayoutUnit(smallDelta), LayoutUnit(0) , LayoutUnit(0), LayoutUnit(0));
1134 }
1135 }
1136 }
1137 }
1138 }
1139
1140 // returns edge index for position, TableCollapsedBorderPainter::npos if out of range
1141 // topLeft intersection is 0, 0, bottomRight is numRows+1, numColumns + 1
1142 unsigned TableCollapsedBorderPainter::edgeToIndex(unsigned intersectionRow, unsi gned intersectionColumn, EdgeDirection direction) const
1143 {
1144 /* Edges map to m_edges like this:
1145 - each intersection 'stores' only two edges: east and south edges
1146 - to map edge to index:
1147 - find intersection so that requested edge is east or south
1148 - edge is row * cols * 2 + (east ? 0 : 1)
1149 - for example:
1150 - North edge at intersection 5, 3, is also South edge at intersection 4, 3
1151 - its index is 4 (rows) * 3 (cols) * 2 + 1 (for South)
1152 */
1153 switch (direction) {
1154 case North:
1155 intersectionRow -= 1;
1156 direction = South;
1157 break;
1158 case West:
1159 intersectionColumn -= 1;
1160 direction = East;
1161 break;
1162 case South:
1163 case East:
1164 case None:
1165 break;
1166 }
1167 // Check if we are inside the covered area
1168 if (intersectionRow < m_startVisibleRow || intersectionColumn < m_startVisib leColumn
1169 || intersectionRow >= m_endVisibleRow || intersectionColumn >= m_endVisi bleColumn) {
1170 // LOG(ERROR) << "GOT AN NPOS";
1171 return TableCollapsedBorderPainter::npos;
1172 }
1173
1174 unsigned index = (intersectionRow - m_startVisibleRow) * (m_endVisibleColumn - m_startVisibleColumn) * 2;
1175 index += (intersectionColumn - m_startVisibleColumn) * 2;
1176 return direction == East ? index : index + 1; // each vertex holds [East, So uth]
1177 }
1178
1179 unsigned TableCollapsedBorderPainter::intersectionToIndex(unsigned row, unsigned column) const
1180 {
1181 if (row < m_startVisibleRow || column < m_startVisibleColumn
1182 || row >= m_endVisibleRow || column >= m_endVisibleColumn )
1183 return TableCollapsedBorderPainter::npos;
1184 return (row - m_startVisibleRow) * (m_endVisibleColumn - m_startVisibleColum n) + column;
1185 }
1186
1187 } // blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698