static void fillSmoothEdgedRect(GraphicsContext* context, const IntRect& rect, const Color& color) { Color halfColor(color.red(), color.green(), color.blue(), color.alpha() / 2); IntRect topRect = rect; topRect.inflateX(-1); topRect.setHeight(1); context->fillRect(topRect, halfColor, ColorSpaceDeviceRGB); IntRect leftRect = rect; leftRect.inflateY(-1); leftRect.setWidth(1); context->fillRect(leftRect, halfColor, ColorSpaceDeviceRGB); IntRect centerRect = rect; centerRect.inflate(-1); context->fillRect(centerRect, color, ColorSpaceDeviceRGB); IntRect rightRect = rect; rightRect.inflateY(-1); rightRect.setX(centerRect.maxX()); rightRect.setWidth(1); context->fillRect(rightRect, halfColor, ColorSpaceDeviceRGB); IntRect bottomRect = rect; bottomRect.inflateX(-1); bottomRect.setY(centerRect.maxY()); bottomRect.setHeight(1); context->fillRect(bottomRect, halfColor, ColorSpaceDeviceRGB); }
IntRect Surface::computePrepareArea() { IntRect area; if (!getFirstLayer()->contentIsScrollable() && !isBase() && getFirstLayer()->state()->layersRenderingMode() == GLWebViewState::kAllTextures) { area = fullContentArea(); double total = ((double) area.width()) * ((double) area.height()); if (total > MAX_FULL_CONTENT_AREA) area = visibleContentArea(); /// M: Willy, limit the max number of tile is 64. @{ else { float scale = getFirstLayer()->state()->scale(); int x = ((double)area.width() * scale) / TilesManager::tileWidth(); int y = ((double)area.height() * scale) / TilesManager::tileHeight(); if ((x * y) > 64) { IntRect a = visibleContentArea(); IntRect tmpArea = a; tmpArea.inflateX(TilesManager::tileWidth() << 1); tmpArea.inflateY(TilesManager::tileHeight() << 1); tmpArea.intersect(area); area = tmpArea; } } /// @} } else area = visibleContentArea(); return area; }
void TiledBackingStore::adjustForContentsRect(IntRect& rect) const { IntRect bounds = contentsRect(); IntSize candidateSize = rect.size(); // We will try to keep the cover and keep rect the same size at all time, which // might not be the case when at the content edges. // We start by moving when at the edges. rect.move(std::max(0, bounds.x() - rect.x()), std::max(0, bounds.y() - rect.y())); rect.move(std::min(0, bounds.maxX() - rect.maxX()), std::min(0, bounds.maxY() - rect.maxY())); rect.intersect(bounds); if (rect.size() == candidateSize) return; // Even now we might cover more than the content area so let's inflate in the // opposite directions. int pixelsCovered = candidateSize.width() * candidateSize.height(); if (rect.width() != candidateSize.width()) rect.inflateY(((pixelsCovered / rect.width()) - rect.height()) / 2); if (rect.height() != candidateSize.height()) rect.inflateX(((pixelsCovered / rect.height()) - rect.width()) / 2); rect.intersect(bounds); }
IntRect TiledDrawingAreaProxy::calculateCoverRect(const IntRect& visibleRect) const { IntRect result = visibleRect; result.inflateX(visibleRect.width() * (m_coverAreaMultiplier.width() - 1)); result.inflateY(visibleRect.height() * (m_coverAreaMultiplier.height() - 1)); result.intersect(contentsRect()); return result; }
void TiledBackingStore::computeCoverAndKeepRect(const IntRect& visibleRect, IntRect& coverRect, IntRect& keepRect) const { coverRect = visibleRect; keepRect = visibleRect; // If we cover more that the actual viewport we can be smart about which tiles we choose to render. if (m_coverAreaMultiplier > 1) { // The initial cover area covers equally in each direction, according to the coverAreaMultiplier. coverRect.inflateX(visibleRect.width() * (m_coverAreaMultiplier - 1) / 2); coverRect.inflateY(visibleRect.height() * (m_coverAreaMultiplier - 1) / 2); keepRect = coverRect; if (m_trajectoryVector != FloatPoint::zero()) { // A null trajectory vector (no motion) means that tiles for the coverArea will be created. // A non-null trajectory vector will shrink the covered rect to visibleRect plus its expansion from its // center toward the cover area edges in the direction of the given vector. // E.g. if visibleRect == (10,10)5x5 and coverAreaMultiplier == 3.0: // a (0,0) trajectory vector will create tiles intersecting (5,5)15x15, // a (1,0) trajectory vector will create tiles intersecting (10,10)10x5, // and a (1,1) trajectory vector will create tiles intersecting (10,10)10x10. // Multiply the vector by the distance to the edge of the cover area. float trajectoryVectorMultiplier = (m_coverAreaMultiplier - 1) / 2; // Unite the visible rect with a "ghost" of the visible rect moved in the direction of the trajectory vector. coverRect = visibleRect; coverRect.move(coverRect.width() * m_trajectoryVector.x() * trajectoryVectorMultiplier, coverRect.height() * m_trajectoryVector.y() * trajectoryVectorMultiplier); coverRect.unite(visibleRect); } ASSERT(keepRect.contains(coverRect)); } adjustForContentsRect(coverRect); // The keep rect is an inflated version of the cover rect, inflated in tile dimensions. keepRect.unite(coverRect); keepRect.inflateX(m_tileSize.width() / 2); keepRect.inflateY(m_tileSize.height() / 2); keepRect.intersect(m_rect); ASSERT(coverRect.isEmpty() || keepRect.contains(coverRect)); }
IntRect Scrollbar::trackRect() { IntRect rect = frameRect(); if (orientation() == HorizontalScrollbar) rect.inflateX(-kScrollbarMargin); else rect.inflateY(-kScrollbarMargin); return rect; }
IntRect ScrollbarThemeOverlay::trackRect(const ScrollbarThemeClient& scrollbar, bool) { IntRect rect = scrollbar.frameRect(); if (scrollbar.orientation() == HorizontalScrollbar) rect.inflateX(-m_scrollbarMargin); else rect.inflateY(-m_scrollbarMargin); return rect; }
IntRect ScrollbarThemeChromiumAndroid::trackRect(ScrollbarThemeClient* scrollbar, bool) { IntRect rect = scrollbar->frameRect(); if (scrollbar->orientation() == HorizontalScrollbar) rect.inflateX(-scrollbarMargin); else rect.inflateY(-scrollbarMargin); return rect; }
IntRect TiledBackingStore::computeKeepRect(const IntRect& visibleRect) const { IntRect result = visibleRect; // Inflates to both sides, so divide the inflate delta by 2. result.inflateX(visibleRect.width() * (m_keepAreaMultiplier - 1) / 2); result.inflateY(visibleRect.height() * (m_keepAreaMultiplier - 1) / 2); result.intersect(contentsRect()); return result; }
IntRect TiledLayerChromium::idlePaintRect(const IntRect& visibleLayerRect) { IntRect prepaintRect = visibleLayerRect; // FIXME: This can be made a lot larger if we can: // - reserve memory at a lower priority than for visible content // - only reserve idle paint tiles up to a memory reclaim threshold and // - insure we play nicely with other layers prepaintRect.inflateX(m_tiler->tileSize().width()); prepaintRect.inflateY(m_tiler->tileSize().height()); prepaintRect.intersect(IntRect(IntPoint::zero(), contentBounds())); return prepaintRect; }
bool RenderThemeQStyle::paintInnerSpinButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect) { StylePainterQStyle p(this, paintInfo); if (!p.isValid()) return true; QStyleOptionSpinBox option; initStyleOption(p.widget, option); option.subControls = QStyle::SC_SpinBoxUp | QStyle::SC_SpinBoxDown; if (!isReadOnlyControl(o)) { if (isEnabled(o)) option.stepEnabled = QAbstractSpinBox::StepUpEnabled | QAbstractSpinBox::StepDownEnabled; if (isPressed(o)) { option.state |= QStyle::State_Sunken; if (isSpinUpButtonPartPressed(o)) option.activeSubControls = QStyle::SC_SpinBoxUp; else option.activeSubControls = QStyle::SC_SpinBoxDown; } } // Render the spin buttons for LTR or RTL accordingly. option.direction = o->style()->isLeftToRightDirection() ? Qt::LeftToRight : Qt::RightToLeft; IntRect buttonRect = rect; // Default to moving the buttons a little bit within the editor frame. int inflateX = -2; int inflateY = -2; #if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) // QMacStyle will position the aqua buttons flush to the right. // This will move them more within the control for better style, a la // Chromium look & feel. if (qobject_cast<QMacStyle*>(p.style)) { inflateX = -4; // Render mini aqua spin buttons for QMacStyle to fit nicely into // the editor area, like Chromium. option.state |= QStyle::State_Mini; } #endif #if !defined(QT_NO_STYLE_PLASTIQUE) // QPlastiqueStyle looks best when the spin buttons are flush with the frame's edge. if (qobject_cast<QPlastiqueStyle*>(p.style)) { inflateX = 0; inflateY = 0; } #endif buttonRect.inflateX(inflateX); buttonRect.inflateY(inflateY); option.rect = buttonRect; p.drawComplexControl(QStyle::CC_SpinBox, option); return false; }
bool ScrollbarThemeWin::shouldSnapBackToDragOrigin(Scrollbar* scrollbar, const PlatformMouseEvent& evt) { // Find the rect within which we shouldn't snap, by expanding the track rect // in both dimensions. IntRect rect = trackRect(scrollbar); const bool horz = scrollbar->orientation() == HorizontalScrollbar; const int thickness = scrollbarThickness(scrollbar->controlSize()); rect.inflateX((horz ? kOffEndMultiplier : kOffSideMultiplier) * thickness); rect.inflateY((horz ? kOffSideMultiplier : kOffEndMultiplier) * thickness); // Convert the event to local coordinates. IntPoint mousePosition = scrollbar->convertFromContainingWindow(evt.pos()); mousePosition.move(scrollbar->x(), scrollbar->y()); // We should snap iff the event is outside our calculated rect. return !rect.contains(mousePosition); }
// A null trajectory vector means that tiles intersecting all the coverArea (i.e. visibleRect * coverMultiplier) will be created. // A non-null trajectory vector will shrink the intersection rect to visibleRect plus its expansion from its // center toward the cover area edges in the direction of the given vector. // E.g. if visibleRect == (10,10)5x5 and coverMultiplier == 3.0: // a (0,0) trajectory vector will create tiles intersecting (5,5)15x15, // a (1,0) trajectory vector will create tiles intersecting (10,10)10x5, // and a (1,1) trajectory vector will create tiles intersecting (10,10)10x10. IntRect TiledBackingStore::computeCoverRect(const IntRect& visibleRect) const { IntRect result = visibleRect; float trajectoryVectorNorm = sqrt(pow(m_visibleRectTrajectoryVector.x(), 2) + pow(m_visibleRectTrajectoryVector.y(), 2)); if (trajectoryVectorNorm > 0) { // Multiply the vector by the distance to the edge of the cover area. float trajectoryVectorMultiplier = (m_coverAreaMultiplier - 1) / 2; // Unite the visible rect with a "ghost" of the visible rect moved in the direction of the trajectory vector. result.move(result.width() * m_visibleRectTrajectoryVector.x() / trajectoryVectorNorm * trajectoryVectorMultiplier, result.height() * m_visibleRectTrajectoryVector.y() / trajectoryVectorNorm * trajectoryVectorMultiplier); result.unite(visibleRect); } else { result.inflateX(visibleRect.width() * (m_coverAreaMultiplier - 1) / 2); result.inflateY(visibleRect.height() * (m_coverAreaMultiplier - 1) / 2); } result.intersect(contentsRect()); return result; }
void RenderThemeGtk::adjustRepaintRect(const RenderObject* renderObject, IntRect& rect) { ControlPart part = renderObject->style().appearance(); switch (part) { case CheckboxPart: case RadioPart: { // We ignore the interior focus property and always expand the focus rect. In GTK+, the // focus indicator is usually on the text next to a checkbox or radio button, but that doesn't // happen in WebCore. By expanding the focus rectangle unconditionally we increase its prominence. adjustRectForFocus(part == CheckboxPart ? gtkCheckButton() : gtkRadioButton(), rect, true); return; } case InnerSpinButtonPart: // See paintInnerSpinButton for an explanation of why we expand the painting rect. rect.inflateY(2); rect.setWidth(rect.width() + 2); default: return; } }
void TiledBackingStore::adjustForContentsRect(IntRect& rect) const { IntRect bounds = m_rect; IntSize candidateSize = rect.size(); rect.intersect(bounds); if (rect.size() == candidateSize) return; /* * In the following case, there is no intersection of the contents rect and the cover rect. * Thus the latter should not be inflated. * * +---------------+ * | m_rect | * +---------------+ * * +-------------------------------+ * | cover rect | * | +---------+ | * | | visible | | * | | rect | | * | +---------+ | * +-------------------------------+ */ if (rect.isEmpty()) return; // Try to create a cover rect of the same size as the candidate, but within content bounds. int pixelsCovered = candidateSize.width() * candidateSize.height(); if (rect.width() < candidateSize.width()) rect.inflateY(((pixelsCovered / rect.width()) - rect.height()) / 2); if (rect.height() < candidateSize.height()) rect.inflateX(((pixelsCovered / rect.height()) - rect.width()) / 2); rect.intersect(bounds); }
void TiledBackingStore::createTiles() { if (m_contentsFrozen) return; IntRect visibleRect = mapFromContents(m_client->tiledBackingStoreVisibleRect()); m_previousVisibleRect = visibleRect; if (visibleRect.isEmpty()) return; // Remove tiles that extend outside the current contents rect. dropOverhangingTiles(); IntRect keepRect = visibleRect; // Inflates to both sides, so divide inflate delta by 2 keepRect.inflateX(visibleRect.width() * (m_keepAreaMultiplier.width() - 1.f) / 2); keepRect.inflateY(visibleRect.height() * (m_keepAreaMultiplier.height() - 1.f) / 2); keepRect.intersect(contentsRect()); dropTilesOutsideRect(keepRect); IntRect coverRect = visibleRect; // Inflates to both sides, so divide inflate delta by 2 coverRect.inflateX(visibleRect.width() * (m_coverAreaMultiplier.width() - 1.f) / 2); coverRect.inflateY(visibleRect.height() * (m_coverAreaMultiplier.height() - 1.f) / 2); coverRect.intersect(contentsRect()); // Search for the tile position closest to the viewport center that does not yet contain a tile. // Which position is considered the closest depends on the tileDistance function. double shortestDistance = std::numeric_limits<double>::infinity(); Vector<Tile::Coordinate> tilesToCreate; unsigned requiredTileCount = 0; Tile::Coordinate topLeft = tileCoordinateForPoint(coverRect.location()); Tile::Coordinate bottomRight = tileCoordinateForPoint(IntPoint(coverRect.maxX(), coverRect.maxY())); for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) { for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) { Tile::Coordinate currentCoordinate(xCoordinate, yCoordinate); if (tileAt(currentCoordinate)) continue; ++requiredTileCount; // Distance is 0 for all currently visible tiles. double distance = tileDistance(visibleRect, currentCoordinate); if (distance > shortestDistance) continue; if (distance < shortestDistance) { tilesToCreate.clear(); shortestDistance = distance; } tilesToCreate.append(currentCoordinate); } } // Now construct the tile(s) unsigned tilesToCreateCount = tilesToCreate.size(); for (unsigned n = 0; n < tilesToCreateCount; ++n) { Tile::Coordinate coordinate = tilesToCreate[n]; setTile(coordinate, Tile::create(this, coordinate)); } requiredTileCount -= tilesToCreateCount; // Paint the content of the newly created tiles if (tilesToCreateCount) updateTileBuffers(); // Keep creating tiles until the whole coverRect is covered. if (requiredTileCount) m_tileCreationTimer->startOneShot(m_tileCreationDelay); }
void TileGrid::prepareGL(GLWebViewState* state, float scale, const IntRect& prepareArea, const IntRect& fullContentArea, TilePainter* painter, int regionFlags, bool isLowResPrefetch, bool updateWithBlit) { // first, how many tiles do we need m_area = computeTilesArea(prepareArea, scale); if (m_area.isEmpty()) return; ALOGV("prepare TileGrid %p with scale %.2f, prepareArea " " %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles", this, scale, prepareArea.x(), prepareArea.y(), prepareArea.width(), prepareArea.height(), m_area.x(), m_area.y(), m_area.width(), m_area.height()); bool goingDown = m_prevTileY < m_area.y(); m_prevTileY = m_area.y(); TilesManager* tilesManager = TilesManager::instance(); if (scale != m_scale) tilesManager->removeOperationsForFilter(new ScaleFilter(painter, m_scale)); m_scale = scale; // apply dirty region to affected tiles if (!m_dirtyRegion.isEmpty()) { for (unsigned int i = 0; i < m_tiles.size(); i++) m_tiles[i]->markAsDirty(m_dirtyRegion); // log inval region for the base surface if (m_isBaseSurface && tilesManager->getProfiler()->enabled()) { SkRegion::Iterator iterator(m_dirtyRegion); while (!iterator.done()) { SkIRect r = iterator.rect(); tilesManager->getProfiler()->nextInval(r, scale); iterator.next(); } } m_dirtyRegion.setEmpty(); } if (regionFlags & StandardRegion) { for (int i = 0; i < m_area.width(); i++) { if (goingDown) { for (int j = 0; j < m_area.height(); j++) prepareTile(m_area.x() + i, m_area.y() + j, painter, state, isLowResPrefetch, false, updateWithBlit); } else { for (int j = m_area.height() - 1; j >= 0; j--) prepareTile(m_area.x() + i, m_area.y() + j, painter, state, isLowResPrefetch, false, updateWithBlit); } } } if (regionFlags & ExpandedRegion) { IntRect fullArea = computeTilesArea(fullContentArea, scale); IntRect expandedArea = m_area; // on systems reporting highEndGfx=true and useMinimalMemory not set, use expanded bounds if (tilesManager->highEndGfx() && !tilesManager->useMinimalMemory()) expandedArea.inflate(EXPANDED_BOUNDS_INFLATE); if (isLowResPrefetch) expandedArea.inflateY(EXPANDED_PREFETCH_BOUNDS_Y_INFLATE); // clip painting area to content expandedArea.intersect(fullArea); for (int i = expandedArea.x(); i < expandedArea.maxX(); i++) for (int j = expandedArea.y(); j < expandedArea.maxY(); j++) if (!m_area.contains(i, j)) prepareTile(i, j, painter, state, isLowResPrefetch, true, updateWithBlit); } }
void RenderRadio::paintObject(PaintInfo& i, int _tx, int _ty) { ASSERT(node()); Element* element = static_cast<Element*>(node()); InputElement* inputElement = toInputElement(element); bool isEnabled = element->isEnabledFormControl(); bool isChecked = inputElement->isChecked(); i.context->save(); RefPtr<Image> image = Image::loadPlatformResource( "radioButtonStates" ).get(); IntPoint destPt( _tx, _ty ); IntRect srcRect( 0, 0, 14, 16 ); if (isEnabled) { if (node()->active()) { if (isChecked) { srcRect.move( 75, 0 ); } else { srcRect.move( 60, 0 ); } } else if (node()->hovered()) { if (isChecked) { srcRect.move( 45, 0 ); } else { srcRect.move( 30, 0 ); } } else { if (isChecked) { srcRect.move( 15, 0 ); } else { } } } else { if (isChecked) { srcRect.move( 105, 0 ); } else { srcRect.move( 90, 0 ); } } i.context->drawImage( image.get(), DeviceColorSpace, destPt, srcRect ); // draw the focus ring. // if (node()->focused()) { IntRect focusRingSrcRect( 120, 0, 15, 17 ); i.context->drawImage( image.get(), DeviceColorSpace, destPt, focusRingSrcRect ); } #if 0 // this is the old "moveto - lineto" drawing code IntRect checkRect(_tx + borderLeft() , _ty + borderTop() , width() - borderLeft() - borderRight() , height() - borderBottom() - borderTop()); Color fillColor(0xff, 0xff, 0xff, 0x00); Color rectColor(0x18, 0x52, 0x84); Color checkColor(0x21, 0xa5, 0x21); if (!node()->isEnabled()) { rectColor = Color(0xce, 0xce, 0xdb); checkColor = Color(0xce, 0xce, 0xdb); } i.context->setStrokeThickness(1); i.context->setStrokeStyle(SolidStroke); i.context->setStrokeColor(rectColor); i.context->setFillColor(fillColor); i.context->drawEllipse(checkRect); if(node()->isEnabled() && node()->hovered()) { i.context->setStrokeColor(Color(0xff, 0xb5, 0x31)); IntRect hoverRect = checkRect; hoverRect.inflateX(-1); hoverRect.inflateY(-1); i.context->drawEllipse( hoverRect ); hoverRect.inflateX(-1); hoverRect.inflateY(-1); i.context->drawEllipse( hoverRect ); } if (isChecked) { i.context->setStrokeThickness(2); i.context->setStrokeColor(checkColor); i.context->setFillColor(checkColor); IntRect fillRect = checkRect; fillRect.inflateX(-2); fillRect.inflateY(-2); i.context->drawEllipse(fillRect); } #endif i.context->restore(); }