void nsShmImage::Put(const mozilla::LayoutDeviceIntRegion& aRegion) { AutoTArray<xcb_rectangle_t, 32> xrects; xrects.SetCapacity(aRegion.GetNumRects()); for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) { const mozilla::LayoutDeviceIntRect &r = iter.Get(); xcb_rectangle_t xrect = { (short)r.x, (short)r.y, (unsigned short)r.width, (unsigned short)r.height }; xrects.AppendElement(xrect); } if (!mGC) { mGC = xcb_generate_id(mConnection); xcb_create_gc(mConnection, mGC, mWindow, 0, nullptr); } xcb_set_clip_rectangles(mConnection, XCB_CLIP_ORDERING_YX_BANDED, mGC, 0, 0, xrects.Length(), xrects.Elements()); if (mPixmap != XCB_NONE) { mLastRequest = xcb_copy_area_checked(mConnection, mPixmap, mWindow, mGC, 0, 0, 0, 0, mSize.width, mSize.height); } else { mLastRequest = xcb_shm_put_image_checked(mConnection, mWindow, mGC, mSize.width, mSize.height, 0, 0, mSize.width, mSize.height, 0, 0, mDepth, XCB_IMAGE_FORMAT_Z_PIXMAP, 0, mShmSeg, 0); } xcb_flush(mConnection); }
already_AddRefed<Promise> Cache::AddAll(const GlobalObject& aGlobal, nsTArray<RefPtr<Request>>&& aRequestList, CallerType aCallerType, ErrorResult& aRv) { MOZ_DIAGNOSTIC_ASSERT(mActor); // If there is no work to do, then resolve immediately if (aRequestList.IsEmpty()) { RefPtr<Promise> promise = Promise::Create(mGlobal, aRv); if (NS_WARN_IF(!promise)) { return nullptr; } promise->MaybeResolveWithUndefined(); return promise.forget(); } AutoTArray<RefPtr<Promise>, 256> fetchList; fetchList.SetCapacity(aRequestList.Length()); // Begin fetching each request in parallel. For now, if an error occurs just // abandon our previous fetch calls. In theory we could cancel them in the // future once fetch supports it. for (uint32_t i = 0; i < aRequestList.Length(); ++i) { RequestOrUSVString requestOrString; requestOrString.SetAsRequest() = aRequestList[i]; RefPtr<Promise> fetch = FetchRequest(mGlobal, requestOrString, RequestInit(), aCallerType, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } fetchList.AppendElement(std::move(fetch)); } RefPtr<Promise> promise = Promise::Create(mGlobal, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } RefPtr<FetchHandler> handler = new FetchHandler(mActor->GetWorkerHolder(), this, std::move(aRequestList), promise); RefPtr<Promise> fetchPromise = Promise::All(aGlobal.Context(), fetchList, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } fetchPromise->AppendNativeHandler(handler); return promise.forget(); }
void CacheOpChild::HandleRequestList( const nsTArray<CacheRequest>& aRequestList) { AutoTArray<RefPtr<Request>, 256> requests; requests.SetCapacity(aRequestList.Length()); for (uint32_t i = 0; i < aRequestList.Length(); ++i) { AddWorkerHolderToStreamChild(aRequestList[i], GetWorkerHolder()); requests.AppendElement(ToRequest(aRequestList[i])); } mPromise->MaybeResolve(requests); }
void CacheOpChild::HandleResponseList(const nsTArray<CacheResponse>& aResponseList) { AutoTArray<RefPtr<Response>, 256> responses; responses.SetCapacity(aResponseList.Length()); for (uint32_t i = 0; i < aResponseList.Length(); ++i) { AddFeatureToStreamChild(aResponseList[i], GetFeature()); responses.AppendElement(ToResponse(aResponseList[i])); } mPromise->MaybeResolve(responses); }
void nsShmImage::Put(const mozilla::LayoutDeviceIntRegion& aRegion) { AutoTArray<xcb_rectangle_t, 32> xrects; xrects.SetCapacity(aRegion.GetNumRects()); for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) { const mozilla::LayoutDeviceIntRect &r = iter.Get(); xcb_rectangle_t xrect = { (short)r.x, (short)r.y, (unsigned short)r.width, (unsigned short)r.height }; xrects.AppendElement(xrect); } if (!mGC) { mGC = xcb_generate_id(mConnection); xcb_create_gc(mConnection, mGC, mWindow, 0, nullptr); } xcb_set_clip_rectangles(mConnection, XCB_CLIP_ORDERING_YX_BANDED, mGC, 0, 0, xrects.Length(), xrects.Elements()); if (mPixmap != XCB_NONE) { mPutRequest = xcb_copy_area_checked(mConnection, mPixmap, mWindow, mGC, 0, 0, 0, 0, mSize.width, mSize.height); } else { mPutRequest = xcb_shm_put_image_checked(mConnection, mWindow, mGC, mSize.width, mSize.height, 0, 0, mSize.width, mSize.height, 0, 0, mDepth, XCB_IMAGE_FORMAT_Z_PIXMAP, 0, mShmSeg, 0); } // Send a request that returns a response so that we don't have to start a // sync in nsShmImage::CreateDrawTarget to retrieve the result of mPutRequest. mSyncRequest = xcb_get_input_focus(mConnection); mRequestPending = true; xcb_flush(mConnection); }
void nsRegion::SimplifyOutwardByArea(uint32_t aThreshold) { pixman_box32_t *boxes; int n; boxes = pixman_region32_rectangles(&mImpl, &n); // if we have no rectangles then we're done if (!n) return; pixman_box32_t *end = boxes + n; pixman_box32_t *topRectsEnd = boxes+1; pixman_box32_t *topRects = boxes; // we need some temporary storage for merging both rows of rectangles AutoTArray<pixman_box32_t, 10> tmpStorage; tmpStorage.SetCapacity(n); pixman_box32_t *tmpRect = tmpStorage.Elements(); pixman_box32_t *destRect = boxes; pixman_box32_t *rect = tmpRect; // find the end of the first span of rectangles while (topRectsEnd < end && topRectsEnd->y1 == topRects->y1) { topRectsEnd++; } // if we only have one row we are done if (topRectsEnd == end) return; pixman_box32_t *bottomRects = topRectsEnd; pixman_box32_t *bottomRectsEnd = bottomRects+1; do { // find the end of the bottom span of rectangles while (bottomRectsEnd < end && bottomRectsEnd->y1 == bottomRects->y1) { bottomRectsEnd++; } uint32_t totalArea = ComputeMergedAreaIncrease(topRects, topRectsEnd, bottomRects, bottomRectsEnd); if (totalArea <= aThreshold) { // merge the rects into tmpRect rect = MergeRects(topRects, topRectsEnd, bottomRects, bottomRectsEnd, tmpRect); // set topRects to where the newly merged rects will be so that we use them // as our next set of topRects topRects = destRect; // copy the merged rects back into the destination topRectsEnd = CopyRow(destRect, tmpRect, rect); } else { // copy the unmerged rects destRect = CopyRow(destRect, topRects, topRectsEnd); topRects = bottomRects; topRectsEnd = bottomRectsEnd; if (bottomRectsEnd == end) { // copy the last row when we are done topRectsEnd = CopyRow(destRect, topRects, topRectsEnd); } } bottomRects = bottomRectsEnd; } while (bottomRectsEnd != end); uint32_t reducedCount = topRectsEnd - pixman_region32_rectangles(&this->mImpl, &n); // pixman has a special representation for // regions of 1 rectangle. So just use the // bounds in that case if (reducedCount > 1) { // reach into pixman and lower the number // of rects stored in data. this->mImpl.data->numRects = reducedCount; } else { *this = GetBounds(); } }
/* virtual */ void nsRubyBaseContainerFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsRubyBaseContainerFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); aStatus = NS_FRAME_COMPLETE; if (!aReflowState.mLineLayout) { NS_ASSERTION( aReflowState.mLineLayout, "No line layout provided to RubyBaseContainerFrame reflow method."); return; } MoveOverflowToChildList(); // Ask text containers to drain overflows AutoRubyTextContainerArray textContainers(this); const uint32_t rtcCount = textContainers.Length(); for (uint32_t i = 0; i < rtcCount; i++) { textContainers[i]->MoveOverflowToChildList(); } WritingMode lineWM = aReflowState.mLineLayout->GetWritingMode(); LogicalSize availSize(lineWM, aReflowState.AvailableISize(), aReflowState.AvailableBSize()); // We have a reflow state and a line layout for each RTC. // They are conceptually the state of the RTCs, but we don't actually // reflow those RTCs in this code. These two arrays are holders of // the reflow states and line layouts. // Since there are pointers refer to reflow states and line layouts, // it is necessary to guarantee that they won't be moved. For this // reason, they are wrapped in UniquePtr here. AutoTArray<UniquePtr<nsHTMLReflowState>, RTC_ARRAY_SIZE> reflowStates; AutoTArray<UniquePtr<nsLineLayout>, RTC_ARRAY_SIZE> lineLayouts; reflowStates.SetCapacity(rtcCount); lineLayouts.SetCapacity(rtcCount); // Begin the line layout for each ruby text container in advance. bool hasSpan = false; for (uint32_t i = 0; i < rtcCount; i++) { nsRubyTextContainerFrame* textContainer = textContainers[i]; if (textContainer->IsSpanContainer()) { hasSpan = true; } nsHTMLReflowState* reflowState = new nsHTMLReflowState( aPresContext, *aReflowState.mParentReflowState, textContainer, availSize.ConvertTo(textContainer->GetWritingMode(), lineWM)); reflowStates.AppendElement(reflowState); nsLineLayout* lineLayout = new nsLineLayout(aPresContext, reflowState->mFloatManager, reflowState, nullptr, aReflowState.mLineLayout); lineLayout->SetSuppressLineWrap(true); lineLayouts.AppendElement(lineLayout); // Line number is useless for ruby text // XXX nullptr here may cause problem, see comments for // nsLineLayout::mBlockRS and nsLineLayout::AddFloat lineLayout->Init(nullptr, reflowState->CalcLineHeight(), -1); reflowState->mLineLayout = lineLayout; // Border and padding are suppressed on ruby text containers. // If the writing mode is vertical-rl, the horizontal position of // rt frames will be updated when reflowing this text container, // hence leave container size 0 here for now. lineLayout->BeginLineReflow(0, 0, reflowState->ComputedISize(), NS_UNCONSTRAINEDSIZE, false, false, lineWM, nsSize(0, 0)); lineLayout->AttachRootFrameToBaseLineLayout(); } aReflowState.mLineLayout->BeginSpan(this, &aReflowState, 0, aReflowState.AvailableISize(), &mBaseline); bool allowInitialLineBreak, allowLineBreak; GetIsLineBreakAllowed(this, aReflowState.mLineLayout->LineIsBreakable(), &allowInitialLineBreak, &allowLineBreak); nscoord isize = 0; // Reflow columns excluding any span ReflowState reflowState = { allowInitialLineBreak, allowLineBreak && !hasSpan, textContainers, aReflowState, reflowStates }; isize = ReflowColumns(reflowState, aStatus); DebugOnly<nscoord> lineSpanSize = aReflowState.mLineLayout->EndSpan(this); aDesiredSize.ISize(lineWM) = isize; // When there are no frames inside the ruby base container, EndSpan // will return 0. However, in this case, the actual width of the // container could be non-zero because of non-empty ruby annotations. // XXX When bug 765861 gets fixed, this warning should be upgraded. NS_WARN_IF_FALSE(NS_INLINE_IS_BREAK(aStatus) || isize == lineSpanSize || mFrames.IsEmpty(), "bad isize"); // If there exists any span, the columns must either be completely // reflowed, or be not reflowed at all. MOZ_ASSERT(NS_INLINE_IS_BREAK_BEFORE(aStatus) || NS_FRAME_IS_COMPLETE(aStatus) || !hasSpan); if (!NS_INLINE_IS_BREAK_BEFORE(aStatus) && NS_FRAME_IS_COMPLETE(aStatus) && hasSpan) { // Reflow spans ReflowState reflowState = { false, false, textContainers, aReflowState, reflowStates }; nscoord spanISize = ReflowSpans(reflowState); isize = std::max(isize, spanISize); } for (uint32_t i = 0; i < rtcCount; i++) { // It happens before the ruby text container is reflowed, and that // when it is reflowed, it will just use this size. nsRubyTextContainerFrame* textContainer = textContainers[i]; nsLineLayout* lineLayout = lineLayouts[i].get(); RubyUtils::ClearReservedISize(textContainer); nscoord rtcISize = lineLayout->GetCurrentICoord(); // Only span containers and containers with collapsed annotations // need reserving isize. For normal ruby text containers, their // children will be expanded properly. We only need to expand their // own size. if (!textContainer->IsSpanContainer()) { rtcISize = isize; } else if (isize > rtcISize) { RubyUtils::SetReservedISize(textContainer, isize - rtcISize); } lineLayout->VerticalAlignLine(); textContainer->SetISize(rtcISize); lineLayout->EndLineReflow(); } // Border and padding are suppressed on ruby base container, // create a fake borderPadding for setting BSize. WritingMode frameWM = aReflowState.GetWritingMode(); LogicalMargin borderPadding(frameWM); nsLayoutUtils::SetBSizeFromFontMetrics(this, aDesiredSize, borderPadding, lineWM, frameWM); }