void Path::transform(const AffineTransform& transformation) { PlatformPathOpenVG* dst = new PlatformPathOpenVG(); // dst->makeCompatibleContextCurrent() is called by the platform path // constructor, therefore not necessary to call it again here. PainterOpenVG::transformPath(dst->vgPath(), m_path->vgPath(), transformation); delete m_path; m_path = dst; m_path->m_currentPoint = transformation.mapPoint(m_path->m_currentPoint); m_path->m_subpathStartPoint = transformation.mapPoint(m_path->m_subpathStartPoint); }
static bool paintMozWidget(RenderTheme* theme, GtkThemeWidgetType type, RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) { // No GdkWindow to render to, so return true to fall back if (!i.context->gdkDrawable()) return true; // Painting is disabled so just claim to have succeeded if (i.context->paintingDisabled()) return false; GtkWidgetState mozState; setMozState(theme, &mozState, o); int flags; // We might want to make setting flags the caller's job at some point rather than doing it here. switch (type) { case MOZ_GTK_BUTTON: flags = GTK_RELIEF_NORMAL; break; case MOZ_GTK_CHECKBUTTON: case MOZ_GTK_RADIOBUTTON: flags = theme->isChecked(o); break; default: flags = 0; break; } AffineTransform ctm = i.context->getCTM(); IntPoint pos = ctm.mapPoint(rect.location()); GdkRectangle gdkRect = IntRect(pos.x(), pos.y(), rect.width(), rect.height()); GtkTextDirection direction = gtkTextDirection(o->style()->direction()); // Find the clip rectangle cairo_t *cr = i.context->platformContext(); double clipX1, clipX2, clipY1, clipY2; cairo_clip_extents(cr, &clipX1, &clipY1, &clipX2, &clipY2); GdkRectangle gdkClipRect; gdkClipRect.width = clipX2 - clipX1; gdkClipRect.height = clipY2 - clipY1; IntPoint clipPos = ctm.mapPoint(IntPoint(clipX1, clipY1)); gdkClipRect.x = clipPos.x(); gdkClipRect.y = clipPos.y(); gdk_rectangle_intersect(&gdkRect, &gdkClipRect, &gdkClipRect); return moz_gtk_widget_paint(type, i.context->gdkDrawable(), &gdkRect, &gdkClipRect, &mozState, flags, direction) != MOZ_GTK_SUCCESS; }
WebMouseEvent WebEventFactory::createWebMouseEvent(const Evas_Event_Mouse_Down* event, const AffineTransform& toWebContent, const AffineTransform& toDeviceScreen) { IntPoint pos(event->canvas.x, event->canvas.y); return WebMouseEvent(WebEvent::MouseDown, buttonForEvent(event->button), toWebContent.mapPoint(pos), toDeviceScreen.mapPoint(pos), 0 /* deltaX */, 0 /* deltaY */, 0 /* deltaZ */, clickCountForEvent(event->flags), modifiersForEvent(event->modifiers), convertMillisecondToSecond(event->timestamp)); }
WebMouseEvent WebEventFactory::createWebMouseEvent(const Evas_Event_Mouse_Move* event, const AffineTransform& toWebContent, const AffineTransform& toDeviceScreen) { IntPoint pos(event->cur.canvas.x, event->cur.canvas.y); return WebMouseEvent(WebEvent::MouseMove, buttonForEvent(event->buttons), toWebContent.mapPoint(pos), toDeviceScreen.mapPoint(pos), (event->cur.canvas.x - event->prev.canvas.x) /* deltaX */, (event->cur.canvas.y - event->prev.canvas.y) /* deltaY */, 0 /* deltaZ */, 0 /* clickCount */, modifiersForEvent(event->modifiers), convertMillisecondToSecond(event->timestamp)); }
bool RenderThemeGtk::paintMozillaGtkWidget(GtkThemeWidgetType type, GraphicsContext* context, const IntRect& rect, GtkWidgetState* widgetState, int flags, GtkTextDirection textDirection) { // Painting is disabled so just claim to have succeeded if (context->paintingDisabled()) return false; PlatformRefPtr<GdkDrawable> drawable(context->gdkDrawable()); GdkRectangle paintRect, clipRect; if (drawable) { AffineTransform ctm = context->getCTM(); IntPoint pos = ctm.mapPoint(rect.location()); paintRect = IntRect(pos.x(), pos.y(), rect.width(), rect.height()); // Intersect the cairo rectangle with the target widget region. This will // prevent the theme drawing code from drawing into regions that cairo will // clip anyway. double clipX1, clipX2, clipY1, clipY2; cairo_clip_extents(context->platformContext(), &clipX1, &clipY1, &clipX2, &clipY2); IntPoint clipPos = ctm.mapPoint(IntPoint(clipX1, clipY1)); clipRect.width = clipX2 - clipX1; clipRect.height = clipY2 - clipY1; clipRect.x = clipPos.x(); clipRect.y = clipPos.y(); gdk_rectangle_intersect(&paintRect, &clipRect, &clipRect); } else { // In some situations, like during print previews, this GraphicsContext is not // backed by a GdkDrawable. In those situations, we render onto a pixmap and then // copy the rendered data back to the GraphicsContext via Cairo. drawable = adoptPlatformRef(gdk_pixmap_new(0, rect.width(), rect.height(), gdk_visual_get_depth(gdk_visual_get_system()))); paintRect = clipRect = IntRect(0, 0, rect.width(), rect.height()); } moz_gtk_use_theme_parts(partsForDrawable(drawable.get())); bool success = moz_gtk_widget_paint(type, drawable.get(), &paintRect, &clipRect, widgetState, flags, textDirection) == MOZ_GTK_SUCCESS; // If the drawing was successful and we rendered onto a pixmap, copy the // results back to the original GraphicsContext. if (success && !context->gdkDrawable()) { cairo_t* cairoContext = context->platformContext(); cairo_save(cairoContext); gdk_cairo_set_source_pixmap(cairoContext, drawable.get(), rect.x(), rect.y()); cairo_paint(cairoContext); cairo_restore(cairoContext); } return !success; }
WebTouchEvent WebEventFactory::createWebTouchEvent(Ewk_Touch_Event_Type type, const Eina_List* points, const Evas_Modifier* modifiers, const AffineTransform& toWebContent, const AffineTransform& toDeviceScreen, double timestamp) { Vector<WebPlatformTouchPoint> touchPoints; touchPoints.reserveInitialCapacity(eina_list_count(points)); const Eina_List* list; void* item; EINA_LIST_FOREACH(points, list, item) { Ewk_Touch_Point* point = static_cast<Ewk_Touch_Point*>(item); WebPlatformTouchPoint::TouchPointState state; switch (point->state) { case EVAS_TOUCH_POINT_UP: state = WebPlatformTouchPoint::TouchReleased; break; case EVAS_TOUCH_POINT_MOVE: state = WebPlatformTouchPoint::TouchMoved; break; case EVAS_TOUCH_POINT_DOWN: state = WebPlatformTouchPoint::TouchPressed; break; case EVAS_TOUCH_POINT_STILL: state = WebPlatformTouchPoint::TouchStationary; break; case EVAS_TOUCH_POINT_CANCEL: state = WebPlatformTouchPoint::TouchCancelled; break; default: ASSERT_NOT_REACHED(); continue; } IntPoint pos(point->x, point->y); touchPoints.uncheckedAppend(WebPlatformTouchPoint(point->id, state, toDeviceScreen.mapPoint(pos), toWebContent.mapPoint(pos))); }
FloatRect GraphicsContext::computeLineBoundsAndAntialiasingModeForText(const FloatPoint& point, float width, bool printing, bool& shouldAntialias, Color& color) { FloatPoint origin = point; float thickness = std::max(strokeThickness(), 0.5f); shouldAntialias = true; if (!printing) { AffineTransform transform = getCTM(GraphicsContext::DefinitelyIncludeDeviceScale); if (transform.preservesAxisAlignment()) shouldAntialias = false; // This code always draws a line that is at least one-pixel line high, // which tends to visually overwhelm text at small scales. To counter this // effect, an alpha is applied to the underline color when text is at small scales. // Just compute scale in x dimension, assuming x and y scales are equal. float scale = transform.b() ? sqrtf(transform.a() * transform.a() + transform.b() * transform.b()) : transform.a(); if (scale < 1.0) { static const float minimumUnderlineAlpha = 0.4f; float shade = scale > minimumUnderlineAlpha ? scale : minimumUnderlineAlpha; int alpha = color.alpha() * shade; color = Color(color.red(), color.green(), color.blue(), alpha); } FloatPoint devicePoint = transform.mapPoint(point); FloatPoint deviceOrigin = FloatPoint(roundf(devicePoint.x()), ceilf(devicePoint.y())); if (auto inverse = transform.inverse()) origin = inverse.value().mapPoint(deviceOrigin); } return FloatRect(origin.x(), origin.y(), width, thickness); }
bool SVGTextQuery::endPositionOfCharacterCallback(Data* queryData, const SVGTextFragment& fragment) const { EndPositionOfCharacterData* data = static_cast<EndPositionOfCharacterData*>(queryData); int startPosition = data->position; int endPosition = startPosition + 1; if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startPosition, endPosition)) return false; data->endPosition = FloatPoint(fragment.x, fragment.y); SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->textRenderer, fragment.characterOffset, startPosition + 1); if (queryData->isVerticalText) data->endPosition.move(0, metrics.height()); else data->endPosition.move(metrics.width(), 0); AffineTransform fragmentTransform; fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::TransformIgnoringTextLength); if (fragmentTransform.isIdentity()) return true; data->endPosition = fragmentTransform.mapPoint(data->endPosition); return true; }
FloatRect GraphicsContext::computeLineBoundsAndAntialiasingModeForText(const FloatPoint& point, float width, bool printing, Color& color) { FloatPoint origin = point; float thickness = std::max(strokeThickness(), 0.5f); if (printing) return FloatRect(origin, FloatSize(width, thickness)); AffineTransform transform = getCTM(GraphicsContext::DefinitelyIncludeDeviceScale); // Just compute scale in x dimension, assuming x and y scales are equal. float scale = transform.b() ? sqrtf(transform.a() * transform.a() + transform.b() * transform.b()) : transform.a(); if (scale < 1.0) { // This code always draws a line that is at least one-pixel line high, // which tends to visually overwhelm text at small scales. To counter this // effect, an alpha is applied to the underline color when text is at small scales. static const float minimumUnderlineAlpha = 0.4f; float shade = scale > minimumUnderlineAlpha ? scale : minimumUnderlineAlpha; int alpha = color.alpha() * shade; color = Color(color.red(), color.green(), color.blue(), alpha); } FloatPoint devicePoint = transform.mapPoint(point); // Visual overflow might occur here due to integral roundf/ceilf. visualOverflowForDecorations adjusts the overflow value for underline decoration. FloatPoint deviceOrigin = FloatPoint(roundf(devicePoint.x()), ceilf(devicePoint.y())); if (auto inverse = transform.inverse()) origin = inverse.value().mapPoint(deviceOrigin); return FloatRect(origin, FloatSize(width, thickness)); }
std::pair<float, float> SVGGlyphToPathTranslator::extents() { AffineTransform glyphPathTransform = transform(); FloatPoint beginning = glyphPathTransform.mapPoint(m_currentPoint); FloatSize end = glyphPathTransform.mapSize(FloatSize(m_glyphBuffer.advanceAt(m_index))); return std::make_pair(beginning.x(), beginning.x() + end.width()); }
static FloatPoint calculateGlyphPosition(const QueryData* queryData, const SVGTextFragment& fragment, int offsetInFragment) { FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData, fragment, offsetInFragment); if (fragment.isTransformed()) { AffineTransform fragmentTransform = fragment.buildFragmentTransform(SVGTextFragment::TransformIgnoringTextLength); glyphPosition = fragmentTransform.mapPoint(glyphPosition); } return glyphPosition; }
bool RenderSVGShape::shapeDependentStrokeContains(const FloatPoint& point) { ASSERT(m_path); BoundingRectStrokeStyleApplier applier(this, style()); if (hasNonScalingStroke()) { AffineTransform nonScalingTransform = nonScalingStrokeTransform(); Path* usePath = nonScalingStrokePath(m_path.get(), nonScalingTransform); return usePath->strokeContains(&applier, nonScalingTransform.mapPoint(point)); } return m_path->strokeContains(&applier, point); }
bool RenderSVGShape::shapeDependentStrokeContains(const FloatPoint& point) { ASSERT(m_path); StrokeData strokeData; SVGRenderSupport::applyStrokeStyleToStrokeData(&strokeData, style(), this); if (hasNonScalingStroke()) { AffineTransform nonScalingTransform = nonScalingStrokeTransform(); Path* usePath = nonScalingStrokePath(m_path.get(), nonScalingTransform); return usePath->strokeContains(nonScalingTransform.mapPoint(point), strokeData); } return m_path->strokeContains(point, strokeData); }
WebTouchEvent WebEventFactory::createWebTouchEvent(const EwkTouchEvent* event, const AffineTransform& toWebContent) { API::Array* touchPointsArray = toImpl(event->touchPoints()); size_t size = touchPointsArray->size(); Vector<WebPlatformTouchPoint> touchPoints; touchPoints.reserveInitialCapacity(size); for (size_t i = 0; i < size; ++i) { if (EwkTouchPoint* point = touchPointsArray->at<EwkTouchPoint>(i)) touchPoints.uncheckedAppend(WebPlatformTouchPoint(point->id(), toWebPlatformTouchPointState(point->state()), toIntPoint(point->screenPosition()), toWebContent.mapPoint(toIntPoint(point->position())), toIntSize(point->radius()), point->rotationAngle(), point->forceFactor())); } return WebTouchEvent(toWebEventType(event->eventType()), touchPoints, toWebEventModifiers(event->modifiers()), event->timestamp()); }
// This works by converting the SVG arc to "simple" beziers. // Partly adapted from Niko's code in kdelibs/kdecore/svgicons. // See also SVG implementation notes: // http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter bool SVGPathNormalizer::decomposeArcToCubic(const FloatPoint& currentPoint, const PathSegmentData& arcSegment) { // If rx = 0 or ry = 0 then this arc is treated as a straight line segment (a // "lineto") joining the endpoints. // http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters float rx = fabsf(arcSegment.arcRadii().x()); float ry = fabsf(arcSegment.arcRadii().y()); if (!rx || !ry) return false; // If the current point and target point for the arc are identical, it should // be treated as a zero length path. This ensures continuity in animations. if (arcSegment.targetPoint == currentPoint) return false; float angle = arcSegment.arcAngle(); FloatSize midPointDistance = currentPoint - arcSegment.targetPoint; midPointDistance.scale(0.5f); AffineTransform pointTransform; pointTransform.rotate(-angle); FloatPoint transformedMidPoint = pointTransform.mapPoint( FloatPoint(midPointDistance.width(), midPointDistance.height())); float squareRx = rx * rx; float squareRy = ry * ry; float squareX = transformedMidPoint.x() * transformedMidPoint.x(); float squareY = transformedMidPoint.y() * transformedMidPoint.y(); // Check if the radii are big enough to draw the arc, scale radii if not. // http://www.w3.org/TR/SVG/implnote.html#ArcCorrectionOutOfRangeRadii float radiiScale = squareX / squareRx + squareY / squareRy; if (radiiScale > 1) { rx *= sqrtf(radiiScale); ry *= sqrtf(radiiScale); } pointTransform.makeIdentity(); pointTransform.scale(1 / rx, 1 / ry); pointTransform.rotate(-angle); FloatPoint point1 = pointTransform.mapPoint(currentPoint); FloatPoint point2 = pointTransform.mapPoint(arcSegment.targetPoint); FloatSize delta = point2 - point1; float d = delta.width() * delta.width() + delta.height() * delta.height(); float scaleFactorSquared = std::max(1 / d - 0.25f, 0.f); float scaleFactor = sqrtf(scaleFactorSquared); if (arcSegment.arcSweep == arcSegment.arcLarge) scaleFactor = -scaleFactor; delta.scale(scaleFactor); FloatPoint centerPoint = point1 + point2; centerPoint.scale(0.5f, 0.5f); centerPoint.move(-delta.height(), delta.width()); float theta1 = FloatPoint(point1 - centerPoint).slopeAngleRadians(); float theta2 = FloatPoint(point2 - centerPoint).slopeAngleRadians(); float thetaArc = theta2 - theta1; if (thetaArc < 0 && arcSegment.arcSweep) thetaArc += twoPiFloat; else if (thetaArc > 0 && !arcSegment.arcSweep) thetaArc -= twoPiFloat; pointTransform.makeIdentity(); pointTransform.rotate(angle); pointTransform.scale(rx, ry); // Some results of atan2 on some platform implementations are not exact // enough. So that we get more cubic curves than expected here. Adding 0.001f // reduces the count of sgements to the correct count. int segments = ceilf(fabsf(thetaArc / (piOverTwoFloat + 0.001f))); for (int i = 0; i < segments; ++i) { float startTheta = theta1 + i * thetaArc / segments; float endTheta = theta1 + (i + 1) * thetaArc / segments; float t = (8 / 6.f) * tanf(0.25f * (endTheta - startTheta)); if (!std::isfinite(t)) return false; float sinStartTheta = sinf(startTheta); float cosStartTheta = cosf(startTheta); float sinEndTheta = sinf(endTheta); float cosEndTheta = cosf(endTheta); point1 = FloatPoint(cosStartTheta - t * sinStartTheta, sinStartTheta + t * cosStartTheta); point1.move(centerPoint.x(), centerPoint.y()); FloatPoint targetPoint = FloatPoint(cosEndTheta, sinEndTheta); targetPoint.move(centerPoint.x(), centerPoint.y()); point2 = targetPoint; point2.move(t * sinEndTheta, -t * cosEndTheta); PathSegmentData cubicSegment; cubicSegment.command = PathSegCurveToCubicAbs; cubicSegment.point1 = pointTransform.mapPoint(point1); cubicSegment.point2 = pointTransform.mapPoint(point2); cubicSegment.targetPoint = pointTransform.mapPoint(targetPoint); m_consumer->emitSegment(cubicSegment); } return true; }
// This works by converting the SVG arc to "simple" beziers. // Partly adapted from Niko's code in kdelibs/kdecore/svgicons. // See also SVG implementation notes: http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter bool SVGPathParser::decomposeArcToCubic(float angle, float rx, float ry, FloatPoint& point1, FloatPoint& point2, bool largeArcFlag, bool sweepFlag) { FloatSize midPointDistance = point1 - point2; midPointDistance.scale(0.5f); AffineTransform pointTransform; pointTransform.rotate(-angle); FloatPoint transformedMidPoint = pointTransform.mapPoint(FloatPoint(midPointDistance.width(), midPointDistance.height())); float squareRx = rx * rx; float squareRy = ry * ry; float squareX = transformedMidPoint.x() * transformedMidPoint.x(); float squareY = transformedMidPoint.y() * transformedMidPoint.y(); // Check if the radii are big enough to draw the arc, scale radii if not. // http://www.w3.org/TR/SVG/implnote.html#ArcCorrectionOutOfRangeRadii float radiiScale = squareX / squareRx + squareY / squareRy; if (radiiScale > 1) { rx *= sqrtf(radiiScale); ry *= sqrtf(radiiScale); } pointTransform.makeIdentity(); pointTransform.scale(1 / rx, 1 / ry); pointTransform.rotate(-angle); point1 = pointTransform.mapPoint(point1); point2 = pointTransform.mapPoint(point2); FloatSize delta = point2 - point1; float d = delta.width() * delta.width() + delta.height() * delta.height(); float scaleFactorSquared = std::max(1 / d - 0.25f, 0.f); float scaleFactor = sqrtf(scaleFactorSquared); if (sweepFlag == largeArcFlag) scaleFactor = -scaleFactor; delta.scale(scaleFactor); FloatPoint centerPoint = point1 + point2; centerPoint.scale(0.5f); centerPoint.move(-delta.height(), delta.width()); float theta1 = FloatPoint(point1 - centerPoint).slopeAngleRadians(); float theta2 = FloatPoint(point2 - centerPoint).slopeAngleRadians(); float thetaArc = theta2 - theta1; if (thetaArc < 0 && sweepFlag) thetaArc += 2 * piFloat; else if (thetaArc > 0 && !sweepFlag) thetaArc -= 2 * piFloat; pointTransform.makeIdentity(); pointTransform.rotate(angle); pointTransform.scale(rx, ry); // Some results of atan2 on some platform implementations are not exact enough. So that we get more // cubic curves than expected here. Adding 0.001f reduces the count of sgements to the correct count. int segments = ceilf(fabsf(thetaArc / (piOverTwoFloat + 0.001f))); for (int i = 0; i < segments; ++i) { float startTheta = theta1 + i * thetaArc / segments; float endTheta = theta1 + (i + 1) * thetaArc / segments; float t = (8 / 6.f) * tanf(0.25f * (endTheta - startTheta)); if (!std::isfinite(t)) return false; float sinStartTheta = sinf(startTheta); float cosStartTheta = cosf(startTheta); float sinEndTheta = sinf(endTheta); float cosEndTheta = cosf(endTheta); point1 = FloatPoint(cosStartTheta - t * sinStartTheta, sinStartTheta + t * cosStartTheta); point1.move(centerPoint.x(), centerPoint.y()); FloatPoint targetPoint = FloatPoint(cosEndTheta, sinEndTheta); targetPoint.move(centerPoint.x(), centerPoint.y()); point2 = targetPoint; point2.move(t * sinEndTheta, -t * cosEndTheta); m_consumer.curveToCubic(pointTransform.mapPoint(point1), pointTransform.mapPoint(point2), pointTransform.mapPoint(targetPoint), AbsoluteCoordinates); } return true; }
std::pair<float, float> CairoGlyphToPathTranslator::extents() { FloatPoint beginning = m_translation.mapPoint(FloatPoint()); FloatSize end = m_translation.mapSize(m_glyphBuffer.advanceAt(m_index)); return std::make_pair(static_cast<float>(beginning.x()), static_cast<float>(beginning.x() + end.width())); }
static bool paintMozillaGtkWidget(const RenderThemeGtk* theme, GtkThemeWidgetType type, RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) { GRefPtr<GdkDrawable> pixmap; // Painting is disabled so just claim to have succeeded if (i.context->paintingDisabled()) return false; // No GdkWindow to render to, so return true to fall back if (!i.context->gdkDrawable()) // This is slow, used only during printing process pixmap = adoptGRef(gdk_pixmap_new(0, rect.width(), rect.height(), gdk_visual_get_system()->depth)); GtkWidgetState mozState; setMozillaState(theme, &mozState, o); int flags; // We might want to make setting flags the caller's job at some point rather than doing it here. switch (type) { case MOZ_GTK_BUTTON: flags = GTK_RELIEF_NORMAL; break; case MOZ_GTK_CHECKBUTTON: case MOZ_GTK_RADIOBUTTON: flags = theme->isChecked(o); break; default: flags = 0; break; } GtkTextDirection direction = gtkTextDirection(o->style()->direction()); if (pixmap) { GdkRectangle gdkRect = IntRect(0, 0, rect.width(), rect.height()); moz_gtk_use_theme_parts(theme->partsForDrawable(pixmap.get())); bool result = moz_gtk_widget_paint(type, pixmap.get(), &gdkRect, &gdkRect, &mozState, flags, direction) != MOZ_GTK_SUCCESS; if (!result) { cairo_t* cr = i.context->platformContext(); gdk_cairo_set_source_pixmap(cr, pixmap.get(), rect.x(), rect.y()); cairo_paint(cr); } return result; } AffineTransform ctm = i.context->getCTM(); IntPoint pos = ctm.mapPoint(rect.location()); GdkRectangle gdkRect = IntRect(pos.x(), pos.y(), rect.width(), rect.height()); // Find the clip rectangle cairo_t* cr = i.context->platformContext(); double clipX1, clipX2, clipY1, clipY2; cairo_clip_extents(cr, &clipX1, &clipY1, &clipX2, &clipY2); GdkRectangle gdkClipRect; gdkClipRect.width = clipX2 - clipX1; gdkClipRect.height = clipY2 - clipY1; IntPoint clipPos = ctm.mapPoint(IntPoint(clipX1, clipY1)); gdkClipRect.x = clipPos.x(); gdkClipRect.y = clipPos.y(); gdk_rectangle_intersect(&gdkRect, &gdkClipRect, &gdkClipRect); // Since the theme renderer is going to be drawing onto this GdkDrawable, // select the appropriate widgets for the drawable depth. moz_gtk_use_theme_parts(theme->partsForDrawable(i.context->gdkDrawable())); return moz_gtk_widget_paint(type, i.context->gdkDrawable(), &gdkRect, &gdkClipRect, &mozState, flags, direction) != MOZ_GTK_SUCCESS; }