/** * Calculates whether content drawn within the passed bounds would be outside of, or intersect with * the clipRect. Does not modify the scissor. * * @param clipRequired if not null, will be set to true if element intersects clip * (and wasn't rejected) * * @param snapOut if set, the geometry will be treated as having an AA ramp. * See Rect::snapGeometryToPixelBoundaries() */ bool CanvasState::calculateQuickRejectForScissor(float left, float top, float right, float bottom, bool* clipRequired, bool* roundRectClipRequired, bool snapOut) const { if (bottom <= top || right <= left) { return true; } Rect r(left, top, right, bottom); currentTransform()->mapRect(r); r.snapGeometryToPixelBoundaries(snapOut); Rect clipRect(currentRenderTargetClip()); clipRect.snapToPixelBoundaries(); if (!clipRect.intersects(r)) return true; // clip is required if geometry intersects clip rect if (clipRequired) { *clipRequired = !clipRect.contains(r); } // round rect clip is required if RR clip exists, and geometry intersects its corners if (roundRectClipRequired) { *roundRectClipRequired = mSnapshot->roundRectClipState != nullptr && mSnapshot->roundRectClipState->areaRequiresRoundRectClip(r); } return false; }
void beginClipping(int x, int y, int width, int height, int screenHeight) { // Apply current transformation. double left = x, right = x + width; double top = y, bottom = y + height; applyTransform(currentTransform(), left, top); applyTransform(currentTransform(), right, bottom); int physX = std::min(left, right); int physY = std::min(top, bottom); int physWidth = std::abs(int(left - right)); int physHeight = std::abs(int(top - bottom)); // Adjust for OpenGL having the wrong idea of where y=0 is. // TODO: This should really happen *right before* setting up // the glScissor. physY = screenHeight - physY - physHeight; clipRectStack.beginClipping(physX, physY, physWidth, physHeight); }
void CanvasState::setClippingOutline(LinearAllocator& allocator, const Outline* outline) { Rect bounds; float radius; if (!outline->getAsRoundRect(&bounds, &radius)) return; // only RR supported bool outlineIsRounded = MathUtils::isPositive(radius); if (!outlineIsRounded || currentTransform()->isSimple()) { // TODO: consider storing this rect separately, so that this can't be replaced with clip ops clipRect(bounds.left, bounds.top, bounds.right, bounds.bottom, SkClipOp::kIntersect); } if (outlineIsRounded) { setClippingRoundRect(allocator, bounds, radius, false); } }
void scheduleDrawOp(DrawOp op) { if (clipRectStack.clippedWorldAway()) return; #ifdef GOSU_IS_IPHONE // No triangles, no lines supported assert (op.verticesOrBlockIndex == 4); #endif op.renderState.transform = ¤tTransform(); if (const ClipRect* cr = clipRectStack.maybeEffectiveRect()) op.renderState.clipRect = *cr; ops.push_back(op); }
bool CanvasState::quickRejectConservative(float left, float top, float right, float bottom) const { if (bottom <= top || right <= left) { return true; } Rect r(left, top, right, bottom); currentTransform()->mapRect(r); r.roundOut(); // rounded out to be conservative Rect clipRect(currentRenderTargetClip()); clipRect.snapToPixelBoundaries(); if (!clipRect.intersects(r)) return true; return false; }
void scheduleGL(std::tr1::function<void()> glBlock, ZPos z) { // TODO: Document this case: Clipped-away GL blocks are *not* being run. if (clipRectStack.clippedWorldAway()) return; int complementOfBlockIndex = ~(int)glBlocks.size(); glBlocks.push_back(glBlock); DrawOp op; op.verticesOrBlockIndex = complementOfBlockIndex; op.renderState.transform = ¤tTransform(); if (const ClipRect* cr = clipRectStack.maybeEffectiveRect()) op.renderState.clipRect = *cr; op.z = z; ops.push_back(op); }
void OpenGLInstance::commit(const OpenGLViewport &viewport) { P(OpenGLInstancePrivate); OpenGLBuffer::RangeAccessFlags flags = OpenGLBuffer::RangeUnsynchronized | OpenGLBuffer::RangeInvalidateBuffer | OpenGLBuffer::RangeWrite; p.m_buffer.bind(); // Send data to the GPU { OpenGLInstanceData *data = (OpenGLInstanceData*)p.m_buffer.mapRange(0, sizeof(OpenGLInstanceData), flags); data->m_currModelView = viewport.current().worldToView() * Karma::ToGlm(currentTransform().toMatrix() ); data->m_prevModelView = viewport.previous().worldToView() * Karma::ToGlm(previousTransform().toMatrix()); data->m_normalTransform = glm::transpose(glm::inverse(data->m_currModelView)); p.m_buffer.unmap(); } update(); // Updates current/previous pairs p.m_buffer.release(); }
void pushTransform(const Transform& transform) { individualTransforms.push_back(transform); Transform result = multiply(transform, currentTransform()); makeCurrentTransform(result); }