void PointLightSource::render(const UsefulRenderData& render_data) { // If we are inside the sphere affected by the light source, render a full // quad. Otherwize just render the light sphere glm::vec4 position_world_space = glm::vec4(absoluteTransform()[3]); glm::vec3 position_view_space = glm::vec3(render_data.camera.viewTransform() * position_world_space); float distance_to_light_source = glm::length(position_view_space); // Probably not the best way of handling rescaled light sources, // but works for now.. glm::vec3 scale; glm::quat rotation; glm::vec3 translation; glm::vec3 skew; glm::vec4 perspective; glm::decompose( absoluteTransform(), scale, rotation, translation, skew,perspective); float transform_scale = scale.x; if (distance_to_light_source < _sphere_scale * transform_scale) renderQuad(render_data); else renderSphere(render_data); }
void RenderForeignObject::paint(PaintInfo& paintInfo, int parentX, int parentY) { if (paintInfo.context->paintingDisabled()) return; paintInfo.context->save(); paintInfo.context->concatCTM(AffineTransform().translate(parentX, parentY)); paintInfo.context->concatCTM(localTransform()); paintInfo.context->concatCTM(translationForAttributes()); paintInfo.context->clip(getClipRect(parentX, parentY)); float opacity = style()->opacity(); if (opacity < 1.0f) // FIXME: Possible optimization by clipping to bbox here, once relativeBBox is implemented & clip, mask and filter support added. paintInfo.context->beginTransparencyLayer(opacity); PaintInfo pi(paintInfo); pi.rect = absoluteTransform().inverse().mapRect(paintInfo.rect); RenderBlock::paint(pi, 0, 0); if (opacity < 1.0f) paintInfo.context->endTransparencyLayer(); paintInfo.context->restore(); }
void PointLightSource::renderSphere(const UsefulRenderData& render_data) { glm::mat4 scaled_transform = absoluteTransform(); scaled_transform[0][0] *= _sphere_scale; scaled_transform[1][1] *= _sphere_scale; scaled_transform[2][2] *= _sphere_scale; glUniformMatrix4fv( glGetUniformLocation(ShaderProgram::currentProgramId(), "M"), 1, GL_FALSE, &scaled_transform[0][0]); glUniformMatrix4fv( glGetUniformLocation(ShaderProgram::currentProgramId(), "V"), 1, GL_FALSE, &render_data.camera.viewTransform()[0][0]); glUniformMatrix4fv( glGetUniformLocation(ShaderProgram::currentProgramId(), "P"), 1, GL_FALSE, &render_data.camera.projectionTransform()[0][0]); setupLightSourceUniforms(render_data); _sphere_mesh->render(); }
IntRect RenderSVGInlineText::computeAbsoluteRectForRange(int startPos, int endPos) { IntRect rect; RenderBlock* cb = containingBlock(); if (!cb || !cb->container()) return rect; RenderSVGRoot* root = findSVGRootObject(parent()); if (!root) return rect; for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) rect.unite(box->selectionRect(0, 0, startPos, endPos)); // Mimic RenderBox::computeAbsoluteRepaintRect() functionality. But only the subset needed for SVG and respecting SVG transformations. int x, y; cb->container()->absolutePosition(x, y); // Remove HTML parent translation offsets here! These need to be retrieved from the RenderSVGRoot object. // But do take the containingBlocks's container position into account, ie. SVG text in scrollable <div>. AffineTransform htmlParentCtm = root->RenderContainer::absoluteTransform(); FloatRect fixedRect(narrowPrecisionToFloat(rect.x() + x - xPos() - htmlParentCtm.e()), narrowPrecisionToFloat(rect.y() + y - yPos() - htmlParentCtm.f()), rect.width(), rect.height()); return enclosingIntRect(absoluteTransform().mapRect(fixedRect)); }
bool RenderForeignObject::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction) { AffineTransform totalTransform = absoluteTransform(); totalTransform *= translationForAttributes(); double localX, localY; totalTransform.inverse().map(x, y, &localX, &localY); return RenderBlock::nodeAtPoint(request, result, static_cast<int>(localX), static_cast<int>(localY), tx, ty, hitTestAction); }
FloatPoint RenderPath::mapAbsolutePointToLocal(const FloatPoint& point) const { // FIXME: does it make sense to map incoming points with the inverse of the // absolute transform? double localX; double localY; absoluteTransform().inverse().map(point.x(), point.y(), &localX, &localY); return FloatPoint::narrowPrecision(localX, localY); }
mat33 CameraNode::cameraTransform() { if(_absoluteTransformDirty) { _cameraTransform = AffineTransform::inverse(absoluteTransform()); } return _cameraTransform; }
bool RenderSVGText::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction) { PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, style()->svgStyle()->pointerEvents()); bool isVisible = (style()->visibility() == VISIBLE); if (isVisible || !hitRules.requireVisible) { if ((hitRules.canHitStroke && (style()->svgStyle()->hasStroke() || !hitRules.requireStroke)) || (hitRules.canHitFill && (style()->svgStyle()->hasFill() || !hitRules.requireFill))) { AffineTransform totalTransform = absoluteTransform(); double localX, localY; totalTransform.inverse().map(_x, _y, &localX, &localY); FloatPoint hitPoint(_x, _y); return RenderBlock::nodeAtPoint(request, result, (int)localX, (int)localY, _tx, _ty, hitTestAction); } } return false; }
IntRect RenderSVGText::absoluteClippedOverflowRect() { FloatRect repaintRect = absoluteTransform().mapRect(relativeBBox(true)); #if ENABLE(SVG_FILTERS) // Filters can expand the bounding box SVGResourceFilter* filter = getFilterById(document(), style()->svgStyle()->filter()); if (filter) repaintRect.unite(filter->filterBBoxForItemBBox(repaintRect)); #endif if (!repaintRect.isEmpty()) repaintRect.inflate(1); // inflate 1 pixel for antialiasing return enclosingIntRect(repaintRect); }
std::pair<glm::vec3, glm::vec3> AbstractCamera::unproject( const glm::vec2& position_ndc) const { // Transform from [-1, 1] to [0, 1] glm::vec2 position = position_ndc / 2.0f + glm::vec2(0.5); float w = 1, h = 1; const glm::mat4& V = glm::inverse(absoluteTransform()); const glm::mat4& P = _projection_transform; glm::vec3 from = glm::unProject(glm::vec3(position, 0.0f), V, P, glm::vec4(0, 0, w, h)); glm::vec3 to = glm::unProject(glm::vec3(position, 1.0f), V, P, glm::vec4(0, 0, w, h)); return {from, to - from}; }
void RenderSVGImage::calculateAbsoluteBounds() { // FIXME: broken with CSS transforms FloatRect absoluteRect = absoluteTransform().mapRect(relativeBBox(true)); #if ENABLE(SVG_FILTERS) // Filters can expand the bounding box SVGResourceFilter* filter = getFilterById(document(), style()->svgStyle()->filter()); if (filter) absoluteRect.unite(filter->filterBBoxForItemBBox(absoluteRect)); #endif if (!absoluteRect.isEmpty()) absoluteRect.inflate(1); // inflate 1 pixel for antialiasing m_absoluteBounds = enclosingIntRect(absoluteRect); }
IntRect RenderSVGImage::absoluteClippedOverflowRect() { FloatRect repaintRect = relativeBBox(true); repaintRect = absoluteTransform().mapRect(repaintRect); #if ENABLE(SVG_EXPERIMENTAL_FEATURES) // Filters can expand the bounding box SVGResourceFilter* filter = getFilterById(document(), SVGURIReference::getTarget(style()->svgStyle()->filter())); if (filter) repaintRect.unite(filter->filterBBoxForItemBBox(repaintRect)); #endif if (!repaintRect.isEmpty()) repaintRect.inflate(1); // inflate 1 pixel for antialiasing return enclosingIntRect(repaintRect); }
void PointLightSource::setupLightSourceUniforms(const UsefulRenderData& render_data) { glm::vec4 position_world_space = glm::vec4(absoluteTransform()[3]); glm::vec4 position_view_space = render_data.camera.viewTransform() * position_world_space; glUniform3f( glGetUniformLocation(ShaderProgram::currentProgramId(), "light_source.position"), position_view_space.x, position_view_space.y, position_view_space.z); glUniform3f( glGetUniformLocation(ShaderProgram::currentProgramId(), "light_source.color"), _color.r, _color.g, _color.b); glUniform1f( glGetUniformLocation(ShaderProgram::currentProgramId(), "light_source.radiant_flux"), _radiant_flux); }
void RenderSVGTSpan::absoluteRects(Vector<IntRect>& rects, int, int, bool) { InlineRunBox* firstBox = firstLineBox(); SVGRootInlineBox* rootBox = firstBox ? static_cast<SVGInlineTextBox*>(firstBox)->svgRootInlineBox() : 0; RenderObject* object = rootBox ? rootBox->object() : 0; if (!object) return; int xRef = object->xPos() + xPos(); int yRef = object->yPos() + yPos(); for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) { FloatRect rect(xRef + curr->xPos(), yRef + curr->yPos(), curr->width(), curr->height()); rects.append(enclosingIntRect(absoluteTransform().mapRect(rect))); } }
void RenderSVGTextPath::absoluteRects(Vector<IntRect>& rects, int, int) { InlineRunBox* firstBox = firstLineBox(); SVGRootInlineBox* rootBox = firstBox ? static_cast<SVGInlineTextBox*>(firstBox)->svgRootInlineBox() : 0; RenderBlock* object = rootBox ? rootBox->block() : 0; if (!object) return; int xRef = object->x() + x(); int yRef = object->y() + y(); for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) { FloatRect rect(xRef + curr->xPos(), yRef + curr->yPos(), curr->width(), curr->height()); // FIXME: broken with CSS transforms rects.append(enclosingIntRect(absoluteTransform().mapRect(rect))); } }
void RenderSVGTextPath::absoluteQuads(Vector<FloatQuad>& quads, bool) { InlineRunBox* firstBox = firstLineBox(); SVGRootInlineBox* rootBox = firstBox ? static_cast<SVGInlineTextBox*>(firstBox)->svgRootInlineBox() : 0; RenderObject* object = rootBox ? rootBox->object() : 0; if (!object) return; int xRef = object->xPos() + xPos(); int yRef = object->yPos() + yPos(); for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) { FloatRect rect(xRef + curr->xPos(), yRef + curr->yPos(), curr->width(), curr->height()); // FIXME: broken with CSS transforms quads.append(absoluteTransform().mapRect(rect)); } }
IntRect RenderPath::clippedOverflowRectForRepaint(RenderBox* /*repaintContainer*/) { // FIXME: handle non-root repaintContainer FloatRect repaintRect = absoluteTransform().mapRect(relativeBBox(true)); // Markers can expand the bounding box repaintRect.unite(m_markerBounds); #if ENABLE(SVG_FILTERS) // Filters can expand the bounding box SVGResourceFilter* filter = getFilterById(document(), style()->svgStyle()->filter()); if (filter) repaintRect.unite(filter->filterBBoxForItemBBox(repaintRect)); #endif if (!repaintRect.isEmpty()) repaintRect.inflate(1); // inflate 1 pixel for antialiasing return enclosingIntRect(repaintRect); }
void DirectionalLightSource::setupLightSourceUniforms(const UsefulRenderData& render_data) { glm::vec3 direction_model_space = glm::vec3(0.0f, -1.0f, 0.0f); glm::vec3 direction_world_space = glm::mat3(absoluteTransform()) * direction_model_space; glm::vec3 direction_view_space = glm::mat3(render_data.camera.viewTransform()) * direction_world_space; glUniform3f( glGetUniformLocation(ShaderProgram::currentProgramId(), "light_source.direction"), direction_view_space.x, direction_view_space.y, direction_view_space.z); glUniform3f( glGetUniformLocation(ShaderProgram::currentProgramId(), "light_source.color"), _color.r, _color.g, _color.b); glUniform1f( glGetUniformLocation(ShaderProgram::currentProgramId(), "light_source.radiance"), _radiance); }
bool RenderSVGImage::nodeAtPoint(const HitTestRequest&, HitTestResult& result, int _x, int _y, int, int, HitTestAction hitTestAction) { // We only draw in the forground phase, so we only hit-test then. if (hitTestAction != HitTestForeground) return false; PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_IMAGE_HITTESTING, style()->pointerEvents()); bool isVisible = (style()->visibility() == VISIBLE); if (isVisible || !hitRules.requireVisible) { double localX, localY; absoluteTransform().inverse().map(_x, _y, localX, localY); if (hitRules.canHitFill) { if (m_localBounds.contains(narrowPrecisionToFloat(localX), narrowPrecisionToFloat(localY))) { updateHitTestResult(result, IntPoint(_x, _y)); return true; } } } return false; }
void RenderSVGText::absoluteRects(Vector<IntRect>& rects, int, int, bool) { RenderSVGRoot* root = findSVGRootObject(parent()); if (!root) return; int x, y; absolutePosition(x, y); AffineTransform htmlParentCtm = root->RenderContainer::absoluteTransform(); // Don't use relativeBBox here, as it's unites the selection rects. Makes it hard // to spot errors, if there are any using WebInspector. Individually feed them into 'rects'. for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) { ASSERT(runBox->isInlineFlowBox()); InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox); for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) { FloatRect boxRect(box->xPos(), box->yPos(), box->width(), box->height()); boxRect.move(narrowPrecisionToFloat(x - htmlParentCtm.e()), narrowPrecisionToFloat(y - htmlParentCtm.f())); rects.append(enclosingIntRect(absoluteTransform().mapRect(boxRect))); } } }
IntRect RenderSVGText::absoluteClippedOverflowRect() { return enclosingIntRect(absoluteTransform().mapRect(relativeBBox(true))); }
void RenderSVGText::paint(PaintInfo& paintInfo, int, int) { RenderObject::PaintInfo pi(paintInfo); pi.rect = absoluteTransform().inverse().mapRect(pi.rect); RenderBlock::paint(pi, 0, 0); }
void RenderSVGImage::paint(PaintInfo& paintInfo, int parentX, int parentY) { if (paintInfo.context->paintingDisabled() || (paintInfo.phase != PaintPhaseForeground) || style()->visibility() == HIDDEN) return; paintInfo.context->save(); paintInfo.context->concatCTM(AffineTransform().translate(parentX, parentY)); paintInfo.context->concatCTM(localTransform()); paintInfo.context->concatCTM(translationForAttributes()); FloatRect boundingBox = FloatRect(0, 0, width(), height()); SVGElement* svgElement = static_cast<SVGElement*>(element()); ASSERT(svgElement && svgElement->document() && svgElement->isStyled()); SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement); const SVGRenderStyle* svgStyle = style()->svgStyle(); AtomicString filterId(SVGURIReference::getTarget(svgStyle->filter())); AtomicString clipperId(SVGURIReference::getTarget(svgStyle->clipPath())); AtomicString maskerId(SVGURIReference::getTarget(svgStyle->maskElement())); #if ENABLE(SVG_EXPERIMENTAL_FEATURES) SVGResourceFilter* filter = getFilterById(document(), filterId); #endif SVGResourceClipper* clipper = getClipperById(document(), clipperId); SVGResourceMasker* masker = getMaskerById(document(), maskerId); #if ENABLE(SVG_EXPERIMENTAL_FEATURES) if (filter) filter->prepareFilter(paintInfo.context, boundingBox); else if (!filterId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement); #endif if (clipper) { clipper->addClient(styledElement); clipper->applyClip(paintInfo.context, boundingBox); } else if (!clipperId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement); if (masker) { masker->addClient(styledElement); masker->applyMask(paintInfo.context, boundingBox); } else if (!maskerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement); float opacity = style()->opacity(); if (opacity < 1.0f) { paintInfo.context->clip(enclosingIntRect(boundingBox)); paintInfo.context->beginTransparencyLayer(opacity); } PaintInfo pi(paintInfo); pi.rect = absoluteTransform().inverse().mapRect(pi.rect); SVGImageElement* imageElt = static_cast<SVGImageElement*>(node()); FloatRect destRect(m_x, m_y, contentWidth(), contentHeight()); FloatRect srcRect(0, 0, image()->width(), image()->height()); if (imageElt->preserveAspectRatio()->align() != SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE) adjustRectsForAspectRatio(destRect, srcRect, imageElt->preserveAspectRatio()); paintInfo.context->drawImage(image(), destRect, srcRect); #if ENABLE(SVG_EXPERIMENTAL_FEATURES) if (filter) filter->applyFilter(paintInfo.context, boundingBox); #endif if (opacity < 1.0f) paintInfo.context->endTransparencyLayer(); paintInfo.context->restore(); }
glm::mat4 AbstractCamera::viewTransform() const { return glm::inverse(absoluteTransform()); }
void RenderSVGInlineText::absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool) { FloatRect absoluteRect = absoluteTransform().mapRect(FloatRect(tx, ty, width(), height())); rects.append(enclosingIntRect(absoluteRect)); }