void AccessibilityTableCell::rowIndexRange(std::pair<unsigned, unsigned>& rowRange)
{
    if (!m_renderer || !m_renderer->isTableCell())
        return;
    
    RenderTableCell* renderCell = toRenderTableCell(m_renderer);
    rowRange.first = renderCell->rowIndex();
    rowRange.second = renderCell->rowSpan();
    
    // since our table might have multiple sections, we have to offset our row appropriately
    RenderTableSection* section = renderCell->section();
    RenderTable* table = renderCell->table();
    if (!table || !section)
        return;

    RenderTableSection* tableSection = table->topSection();    
    unsigned rowOffset = 0;
    while (tableSection) {
        if (tableSection == section)
            break;
        rowOffset += tableSection->numRows();
        tableSection = table->sectionBelow(tableSection, SkipEmptySections);
    }

    rowRange.first += rowOffset;
}
Esempio n. 2
0
void AccessibilityTableCell::rowIndexRange(pair<int, int>& rowRange)
{
    if (!m_renderer || !m_renderer->isTableCell())
        return;
    
    RenderTableCell* renderCell = toRenderTableCell(m_renderer);
    rowRange.first = renderCell->rowIndex();
    rowRange.second = renderCell->rowSpan();
    
    // since our table might have multiple sections, we have to offset our row appropriately
    RenderTableSection* section = renderCell->section();
    RenderTable* table = renderCell->table();
    if (!table || !section)
        return;

    // FIXME: This will skip a table with just a tfoot. Should fix by using RenderTable::topSection.
    RenderTableSection* tableSection = table->header();
    if (!tableSection)
        tableSection = table->firstBody();
    
    unsigned rowOffset = 0;
    while (tableSection) {
        if (tableSection == section)
            break;
        rowOffset += tableSection->numRows();
        tableSection = table->sectionBelow(tableSection, SkipEmptySections);
    }

    rowRange.first += rowOffset;
}
void AccessibilityTableCell::rowIndexRange(std::pair<unsigned, unsigned>& rowRange)
{
    if (!m_renderer || !m_renderer->isTableCell())
        return;
    
    RenderTableCell* renderCell = toRenderTableCell(m_renderer);
    rowRange.first = renderCell->rowIndex();
    rowRange.second = renderCell->rowSpan();
    
    // since our table might have multiple sections, we have to offset our row appropriately
    RenderTableSection* section = renderCell->section();
    RenderTable* table = renderCell->table();
    if (!table || !section)
        return;

    RenderTableSection* footerSection = table->footer();
    unsigned rowOffset = 0;
    for (RenderTableSection* tableSection = table->topSection(); tableSection; tableSection = table->sectionBelow(tableSection, SkipEmptySections)) {
        // Don't add row offsets for bottom sections that are placed in before the body section.
        if (tableSection == footerSection)
            continue;
        if (tableSection == section)
            break;
        rowOffset += tableSection->numRows();
    }

    rowRange.first += rowOffset;
}
Esempio n. 4
0
void RenderTableCol::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    RenderBox::styleDidChange(diff, oldStyle);

    // If border was changed, notify table.
    if (parent()) {
        RenderTable* table = this->table();
        if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style().border())
            table->invalidateCollapsedBorders();
        else if (oldStyle->width() != style().width()) {
            for (auto& section : childrenOfType<RenderTableSection>(*table)) {
                unsigned nEffCols = table->numEffCols();
                for (unsigned j = 0; j < nEffCols; j++) {
                    unsigned rowCount = section.numRows();
                    for (unsigned i = 0; i < rowCount; i++) {
                        RenderTableCell* cell = section.primaryCellAt(i, j);
                        if (!cell)
                            continue;
                        cell->setPreferredLogicalWidthsDirty(true);
                    }
                }
            }
        }
    }
}
void AccessibilityTableCell::rowIndexRange(pair<int, int>& rowRange)
{
    if (!m_renderer)
        return;
    
    RenderTableCell* renderCell = static_cast<RenderTableCell*>(m_renderer);
    rowRange.first = renderCell->row();
    rowRange.second = renderCell->rowSpan();
    
    // since our table might have multiple sections, we have to offset our row appropriately
    RenderTableSection* section = renderCell->section();
    RenderTable* table = renderCell->table();
    if (!table || !section)
        return;
    
    RenderTableSection* tableSection = table->header();
    if (!tableSection)
        tableSection = table->firstBody();
    
    unsigned rowOffset = 0;
    while (tableSection) {
        if (tableSection == section)
            break;
        rowOffset += tableSection->numRows();
        tableSection = table->sectionBelow(tableSection, true); 
    }

    rowRange.first += rowOffset;
}
Esempio n. 6
0
void TableCellPainter::paintBoxDecorationBackground(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (!paintInfo.shouldPaintWithinRoot(&m_renderTableCell))
        return;

    RenderTable* tableElt = m_renderTableCell.table();
    if (!tableElt->collapseBorders() && m_renderTableCell.style()->emptyCells() == HIDE && !m_renderTableCell.firstChild())
        return;

    LayoutRect paintRect = paintBounds(paintOffset, DoNotAddOffsetFromParent);
    RenderDrawingRecorder recorder(paintInfo.context, m_renderTableCell, paintInfo.phase, pixelSnappedIntRect(paintRect));
    if (recorder.canUseCachedDrawing())
        return;

    BoxPainter::paintBoxShadow(paintInfo, paintRect, m_renderTableCell.style(), Normal);

    // Paint our cell background.
    paintBackgroundsBehindCell(paintInfo, paintOffset, &m_renderTableCell);

    BoxPainter::paintBoxShadow(paintInfo, paintRect, m_renderTableCell.style(), Inset);

    if (!m_renderTableCell.style()->hasBorder() || tableElt->collapseBorders())
        return;

    BoxPainter::paintBorder(m_renderTableCell, paintInfo, paintRect, m_renderTableCell.style());
}
Esempio n. 7
0
void TableCellPainter::paintBackgroundsBehindCell(const PaintInfo& paintInfo, const LayoutPoint& paintOffset, RenderObject* backgroundObject)
{
    if (!paintInfo.shouldPaintWithinRoot(&m_renderTableCell))
        return;

    if (!backgroundObject)
        return;

    if (m_renderTableCell.style()->visibility() != VISIBLE)
        return;

    RenderTable* tableElt = m_renderTableCell.table();
    if (!tableElt->collapseBorders() && m_renderTableCell.style()->emptyCells() == HIDE && !m_renderTableCell.firstChild())
        return;

    Color c = backgroundObject->resolveColor(CSSPropertyBackgroundColor);
    const FillLayer& bgLayer = backgroundObject->style()->backgroundLayers();

    LayoutRect paintRect = paintBounds(paintOffset, backgroundObject != &m_renderTableCell ? AddOffsetFromParent : DoNotAddOffsetFromParent);

    if (bgLayer.hasImage() || c.alpha()) {
        // We have to clip here because the background would paint
        // on top of the borders otherwise.  This only matters for cells and rows.
        bool shouldClip = backgroundObject->hasLayer() && (backgroundObject == &m_renderTableCell || backgroundObject == m_renderTableCell.parent()) && tableElt->collapseBorders();
        GraphicsContextStateSaver stateSaver(*paintInfo.context, shouldClip);
        if (shouldClip) {
            LayoutRect clipRect(paintRect.location(), m_renderTableCell.size());
            clipRect.expand(m_renderTableCell.borderInsets());
            paintInfo.context->clip(clipRect);
        }
        BoxPainter(m_renderTableCell).paintFillLayers(paintInfo, c, bgLayer, paintRect, BackgroundBleedNone, CompositeSourceOver, backgroundObject);
    }
}
void RenderTableCell::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
{
#if PLATFORM(WKC)
    CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT);
#endif
    RenderTable* tableElt = table();
    if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
        return;

    int w = width();
    int h = height();
   
    if (style()->boxShadow())
        paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Normal);
    
    // Paint our cell background.
    paintBackgroundsBehindCell(paintInfo, tx, ty, this);
    if (style()->boxShadow())
        paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Inset);

    if (!style()->hasBorder() || tableElt->collapseBorders())
        return;

    paintBorder(paintInfo.context, tx, ty, w, h, style());
}
Esempio n. 9
0
void RenderTableRow::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    ASSERT(style()->display() == TABLE_ROW);

    RenderBox::styleDidChange(diff, oldStyle);
    propagateStyleToAnonymousChildren();

    if (section() && oldStyle && style()->logicalHeight() != oldStyle->logicalHeight())
        section()->rowLogicalHeightChanged(rowIndex());

    // If border was changed, notify table.
    if (parent()) {
        RenderTable* table = this->table();
        if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border())
            table->invalidateCollapsedBorders();
        
        if (table && oldStyle && diff == StyleDifferenceLayout && needsLayout() && table->collapseBorders() && borderWidthChanged(oldStyle, style())) {
            // If the border width changes on a row, we need to make sure the cells in the row know to lay out again.
            // This only happens when borders are collapsed, since they end up affecting the border sides of the cell
            // itself.
            for (RenderBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) {
                if (!childBox->isTableCell())
                    continue;
                childBox->setChildNeedsLayout(true, MarkOnlyThis);
            }
        }
    }
}
Esempio n. 10
0
IntRect RenderTableRow::getAbsoluteRepaintRect()
{
    // For now, just repaint the whole table.
    // FIXME: Find a better way to do this, e.g., need to repaint all the cells that we
    // might have propagated a background color into.
    RenderTable* parentTable = table();
    if (parentTable)
        return parentTable->getAbsoluteRepaintRect();
    else
        return IntRect();
}
Esempio n. 11
0
void RenderTableCol::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    RenderBox::styleDidChange(diff, oldStyle);

    // If border was changed, notify table.
    if (parent()) {
        RenderTable* table = this->table();
        if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border())
            table->invalidateCollapsedBorders();
    }
}
void RenderTableCell::paintMask(PaintInfo& paintInfo, IntSize paintOffset)
{
    if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
        return;

    RenderTable* tableElt = table();
    if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
        return;
   
    paintMaskImages(paintInfo, IntRect(toPoint(paintOffset), size()));
}
Esempio n. 13
0
void TableCellPainter::paintMask(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (m_renderTableCell.style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
        return;

    RenderTable* tableElt = m_renderTableCell.table();
    if (!tableElt->collapseBorders() && m_renderTableCell.style()->emptyCells() == HIDE && !m_renderTableCell.firstChild())
        return;

    BoxPainter(m_renderTableCell).paintMaskImages(paintInfo, paintBounds(paintOffset, DoNotAddOffsetFromParent));
}
Esempio n. 14
0
LayoutRect RenderTableCol::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
{
    // For now, just repaint the whole table.
    // FIXME: Find a better way to do this, e.g., need to repaint all the cells that we
    // might have propagated a background color or borders into.
    // FIXME: check for repaintContainer each time here?

    RenderTable* parentTable = table();
    if (!parentTable)
        return LayoutRect();
    return parentTable->clippedOverflowRectForRepaint(repaintContainer);
}
Esempio n. 15
0
static bool shouldEmitTabBeforeNode(Node* node)
{
    RenderObject* r = node->renderer();
    
    // Table cells are delimited by tabs.
    if (!r || !isTableCell(node))
        return false;
    
    // Want a tab before every cell other than the first one
    RenderTableCell* rc = static_cast<RenderTableCell*>(r);
    RenderTable* t = rc->table();
    return t && (t->cellBefore(rc) || t->cellAbove(rc));
}
Esempio n. 16
0
void RenderTableCell::readyWRATHWidgetBackgroundsBehindCell(PaintedWidgetsOfWRATHHandle& handle,
                                                            PaintInfoOfWRATH& paintInfo, int tx, int ty,
                                                            RenderObject* backgroundObject)
{
    RenderTableCell_ReadyWRATHWidgetBackgroundsBehindCell *d(RenderTableCell_ReadyWRATHWidgetBackgroundsBehindCell::object(this, handle));
    ContextOfWRATH::AutoPushNode autoPushRoot(paintInfo.wrath_context, d->m_root_node);

    d->m_fill_layers.visible(false);

    if (!paintInfo.shouldPaintWithinRoot(this))
        return;

    if (!backgroundObject)
        return;

    if (style()->visibility() != VISIBLE)
        return;

    RenderTable* tableElt = table();
    if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
        return;

    if (backgroundObject != this) {
        tx += x();
        ty += y();
    }

    int w = width();
    int h = height();

    Color c = backgroundObject->style()->visitedDependentColor(CSSPropertyBackgroundColor);
    const FillLayer* bgLayer = backgroundObject->style()->backgroundLayers();

    if (bgLayer->hasImage() || c.isValid()) {
        // We have to clip here because the background would paint
        // on top of the borders otherwise.  This only matters for cells and rows.
        bool shouldClip = backgroundObject->hasLayer() && (backgroundObject == this || backgroundObject == parent()) && tableElt->collapseBorders();

        ContextOfWRATH::AutoPushNode autoPushClip(paintInfo.wrath_context, d->m_clip_node);
        d->m_clip_node.widget()->node()->clipping_active(false);

        if (shouldClip) {
            IntRect clipRect(tx + borderLeft(), ty + borderTop(),
                w - borderLeft() - borderRight(), h - borderTop() - borderBottom());
            ContextOfWRATH::set_clipping(d->m_clip_node, clipRect);
            d->m_clip_node.widget()->node()->clipping_active(true);
        }
        readyWRATHWidgetFillLayers(d->m_fill_layers, paintInfo, c, bgLayer, tx, ty, w, h, BackgroundBleedNone, CompositeSourceOver, backgroundObject);
        d->m_fill_layers.visible(true);
    }
}
Esempio n. 17
0
void RenderContainer::addChild(RenderObject* newChild, RenderObject* beforeChild)
{
    bool needsTable = false;

    if (newChild->isListItem())
        updateListMarkerNumbers(beforeChild ? beforeChild : m_lastChild);
    else if (newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP)
        needsTable = !isTable();
    else if (newChild->isRenderBlock() && newChild->style()->display() == TABLE_CAPTION)
        needsTable = !isTable();
    else if (newChild->isTableSection())
        needsTable = !isTable();
    else if (newChild->isTableRow())
        needsTable = !isTableSection();
    else if (newChild->isTableCell()) {
        needsTable = !isTableRow();
        // I'm not 100% sure this is the best way to fix this, but without this
        // change we recurse infinitely when trying to render the CSS2 test page:
        // http://www.bath.ac.uk/%7Epy8ieh/internet/eviltests/htmlbodyheadrendering2.html.
        // See Radar 2925291.
        if (needsTable && isTableCell() && !m_firstChild && !newChild->isTableCell())
            needsTable = false;
    }

    if (needsTable) {
        RenderTable* table;
        RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : m_lastChild;
        if (afterChild && afterChild->isAnonymous() && afterChild->isTable())
            table = static_cast<RenderTable*>(afterChild);
        else {
            table = new (renderArena()) RenderTable(document() /* is anonymous */);
            RefPtr<RenderStyle> newStyle = RenderStyle::create();
            newStyle->inheritFrom(style());
            newStyle->setDisplay(TABLE);
            table->setStyle(newStyle.release());
            addChild(table, beforeChild);
        }
        table->addChild(newChild);
    } else {
        // just add it...
        insertChildNode(newChild, beforeChild);
    }

    if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE) {
        RefPtr<StringImpl> textToTransform = static_cast<RenderText*>(newChild)->originalText();
        if (textToTransform)
            static_cast<RenderText*>(newChild)->setText(textToTransform.release(), true);
    }
}
Esempio n. 18
0
void RenderTableRow::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    RenderBox::styleDidChange(diff, oldStyle);
    propagateStyleToAnonymousChildren();

    if (parent())
        updateBeforeAndAfterContent();

    // If border was changed, notify table.
    if (parent()) {
        RenderTable* table = this->table();
        if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border())
            table->invalidateCollapsedBorders();
    }
}
void RenderTableCell::paintMask(PaintInfo& paintInfo, int tx, int ty)
{
#if PLATFORM(WKC)
    CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT);
#endif
    if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
        return;

    RenderTable* tableElt = table();
    if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
        return;

    int w = width();
    int h = height();
   
    paintMaskImages(paintInfo, tx, ty, w, h);
}
Esempio n. 20
0
void AccessibilityTable::addChildren()
{
    if (!isAccessibilityTable()) {
        AccessibilityRenderObject::addChildren();
        return;
    }
    
    ASSERT(!m_haveChildren); 
    
    m_haveChildren = true;
    if (!m_renderer || !m_renderer->isTable())
        return;
    
    RenderTable* table = toRenderTable(m_renderer);
    // Go through all the available sections to pull out the rows and add them as children.
    table->recalcSectionsIfNeeded();
    
    unsigned maxColumnCount = 0;
    RenderTableSection* footer = table->footer();
    
    for (RenderTableSection* tableSection = table->topSection(); tableSection; tableSection = table->sectionBelow(tableSection, SkipEmptySections)) {
        if (tableSection == footer)
            continue;
        addChildrenFromSection(tableSection, maxColumnCount);
    }
    
    // Process the footer last, in case it was ordered earlier in the DOM.
    if (footer)
        addChildrenFromSection(footer, maxColumnCount);
    
    AXObjectCache* axCache = m_renderer->document().axObjectCache();
    // make the columns based on the number of columns in the first body
    unsigned length = maxColumnCount;
    for (unsigned i = 0; i < length; ++i) {
        AccessibilityTableColumn* column = toAccessibilityTableColumn(axCache->getOrCreate(ColumnRole));
        column->setColumnIndex((int)i);
        column->setParent(this);
        m_columns.append(column);
        if (!column->accessibilityIsIgnored())
            m_children.append(column);
    }
    
    AccessibilityObject* headerContainerObject = headerContainer();
    if (headerContainerObject && !headerContainerObject->accessibilityIsIgnored())
        m_children.append(headerContainerObject);
}
Esempio n. 21
0
void RenderTableRow::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    ASSERT(style()->display() == TABLE_ROW);

    RenderBox::styleDidChange(diff, oldStyle);
    propagateStyleToAnonymousChildren();

    if (section() && oldStyle && style()->logicalHeight() != oldStyle->logicalHeight())
        section()->rowLogicalHeightChanged(rowIndex());

    // If border was changed, notify table.
    if (parent()) {
        RenderTable* table = this->table();
        if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border())
            table->invalidateCollapsedBorders();
    }
}
Esempio n. 22
0
void Control::parsePanoramaControl(ZVision *engine, Common::SeekableReadStream &stream) {
	RenderTable *renderTable = engine->getRenderManager()->getRenderTable();
	renderTable->setRenderState(RenderTable::PANORAMA);

	// Loop until we find the closing brace
	Common::String line = stream.readLine();
	trimCommentsAndWhiteSpace(&line);

	while (!stream.eos() && !line.contains('}')) {
		if (line.matchString("angle*", true)) {
			float fov;
			sscanf(line.c_str(), "angle(%f)", &fov);
			renderTable->setPanoramaFoV(fov);
		} else if (line.matchString("linscale*", true)) {
			float scale;
			sscanf(line.c_str(), "linscale(%f)", &scale);
			renderTable->setPanoramaScale(scale);
		} else if (line.matchString("reversepana*", true)) {
			uint reverse;
			sscanf(line.c_str(), "reversepana(%u)", &reverse);
			if (reverse == 1) {
				renderTable->setPanoramaReverse(true);
			}
		} else if (line.matchString("zeropoint*", true)) {
			uint point;
			sscanf(line.c_str(), "zeropoint(%u)", &point);
			renderTable->setPanoramaZeroPoint(point);
		}

		line = stream.readLine();
		trimCommentsAndWhiteSpace(&line);
	}

	renderTable->generateRenderTable();
}
AccessibilityObject* AccessibilityTableColumn::headerObject()
{
    if (!m_parent)
        return 0;
    
    RenderObject* renderer = m_parent->renderer();
    if (!renderer)
        return 0;
    
    if (!m_parent->isAccessibilityTable())
        return 0;
    
    AccessibilityTable* parentTable = toAccessibilityTable(m_parent);
    if (parentTable->isAriaTable()) {
        AccessibilityChildrenVector rowChildren = children();
        unsigned childrenCount = rowChildren.size();
        for (unsigned i = 0; i < childrenCount; ++i) {
            AccessibilityObject* cell = rowChildren[i].get();
            if (cell->ariaRoleAttribute() == ColumnHeaderRole)
                return cell;
        }
        
        return 0;
    }

    if (!renderer->isTable())
        return 0;
    
    RenderTable* table = toRenderTable(renderer);
    
    AccessibilityObject* headerObject = 0;
    
    // try the <thead> section first. this doesn't require th tags
    headerObject = headerObjectForSection(table->header(), false);

    if (headerObject)
        return headerObject;
    
    // now try for <th> tags in the first body
    headerObject = headerObjectForSection(table->firstBody(), true);

    return headerObject;
}
Esempio n. 24
0
static bool shouldEmitNewlinesBeforeAndAfterNode(Node* node)
{
    // Block flow (versus inline flow) is represented by having
    // a newline both before and after the element.
    RenderObject* r = node->renderer();
    if (!r) {
        return (node->hasTagName(blockquoteTag)
                || node->hasTagName(ddTag)
                || node->hasTagName(divTag)
                || node->hasTagName(dlTag)
                || node->hasTagName(dtTag)
                || node->hasTagName(h1Tag)
                || node->hasTagName(h2Tag)
                || node->hasTagName(h3Tag)
                || node->hasTagName(h4Tag)
                || node->hasTagName(h5Tag)
                || node->hasTagName(h6Tag)
                || node->hasTagName(hrTag)
                || node->hasTagName(liTag)
                || node->hasTagName(listingTag)
                || node->hasTagName(olTag)
                || node->hasTagName(pTag)
                || node->hasTagName(preTag)
                || node->hasTagName(trTag)
                || node->hasTagName(ulTag));
    }
    
    // Need to make an exception for table cells, because they are blocks, but we
    // want them tab-delimited rather than having newlines before and after.
    if (isTableCell(node))
        return false;
    
    // Need to make an exception for table row elements, because they are neither
    // "inline" or "RenderBlock", but we want newlines for them.
    if (r->isTableRow()) {
        RenderTable* t = static_cast<RenderTableRow*>(r)->table();
        if (t && !t->isInline())
            return true;
    }
    
    return !r->isInline() && r->isRenderBlock() && !r->isFloatingOrPositioned() && !r->isBody();
}
void RenderTableCell::paintBackgroundsBehindCell(PaintInfo& paintInfo, int tx, int ty, RenderObject* backgroundObject)
{
#if PLATFORM(WKC)
    CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT);
#endif
    if (!backgroundObject)
        return;

    if (style()->visibility() != VISIBLE)
        return;

    RenderTable* tableElt = table();
    if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
        return;

    if (backgroundObject != this) {
        tx += x();
        ty += y();
    }

    int w = width();
    int h = height();

    Color c = backgroundObject->style()->backgroundColor();
    const FillLayer* bgLayer = backgroundObject->style()->backgroundLayers();

    if (bgLayer->hasImage() || c.isValid()) {
        // We have to clip here because the background would paint
        // on top of the borders otherwise.  This only matters for cells and rows.
        bool shouldClip = backgroundObject->hasLayer() && (backgroundObject == this || backgroundObject == parent()) && tableElt->collapseBorders();
        if (shouldClip) {
            IntRect clipRect(tx + borderLeft(), ty + borderTop(),
                w - borderLeft() - borderRight(), h - borderTop() - borderBottom());
            paintInfo.context->save();
            paintInfo.context->clip(clipRect);
        }
        paintFillLayers(paintInfo, c, bgLayer, tx, ty, w, h);
        if (shouldClip)
            paintInfo.context->restore();
    }
}
Esempio n. 26
0
HTMLTableElement* AccessibilityTable::tableElement() const
{
    if (!m_renderer->isTable())
        return nullptr;
    
    RenderTable* table = toRenderTable(m_renderer);
    if (table->element() && isHTMLTableElement(table->element()))
        return toHTMLTableElement(table->element());
    
    // If the table has a display:table-row-group, then the RenderTable does not have a pointer to it's HTMLTableElement.
    // We can instead find it by asking the firstSection for its parent.
    RenderTableSection* firstBody = table->firstBody();
    if (!firstBody || !firstBody->element())
        return nullptr;
    
    Element* actualTable = firstBody->element()->parentElement();
    if (!actualTable || !isHTMLTableElement(actualTable))
        return nullptr;
    
    return toHTMLTableElement(actualTable);
}
void RenderTableCell::paintBackgroundsBehindCell(PaintInfo& paintInfo, int tx, int ty, RenderObject* backgroundObject)
{
    if (!paintInfo.shouldPaintWithinRoot(this))
        return;

    if (!backgroundObject)
        return;

    if (style()->visibility() != VISIBLE)
        return;

    RenderTable* tableElt = table();
    if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
        return;

    if (backgroundObject != this) {
        tx += x();
        ty += y();
    }

    int w = width();
    int h = height();

    Color c = backgroundObject->style()->visitedDependentColor(CSSPropertyBackgroundColor);
    const FillLayer* bgLayer = backgroundObject->style()->backgroundLayers();

    if (bgLayer->hasImage() || c.isValid()) {
        // We have to clip here because the background would paint
        // on top of the borders otherwise.  This only matters for cells and rows.
        bool shouldClip = backgroundObject->hasLayer() && (backgroundObject == this || backgroundObject == parent()) && tableElt->collapseBorders();
        GraphicsContextStateSaver stateSaver(*paintInfo.context, shouldClip);
        if (shouldClip) {
            IntRect clipRect(tx + borderLeft(), ty + borderTop(),
                w - borderLeft() - borderRight(), h - borderTop() - borderBottom());
            paintInfo.context->clip(clipRect);
        }
        paintFillLayers(paintInfo, c, bgLayer, IntRect(tx, ty, w, h), BackgroundBleedNone, CompositeSourceOver, backgroundObject);
    }
}
void RenderTableCell::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
{
    if (!paintInfo.shouldPaintWithinRoot(this))
        return;

    RenderTable* tableElt = table();
    if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
        return;

    IntRect paintRect = IntRect(IntPoint(tx, ty), size());
    paintBoxShadow(paintInfo, paintRect, style(), Normal);
    
    // Paint our cell background.
    paintBackgroundsBehindCell(paintInfo, tx, ty, this);

    paintBoxShadow(paintInfo, paintRect, style(), Inset);

    if (!style()->hasBorder() || tableElt->collapseBorders())
        return;

    paintBorder(paintInfo, paintRect, style());
}
Esempio n. 29
0
void RenderTableCell::readyWRATHWidgetBoxDecorations(PaintedWidgetsOfWRATHHandle& handle,
                                                     PaintInfoOfWRATH& paintInfo, int tx, int ty)
{
    RenderTableCell_ReadyWRATHWidgetBoxDecorations *d(RenderTableCell_ReadyWRATHWidgetBoxDecorations::object(this, handle));
    ContextOfWRATH::AutoPushNode autoPushRoot(paintInfo.wrath_context, d->m_root_node);

    d->m_box_shadow.visible(false);
    d->m_backgrounds.visible(false);
    d->m_latter_box_shadow.visible(false);
    d->m_border.visible(false);

    if (!paintInfo.shouldPaintWithinRoot(this))
        return;

    RenderTable* tableElt = table();
    if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
        return;

    int w = width();
    int h = height();
   
    readyWRATHWidgetBoxShadow(d->m_box_shadow, paintInfo.wrath_context, tx, ty, w, h, style(), Normal);
    d->m_box_shadow.visible(true);
    
    // Paint our cell background.
    readyWRATHWidgetBackgroundsBehindCell(d->m_backgrounds, paintInfo, tx, ty, this);
    d->m_backgrounds.visible(true);

    readyWRATHWidgetBoxShadow(d->m_latter_box_shadow, paintInfo.wrath_context, tx, ty, w, h, style(), Inset);
    d->m_latter_box_shadow.visible(true);

    if (!style()->hasBorder() || tableElt->collapseBorders())
        return;

    readyWRATHWidgetBorder(d->m_border, paintInfo.wrath_context, tx, ty, w, h, style());
    d->m_border.visible(true);
}
Esempio n. 30
0
bool AccessibilityTable::isDataTable() const
{
    if (!m_renderer)
        return false;

    // Do not consider it a data table is it has an ARIA role.
    if (hasARIARole())
        return false;

    // When a section of the document is contentEditable, all tables should be
    // treated as data tables, otherwise users may not be able to work with rich
    // text editors that allow creating and editing tables.
    if (node() && node()->hasEditableStyle())
        return true;

    // This employs a heuristic to determine if this table should appear.
    // Only "data" tables should be exposed as tables.
    // Unfortunately, there is no good way to determine the difference
    // between a "layout" table and a "data" table.
    
    RenderTable* table = toRenderTable(m_renderer);
    if (!table->element() || !isHTMLTableElement(table->element()))
        return false;

    // if there is a caption element, summary, THEAD, or TFOOT section, it's most certainly a data table
    HTMLTableElement* tableElement = toHTMLTableElement(table->element());
    if (!tableElement->summary().isEmpty() || tableElement->tHead() || tableElement->tFoot() || tableElement->caption())
        return true;
    
    // if someone used "rules" attribute than the table should appear
    if (!tableElement->rules().isEmpty())
        return true;    

    // if there's a colgroup or col element, it's probably a data table.
    for (const auto& child : childrenOfType<Element>(*tableElement)) {
        if (child.hasTagName(colTag) || child.hasTagName(colgroupTag))
            return true;
    }
    
    // go through the cell's and check for tell-tale signs of "data" table status
    // cells have borders, or use attributes like headers, abbr, scope or axis
    table->recalcSectionsIfNeeded();
    RenderTableSection* firstBody = table->firstBody();
    if (!firstBody)
        return false;
    
    int numCols = firstBody->numColumns();
    int numRows = firstBody->numRows();
    
    // If there's only one cell, it's not a good AXTable candidate.
    if (numRows == 1 && numCols == 1)
        return false;

    // If there are at least 20 rows, we'll call it a data table.
    if (numRows >= 20)
        return true;
    
    // Store the background color of the table to check against cell's background colors.
    const RenderStyle& tableStyle = table->style();
    Color tableBGColor = tableStyle.visitedDependentColor(CSSPropertyBackgroundColor);
    
    // check enough of the cells to find if the table matches our criteria
    // Criteria: 
    //   1) must have at least one valid cell (and)
    //   2) at least half of cells have borders (or)
    //   3) at least half of cells have different bg colors than the table, and there is cell spacing
    unsigned validCellCount = 0;
    unsigned borderedCellCount = 0;
    unsigned backgroundDifferenceCellCount = 0;
    unsigned cellsWithTopBorder = 0;
    unsigned cellsWithBottomBorder = 0;
    unsigned cellsWithLeftBorder = 0;
    unsigned cellsWithRightBorder = 0;
    
    Color alternatingRowColors[5];
    int alternatingRowColorCount = 0;
    
    int headersInFirstColumnCount = 0;
    for (int row = 0; row < numRows; ++row) {
    
        int headersInFirstRowCount = 0;
        for (int col = 0; col < numCols; ++col) {    
            RenderTableCell* cell = firstBody->primaryCellAt(row, col);
            if (!cell)
                continue;

            Element* cellElement = cell->element();
            if (!cellElement)
                continue;
            
            if (cell->width() < 1 || cell->height() < 1)
                continue;
            
            validCellCount++;
            
            bool isTHCell = cellElement->hasTagName(thTag);
            // If the first row is comprised of all <th> tags, assume it is a data table.
            if (!row && isTHCell)
                headersInFirstRowCount++;

            // If the first column is comprised of all <th> tags, assume it is a data table.
            if (!col && isTHCell)
                headersInFirstColumnCount++;
            
            // In this case, the developer explicitly assigned a "data" table attribute.
            if (cellElement->hasTagName(tdTag) || cellElement->hasTagName(thTag)) {
                HTMLTableCellElement* tableCellElement = toHTMLTableCellElement(cellElement);
                if (!tableCellElement->headers().isEmpty() || !tableCellElement->abbr().isEmpty()
                    || !tableCellElement->axis().isEmpty() || !tableCellElement->scope().isEmpty())
                    return true;
            }
            const RenderStyle& renderStyle = cell->style();

            // If the empty-cells style is set, we'll call it a data table.
            if (renderStyle.emptyCells() == HIDE)
                return true;

            // If a cell has matching bordered sides, call it a (fully) bordered cell.
            if ((cell->borderTop() > 0 && cell->borderBottom() > 0)
                || (cell->borderLeft() > 0 && cell->borderRight() > 0))
                borderedCellCount++;

            // Also keep track of each individual border, so we can catch tables where most
            // cells have a bottom border, for example.
            if (cell->borderTop() > 0)
                cellsWithTopBorder++;
            if (cell->borderBottom() > 0)
                cellsWithBottomBorder++;
            if (cell->borderLeft() > 0)
                cellsWithLeftBorder++;
            if (cell->borderRight() > 0)
                cellsWithRightBorder++;
            
            // If the cell has a different color from the table and there is cell spacing,
            // then it is probably a data table cell (spacing and colors take the place of borders).
            Color cellColor = renderStyle.visitedDependentColor(CSSPropertyBackgroundColor);
            if (table->hBorderSpacing() > 0 && table->vBorderSpacing() > 0
                && tableBGColor != cellColor && cellColor.alpha() != 1)
                backgroundDifferenceCellCount++;
            
            // If we've found 10 "good" cells, we don't need to keep searching.
            if (borderedCellCount >= 10 || backgroundDifferenceCellCount >= 10)
                return true;
            
            // For the first 5 rows, cache the background color so we can check if this table has zebra-striped rows.
            if (row < 5 && row == alternatingRowColorCount) {
                RenderObject* renderRow = cell->parent();
                if (!renderRow || !renderRow->isBoxModelObject() || !toRenderBoxModelObject(renderRow)->isTableRow())
                    continue;
                const RenderStyle& rowRenderStyle = renderRow->style();
                Color rowColor = rowRenderStyle.visitedDependentColor(CSSPropertyBackgroundColor);
                alternatingRowColors[alternatingRowColorCount] = rowColor;
                alternatingRowColorCount++;
            }
        }
        
        if (!row && headersInFirstRowCount == numCols && numCols > 1)
            return true;
    }

    if (headersInFirstColumnCount == numRows && numRows > 1)
        return true;
    
    // if there is less than two valid cells, it's not a data table
    if (validCellCount <= 1)
        return false;
    
    // half of the cells had borders, it's a data table
    unsigned neededCellCount = validCellCount / 2;
    if (borderedCellCount >= neededCellCount
        || cellsWithTopBorder >= neededCellCount
        || cellsWithBottomBorder >= neededCellCount
        || cellsWithLeftBorder >= neededCellCount
        || cellsWithRightBorder >= neededCellCount)
        return true;
    
    // half had different background colors, it's a data table
    if (backgroundDifferenceCellCount >= neededCellCount)
        return true;

    // Check if there is an alternating row background color indicating a zebra striped style pattern.
    if (alternatingRowColorCount > 2) {
        Color firstColor = alternatingRowColors[0];
        for (int k = 1; k < alternatingRowColorCount; k++) {
            // If an odd row was the same color as the first row, its not alternating.
            if (k % 2 == 1 && alternatingRowColors[k] == firstColor)
                return false;
            // If an even row is not the same as the first row, its not alternating.
            if (!(k % 2) && alternatingRowColors[k] != firstColor)
                return false;
        }
        return true;
    }
    
    return false;
}