void AndroidGeckoLayerClient::SyncFrameMetrics(const gfx::Point& aScrollOffset, float aZoom, const gfx::Rect& aCssPageRect, bool aLayersUpdated, const gfx::Rect& aDisplayPort, float aDisplayResolution, bool aIsFirstPaint, gfx::Margin& aFixedLayerMargins, gfx::Point& aOffset) { NS_ASSERTION(!isNull(), "SyncFrameMetrics called on null layer client!"); JNIEnv *env = GetJNIForThread(); // this is called on the compositor thread if (!env) return; AutoLocalJNIFrame jniFrame(env); // convert the displayport rect from scroll-relative CSS pixels to document-relative device pixels int dpX = NS_lround((aDisplayPort.x * aDisplayResolution) + aScrollOffset.x); int dpY = NS_lround((aDisplayPort.y * aDisplayResolution) + aScrollOffset.y); int dpW = NS_lround(aDisplayPort.width * aDisplayResolution); int dpH = NS_lround(aDisplayPort.height * aDisplayResolution); jobject viewTransformJObj = env->CallObjectMethod(wrapped_obj, jSyncFrameMetricsMethod, aScrollOffset.x, aScrollOffset.y, aZoom, aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost(), aLayersUpdated, dpX, dpY, dpW, dpH, aDisplayResolution, aIsFirstPaint); if (jniFrame.CheckForException()) return; NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!"); AndroidViewTransform viewTransform; viewTransform.Init(viewTransformJObj); viewTransform.GetFixedLayerMargins(env, aFixedLayerMargins); aOffset.x = viewTransform.GetOffsetX(env); aOffset.y = viewTransform.GetOffsetY(env); }
static void rectgrid(ui::Graphics* g, const gfx::Rect& rc, const gfx::Size& tile) { if (tile.w < 1 || tile.h < 1) return; int x, y, u, v; gfx::Color c1 = gfx::rgba(128, 128, 128); gfx::Color c2 = gfx::rgba(192, 192, 192); u = 0; v = 0; for (y=rc.y; y<rc.y2()-tile.h; y+=tile.h) { for (x=rc.x; x<rc.x2()-tile.w; x+=tile.w) g->fillRect(((u++)&1)? c1: c2, gfx::Rect(x, y, tile.w, tile.h)); if (x < rc.x2()) g->fillRect(((u++)&1)? c1: c2, gfx::Rect(x, y, rc.x2()-x, tile.h)); u = (++v); } if (y < rc.y2()) { for (x=rc.x; x<rc.x2()-tile.w; x+=tile.w) g->fillRect(((u++)&1)? c1: c2, gfx::Rect(x, y, tile.w, rc.y2()-y)); if (x < rc.x2()) g->fillRect(((u++)&1)? c1: c2, gfx::Rect(x, y, rc.x2()-x, rc.y2()-y)); } }
static void DrawSurfaceWithTextureCoords(DrawTarget *aDest, const gfx::Rect& aDestRect, SourceSurface *aSource, const gfx::Rect& aTextureCoords, gfx::Filter aFilter, float aOpacity, SourceSurface *aMask, const Matrix* aMaskTransform) { // Convert aTextureCoords into aSource's coordinate space gfxRect sourceRect(aTextureCoords.x * aSource->GetSize().width, aTextureCoords.y * aSource->GetSize().height, aTextureCoords.width * aSource->GetSize().width, aTextureCoords.height * aSource->GetSize().height); // Floating point error can accumulate above and we know our visible region // is integer-aligned, so round it out. sourceRect.Round(); // Compute a transform that maps sourceRect to aDestRect. Matrix matrix = gfxUtils::TransformRectToRect(sourceRect, gfx::IntPoint(aDestRect.x, aDestRect.y), gfx::IntPoint(aDestRect.XMost(), aDestRect.y), gfx::IntPoint(aDestRect.XMost(), aDestRect.YMost())); // Only use REPEAT if aTextureCoords is outside (0, 0, 1, 1). gfx::Rect unitRect(0, 0, 1, 1); ExtendMode mode = unitRect.Contains(aTextureCoords) ? ExtendMode::CLAMP : ExtendMode::REPEAT; FillRectWithMask(aDest, aDestRect, aSource, aFilter, DrawOptions(aOpacity), mode, aMask, aMaskTransform, &matrix); }
void BrowserBubble::SetAbsoluteBounds(const gfx::Rect& window_bounds) { // Convert screen coordinates to frame relative. gfx::Point relative_origin = window_bounds.origin(); view::View::ConvertPointToView(NULL, frame_->GetRootView(), &relative_origin); SetBounds(relative_origin.x(), relative_origin.y(), window_bounds.width(), window_bounds.height()); }
gfx::Rect CustomFrameView::GetWindowBoundsForClientBounds( const gfx::Rect& client_bounds) const { int top_height = NonClientTopBorderHeight(); int border_thickness = NonClientBorderThickness(); return gfx::Rect(std::max(0, client_bounds.x()-border_thickness), std::max(0, client_bounds.y()-top_height), client_bounds.width()+(2*border_thickness), client_bounds.height()+top_height+border_thickness); }
void AndroidGeckoLayerClient::SetPageRect(const gfx::Rect& aCssPageRect) { NS_ASSERTION(!isNull(), "SetPageRect called on null layer client!"); JNIEnv *env = GetJNIForThread(); // this is called on the compositor thread if (!env) return; AutoLocalJNIFrame jniFrame(env, 0); return env->CallVoidMethod(wrapped_obj, jSetPageRect, aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost()); }
void CompositorD3D9::ClearRect(const gfx::Rect& aRect) { D3DRECT rect; rect.x1 = aRect.X(); rect.y1 = aRect.Y(); rect.x2 = aRect.XMost(); rect.y2 = aRect.YMost(); device()->Clear(1, &rect, D3DCLEAR_TARGET, 0x00000000, 0, 0); }
void Compositor::DrawGeometry(const gfx::Rect& aRect, const gfx::IntRect& aClipRect, const EffectChain& aEffectChain, gfx::Float aOpacity, const gfx::Matrix4x4& aTransform, const gfx::Rect& aVisibleRect, const Maybe<gfx::Polygon3D>& aGeometry) { if (!aGeometry) { DrawQuad(aRect, aClipRect, aEffectChain, aOpacity, aTransform, aVisibleRect); return; } // Cull invisible polygons. if (aRect.Intersect(aGeometry->BoundingBox()).IsEmpty()) { return; } gfx::Polygon3D clipped = aGeometry->ClipPolygon(aRect); nsTArray<gfx::Triangle> triangles = clipped.ToTriangles(); for (gfx::Triangle& geometry : triangles) { const gfx::Rect intersection = aRect.Intersect(geometry.BoundingBox()); // Cull invisible triangles. if (intersection.IsEmpty()) { continue; } MOZ_ASSERT(aRect.width > 0.0f && aRect.height > 0.0f); MOZ_ASSERT(intersection.width > 0.0f && intersection.height > 0.0f); gfx::TexturedTriangle triangle(Move(geometry)); triangle.width = aRect.width; triangle.height = aRect.height; // Since the texture was created for non-split geometry, we need to // update the texture coordinates to account for the split. if (aEffectChain.mPrimaryEffect->mType == EffectTypes::RGB) { TexturedEffect* texturedEffect = static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get()); UpdateTextureCoordinates(triangle, aRect, intersection, texturedEffect->mTextureCoords); } DrawTriangle(triangle, aClipRect, aEffectChain, aOpacity, aTransform, aVisibleRect); } }
void AndroidGeckoLayerClient::SetFirstPaintViewport(const nsIntPoint& aOffset, float aZoom, const nsIntRect& aPageRect, const gfx::Rect& aCssPageRect) { NS_ASSERTION(!isNull(), "SetFirstPaintViewport called on null layer client!"); JNIEnv *env = GetJNIForThread(); // this is called on the compositor thread if (!env) return; AutoLocalJNIFrame jniFrame(env, 0); return env->CallVoidMethod(wrapped_obj, jSetFirstPaintViewport, (float)aOffset.x, (float)aOffset.y, aZoom, (float)aPageRect.x, (float)aPageRect.y, (float)aPageRect.XMost(), (float)aPageRect.YMost(), aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost()); }
bool Rect::SharesEdgeWith(const gfx::Rect& rect) const { return (y()==rect.y() && height()==rect.height() && (x()==rect.right() || right()==rect.x())) || (x()==rect.x() && width()==rect.width() && (y()==rect.bottom() || bottom()==rect.y())); }
void fill_rect(Image* image, const gfx::Rect& rc, color_t c) { gfx::Rect clip = rc.createIntersect(image->bounds()); if (!clip.isEmpty()) image->fillRect(clip.x, clip.y, clip.x+clip.w-1, clip.y+clip.h-1, c); }
void ExtraCel::create(doc::Sprite* sprite, const gfx::Rect& bounds, doc::frame_t frame, int opacity) { ASSERT(sprite); if (!m_image || m_image->pixelFormat() != sprite->pixelFormat() || m_image->width() != bounds.w || m_image->height() != bounds.h) { if (!m_imageBuffer) m_imageBuffer.reset(new doc::ImageBuffer(1)); doc::Image* newImage = doc::Image::create(sprite->pixelFormat(), bounds.w, bounds.h, m_imageBuffer); m_image.reset(newImage); } if (!m_cel) { // Ignored fields for this cel (frame, and image index) m_cel.reset(new doc::Cel(doc::frame_t(0), doc::ImageRef(nullptr))); } m_cel->setPosition(bounds.getOrigin()); m_cel->setOpacity(opacity); m_cel->setFrame(frame); }
ClearRect::ClearRect(Cel* cel, const gfx::Rect& bounds) { app::Document* doc = static_cast<app::Document*>(cel->document()); Image* image = (cel ? cel->image(): NULL); if (!image) return; m_offsetX = bounds.x - cel->x(); m_offsetY = bounds.y - cel->y(); gfx::Rect bounds2 = image->bounds().createIntersection( gfx::Rect( m_offsetX, m_offsetY, bounds.w, bounds.h)); if (bounds.isEmpty()) return; m_dstImage.reset(new WithImage(image)); m_bgcolor = doc->bgColor(cel->layer()); m_copy.reset(crop_image(image, bounds2.x, bounds2.y, bounds2.w, bounds2.h, m_bgcolor)); }
bool CropSpriteCommand::onEnabled(Context* context) { return context->checkFlags( ContextFlags::ActiveDocumentIsWritable | (m_bounds.isEmpty() ? ContextFlags::HasVisibleMask: 0)); }
void Label::PaintText(gfx::Canvas* canvas, const std::wstring& text, const gfx::Rect& text_bounds, int flags) { canvas->DrawStringInt(text, font_, color_, text_bounds.x(), text_bounds.y(), text_bounds.width(), text_bounds.height(), flags); if(HasFocus() || paint_as_focused_) { gfx::Rect focus_bounds = text_bounds; focus_bounds.Inset(-kFocusBorderPadding, -kFocusBorderPadding); canvas->DrawFocusRect(focus_bounds.x(), focus_bounds.y(), focus_bounds.width(), focus_bounds.height()); } }
void Layer::DrawRegion(const ui::TextureDrawParams& params, const gfx::Rect& region_to_draw) { if(!region_to_draw.IsEmpty()) { texture_->Draw(params, region_to_draw); } }
void Graphics::fillAreaBetweenRects(gfx::Color color, const gfx::Rect& outer, const gfx::Rect& inner) { if (!outer.intersects(inner)) fillRect(color, outer); else { gfx::Region rgn(outer); rgn.createSubtraction(rgn, gfx::Region(inner)); fillRegion(color, rgn); } }
Dirty::Dirty(Image* image, Image* image_diff, const gfx::Rect& bounds) : m_format(image->getPixelFormat()) , m_x1(bounds.x), m_y1(bounds.y) , m_x2(bounds.x2()-1), m_y2(bounds.y2()-1) { int y, x1, x2; for (y=m_y1; y<=m_y2; y++) { x1 = m_x1; x2 = m_x2; bool res; switch (image->getPixelFormat()) { case IMAGE_RGB: res = shrink_row<RgbTraits>(image, image_diff, x1, y, x2); break; case IMAGE_GRAYSCALE: res = shrink_row<GrayscaleTraits>(image, image_diff, x1, y, x2); break; case IMAGE_INDEXED: res = shrink_row<IndexedTraits>(image, image_diff, x1, y, x2); break; default: ASSERT(false && "Not implemented for bitmaps"); return; } if (!res) continue; Col* col = new Col(x1, x2-x1+1); col->data.resize(getLineSize(col->w)); Row* row = new Row(y); row->cols.push_back(col); m_rows.push_back(row); } }
void SingleSplitView::DidChangeBounds(const gfx::Rect& previous, const gfx::Rect& current) { if(resize_leading_on_bounds_change_) { // We do not update divider_offset_ on minimize (to zero) and on restore // (to largest value). As a result we get back to the original value upon // window restore. bool is_minimize_or_restore = previous.height()==0 || current.height()==0; if(!is_minimize_or_restore) { if(is_horizontal_) { divider_offset_ += (current.width() - previous.width()) / 2; } else { divider_offset_ += (current.height() - previous.height()) / 2; } if(divider_offset_ < 0) { divider_offset_ = kDividerSize; } } } View::DidChangeBounds(previous, current); }
static void paintArtifactToWebDisplayItemList(WebDisplayItemList* list, const PaintArtifact& artifact, const gfx::Rect& bounds) { if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { // This is a temporary path to paint the artifact using the paint chunk // properties. Ultimately, we should instead split the artifact into // separate layers and send those to the compositor, instead of sending // one big flat SkPicture. SkRect skBounds = SkRect::MakeXYWH(bounds.x(), bounds.y(), bounds.width(), bounds.height()); RefPtr<SkPicture> picture = paintArtifactToSkPicture(artifact, skBounds); list->appendDrawingItem(WebRect(bounds.x(), bounds.y(), bounds.width(), bounds.height()), picture.get()); return; } artifact.appendToWebDisplayItemList(list); }
static void replace_color(Image* image, const gfx::Rect& bounds, int src_color, int tolerance, void *data, AlgoHLine proc) { typename ImageTraits::address_t address; for (int y=bounds.y; y<bounds.y2(); ++y) { address = reinterpret_cast<typename ImageTraits::address_t>(image->getPixelAddress(bounds.x, y)); for (int x=bounds.x; x<bounds.x2(); ++x, ++address) { int right = -1; if (color_equal<ImageTraits>((int)(*address), src_color, tolerance)) { ++address; for (right=x+1; right<bounds.x2(); ++right, ++address) { if (!color_equal<ImageTraits>((int)(*address), src_color, tolerance)) break; } (*proc)(x, y, right-1, data); x = right; } } } }
void BackgroundRule::onPaint(ui::Graphics* g, const gfx::Rect& bounds, const char* text) { SkinTheme* theme = static_cast<SkinTheme*>(ui::CurrentTheme::get()); if (m_part && m_part->countBitmaps() > 0) { if (m_part->countBitmaps() == 1) { if (!gfx::is_transparent(m_color)) g->fillRect(m_color, bounds); she::Surface* bmp = m_part->bitmap(0); if (m_repeat == BackgroundRepeat::NO_REPEAT) { g->drawRgbaSurface(bmp, bounds.x, bounds.y); } else { ui::IntersectClip clip(g, bounds); if (!clip) return; for (int y=bounds.y; y<bounds.y2(); y+=bmp->height()) { for (int x=bounds.x; x<bounds.x2(); x+=bmp->width()) { g->drawRgbaSurface(bmp, x, y); if (m_repeat == BackgroundRepeat::REPEAT_Y) break; } if (m_repeat == BackgroundRepeat::REPEAT_X) break; } } } else if (m_part->countBitmaps() == 8) { theme->drawRect(g, bounds, m_part.get(), m_color); } } else if (!gfx::is_transparent(m_color)) { g->fillRect(m_color, bounds); } }
gfx::Rect GetMonitorBoundsForRect(const gfx::Rect& rect) { RECT p_rect = rect.ToRECT(); HMONITOR monitor = MonitorFromRect(&p_rect, MONITOR_DEFAULTTONEAREST); if(monitor) { MONITORINFO mi = { 0 }; mi.cbSize = sizeof(mi); GetMonitorInfo(monitor, &mi); return gfx::Rect(mi.rcWork); } NOTREACHED(); return gfx::Rect(); }
void CompositorD3D11::ClearRect(const gfx::Rect& aRect) { mContext->OMSetBlendState(mAttachments->mDisabledBlendState, sBlendFactor, 0xFFFFFFFF); Matrix4x4 identity; memcpy(&mVSConstants.layerTransform, &identity._11, 64); mVSConstants.layerQuad = aRect; mVSConstants.renderTargetOffset[0] = 0; mVSConstants.renderTargetOffset[1] = 0; mPSConstants.layerOpacity[0] = 1.0f; D3D11_RECT scissor; scissor.left = aRect.x; scissor.right = aRect.XMost(); scissor.top = aRect.y; scissor.bottom = aRect.YMost(); mContext->RSSetScissorRects(1, &scissor); mContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); mContext->VSSetShader(mAttachments->mVSQuadShader[MaskType::MaskNone], nullptr, 0); mContext->PSSetShader(mAttachments->mSolidColorShader[MaskType::MaskNone], nullptr, 0); mPSConstants.layerColor[0] = 0; mPSConstants.layerColor[1] = 0; mPSConstants.layerColor[2] = 0; mPSConstants.layerColor[3] = 0; if (!UpdateConstantBuffers()) { NS_WARNING("Failed to update shader constant buffers"); return; } mContext->Draw(4, 0); mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF); }
void IconRule::onPaint(ui::Graphics* g, const gfx::Rect& bounds, const char* text) { she::Surface* bmp = m_part->bitmap(0); int x, y; if (m_align & ui::RIGHT) x = bounds.x2() - bmp->width(); else if (m_align & ui::CENTER) x = bounds.x + bounds.w/2 - bmp->width()/2; else x = bounds.x; if (m_align & ui::BOTTOM) y = bounds.y2() - bmp->height(); else if (m_align & ui::MIDDLE) y = bounds.y + bounds.h/2 - bmp->height()/2; else y = bounds.y; x += m_x; y += m_y; g->drawRgbaSurface(bmp, x, y); }
void DesktopWindowManager::UpdateWindowsAfterScreenSizeChanged( const gfx::Rect& new_size) { for(std::vector<Widget*>::iterator i=toplevels_.begin(); i!=toplevels_.end(); ++i) { Widget* toplevel = *i; if(!toplevel->IsMaximized()) { continue; } // If the window is maximized, then resize it! toplevel->SetSize(new_size.size()); } }
void Tabs::drawTab(Graphics* g, const gfx::Rect& box, Tab* tab, int y_delta, bool selected) { // Is the tab outside the bounds of the widget? if (box.x >= getBounds().x2() || box.x2() <= getBounds().x) return; SkinTheme* theme = static_cast<SkinTheme*>(this->getTheme()); gfx::Color text_color; gfx::Color face_color; // Selected if (selected) { text_color = theme->getColor(ThemeColor::TabSelectedText); face_color = theme->getColor(ThemeColor::TabSelectedFace); } // Non-selected else { text_color = theme->getColor(ThemeColor::TabNormalText); face_color = theme->getColor(ThemeColor::TabNormalFace); } if (box.w > 2) { theme->draw_bounds_nw(g, gfx::Rect(box.x, box.y+y_delta, box.w, box.h), (selected) ? PART_TAB_SELECTED_NW: PART_TAB_NORMAL_NW, face_color); g->drawString(tab->text, text_color, gfx::ColorNone, gfx::Point( box.x + 4*jguiscale(), box.y + box.h/2 - getFont()->height()/2+1 + y_delta)); } if (selected) { theme->draw_bounds_nw(g, gfx::Rect(box.x, box.y2(), box.w, getBounds().y2()-box.y2()), PART_TAB_BOTTOM_SELECTED_NW, theme->getColor(ThemeColor::TabSelectedFace)); } else { theme->draw_part_as_hline(g, gfx::Rect(box.x, box.y2(), box.w, getBounds().y2()-box.y2()), PART_TAB_BOTTOM_NORMAL); } #ifdef CLOSE_BUTTON_IN_EACH_TAB she::Surface* close_icon = theme->get_part(PART_WINDOW_CLOSE_BUTTON_NORMAL); g->drawRgbaSurface(close_icon, box.x2() - 4*jguiscale() - close_icon->width(), box.y + box.h/2 - close_icon->height()/2+1 * jguiscale()); #endif }
bool VRDisplayOpenVR::SubmitFrame(void* aTextureHandle, ::vr::ETextureType aTextureType, const IntSize& aSize, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect) { MOZ_ASSERT(mSubmitThread->GetThread() == NS_GetCurrentThread()); if (!mIsPresenting) { return false; } ::vr::Texture_t tex; tex.handle = aTextureHandle; tex.eType = aTextureType; tex.eColorSpace = ::vr::EColorSpace::ColorSpace_Auto; ::vr::VRTextureBounds_t bounds; bounds.uMin = aLeftEyeRect.X(); bounds.vMin = 1.0 - aLeftEyeRect.Y(); bounds.uMax = aLeftEyeRect.XMost(); bounds.vMax = 1.0 - aLeftEyeRect.YMost(); ::vr::EVRCompositorError err; err = mVRCompositor->Submit(::vr::EVREye::Eye_Left, &tex, &bounds); if (err != ::vr::EVRCompositorError::VRCompositorError_None) { printf_stderr("OpenVR Compositor Submit() failed.\n"); } bounds.uMin = aRightEyeRect.X(); bounds.vMin = 1.0 - aRightEyeRect.Y(); bounds.uMax = aRightEyeRect.XMost(); bounds.vMax = 1.0 - aRightEyeRect.YMost(); err = mVRCompositor->Submit(::vr::EVREye::Eye_Right, &tex, &bounds); if (err != ::vr::EVRCompositorError::VRCompositorError_None) { printf_stderr("OpenVR Compositor Submit() failed.\n"); } mVRCompositor->PostPresentHandoff(); return true; }
void Document::prepareExtraCel(const gfx::Rect& bounds, int opacity) { ASSERT(sprite() != NULL); if (!m_extraImage || m_extraImage->pixelFormat() != sprite()->pixelFormat() || m_extraImage->width() != bounds.w || m_extraImage->height() != bounds.h) { Image* newImage = Image::create(sprite()->pixelFormat(), bounds.w, bounds.h); m_extraImage.reset(newImage); } if (!m_extraCel) m_extraCel = new Cel(frame_t(0), ImageRef(NULL)); // Ignored fields for this cel (frame, and image index) m_extraCel->setPosition(bounds.getOrigin()); m_extraCel->setOpacity(opacity); }
void BrushPopup::regenerate(const gfx::Rect& box) { auto& brushSlots = App::instance()->brushes().getBrushSlots(); if (m_customBrushes) { // As BrushPopup::regenerate() can be called when a // "m_customBrushes" button is clicked we cannot delete // "m_customBrushes" right now. m_customBrushes->parent()->removeChild(m_customBrushes); m_customBrushes->deferDelete(); } m_customBrushes = new ButtonSet(3); m_customBrushes->setTriggerOnMouseUp(true); int slot = 0; for (const auto& brush : brushSlots) { ++slot; // Get shortcut std::string shortcut; { Params params; params.set("change", "custom"); params.set("slot", base::convert_to<std::string>(slot).c_str()); Key* key = KeyboardShortcuts::instance()->command( CommandId::ChangeBrush, params); if (key && !key->accels().empty()) shortcut = key->accels().front().toString(); } m_customBrushes->addItem(new SelectBrushItem(brush, slot)); m_customBrushes->addItem(new BrushShortcutItem(shortcut, slot)); m_customBrushes->addItem(new BrushOptionsItem(this, slot)); } m_customBrushes->addItem(new NewCustomBrushItem, 2, 1); m_customBrushes->addItem(new NewBrushOptionsItem); m_customBrushes->setExpansive(true); m_box.addChild(m_customBrushes); // Resize the window and change the hot region. setBounds(gfx::Rect(box.origin(), sizeHint())); setHotRegion(gfx::Region(bounds())); }