本文整理汇总了C++中AutoTArray::IsEmpty方法的典型用法代码示例。如果您正苦于以下问题:C++ AutoTArray::IsEmpty方法的具体用法?C++ AutoTArray::IsEmpty怎么用?C++ AutoTArray::IsEmpty使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类AutoTArray
的用法示例。
在下文中一共展示了AutoTArray::IsEmpty方法的11个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: lists
/* static */ void
nsFontFaceUtils::MarkDirtyForFontChange(nsIFrame* aSubtreeRoot,
const gfxUserFontEntry* aFont)
{
AutoTArray<nsIFrame*, 4> subtrees;
subtrees.AppendElement(aSubtreeRoot);
nsIPresShell* ps = aSubtreeRoot->PresContext()->PresShell();
// check descendants, iterating over subtrees that may include
// additional subtrees associated with placeholders
do {
nsIFrame* subtreeRoot = subtrees.ElementAt(subtrees.Length() - 1);
subtrees.RemoveElementAt(subtrees.Length() - 1);
// Check all descendants to see if they use the font
AutoTArray<nsIFrame*, 32> stack;
stack.AppendElement(subtreeRoot);
do {
nsIFrame* f = stack.ElementAt(stack.Length() - 1);
stack.RemoveElementAt(stack.Length() - 1);
// if this frame uses the font, mark its descendants dirty
// and skip checking its children
if (FrameUsesFont(f, aFont)) {
ScheduleReflow(ps, f);
} else {
if (f->GetType() == nsGkAtoms::placeholderFrame) {
nsIFrame* oof = nsPlaceholderFrame::GetRealFrameForPlaceholder(f);
if (!nsLayoutUtils::IsProperAncestorFrame(subtreeRoot, oof)) {
// We have another distinct subtree we need to mark.
subtrees.AppendElement(oof);
}
}
nsIFrame::ChildListIterator lists(f);
for (; !lists.IsDone(); lists.Next()) {
nsFrameList::Enumerator childFrames(lists.CurrentList());
for (; !childFrames.AtEnd(); childFrames.Next()) {
nsIFrame* kid = childFrames.get();
stack.AppendElement(kid);
}
}
}
} while (!stack.IsEmpty());
} while (!subtrees.IsEmpty());
}
示例2: Share
/* static */ nsresult
SharedSurfacesChild::Share(ImageContainer* aContainer,
WebRenderLayerManager* aManager,
wr::IpcResourceUpdateQueue& aResources,
wr::ImageKey& aKey)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aContainer);
MOZ_ASSERT(aManager);
if (aContainer->IsAsync()) {
return NS_ERROR_NOT_IMPLEMENTED;
}
AutoTArray<ImageContainer::OwningImage,4> images;
aContainer->GetCurrentImages(&images);
if (images.IsEmpty()) {
return NS_ERROR_NOT_AVAILABLE;
}
RefPtr<gfx::SourceSurface> surface = images[0].mImage->GetAsSourceSurface();
if (!surface) {
return NS_ERROR_NOT_IMPLEMENTED;
}
if (surface->GetType() != SurfaceType::DATA_SHARED) {
return NS_ERROR_NOT_IMPLEMENTED;
}
auto sharedSurface = static_cast<SourceSurfaceSharedData*>(surface.get());
return Share(sharedSurface, aManager, aResources, aKey);
}
示例3: AssertOwnerThread
void
VideoSink::RenderVideoFrames(int32_t aMaxFrames,
int64_t aClockTime,
const TimeStamp& aClockTimeStamp)
{
AssertOwnerThread();
AutoTArray<RefPtr<MediaData>,16> frames;
VideoQueue().GetFirstElements(aMaxFrames, &frames);
if (frames.IsEmpty() || !mContainer) {
return;
}
AutoTArray<ImageContainer::NonOwningImage,16> images;
TimeStamp lastFrameTime;
MediaSink::PlaybackParams params = mAudioSink->GetPlaybackParams();
for (uint32_t i = 0; i < frames.Length(); ++i) {
VideoData* frame = frames[i]->As<VideoData>();
frame->mSentToCompositor = true;
if (!frame->mImage || !frame->mImage->IsValid() ||
!frame->mImage->GetSize().width || !frame->mImage->GetSize().height) {
continue;
}
int64_t frameTime = frame->mTime;
if (frameTime < 0) {
// Frame times before the start time are invalid; drop such frames
continue;
}
TimeStamp t;
if (aMaxFrames > 1) {
MOZ_ASSERT(!aClockTimeStamp.IsNull());
int64_t delta = frame->mTime - aClockTime;
t = aClockTimeStamp +
TimeDuration::FromMicroseconds(delta / params.mPlaybackRate);
if (!lastFrameTime.IsNull() && t <= lastFrameTime) {
// Timestamps out of order; drop the new frame. In theory we should
// probably replace the previous frame with the new frame if the
// timestamps are equal, but this is a corrupt video file already so
// never mind.
continue;
}
lastFrameTime = t;
}
ImageContainer::NonOwningImage* img = images.AppendElement();
img->mTimeStamp = t;
img->mImage = frame->mImage;
img->mFrameID = frame->mFrameID;
img->mProducerID = mProducerID;
VSINK_LOG_V("playing video frame %lld (id=%x) (vq-queued=%i)",
frame->mTime, frame->mFrameID, VideoQueue().GetSize());
}
mContainer->SetCurrentFrames(frames[0]->As<VideoData>()->mDisplay, images);
}
示例4: tagStr
NS_IMETHODIMP
RDFContentSinkImpl::HandleEndElement(const char16_t *aName)
{
FlushText();
nsIRDFResource* resource;
if (NS_FAILED(PopContext(resource, mState, mParseMode))) {
// XXX parser didn't catch unmatched tags?
if (MOZ_LOG_TEST(gLog, LogLevel::Warning)) {
nsAutoString tagStr(aName);
char* tagCStr = ToNewCString(tagStr);
PR_LogPrint
("rdfxml: extra close tag '%s' at line %d",
tagCStr, 0/*XXX fix me */);
free(tagCStr);
}
return NS_ERROR_UNEXPECTED; // XXX
}
// If we've just popped a member or property element, _now_ is the
// time to add that element to the graph.
switch (mState) {
case eRDFContentSinkState_InMemberElement:
{
nsCOMPtr<nsIRDFContainer> container;
NS_NewRDFContainer(getter_AddRefs(container));
container->Init(mDataSource, GetContextElement(1));
container->AppendElement(resource);
}
break;
case eRDFContentSinkState_InPropertyElement:
{
mDataSource->Assert(GetContextElement(1), GetContextElement(0), resource, true);
}
break;
default:
break;
}
if (mContextStack->IsEmpty())
mState = eRDFContentSinkState_InEpilog;
NS_IF_RELEASE(resource);
return NS_OK;
}
示例5: switch
already_AddRefed<InternalResponse>
FetchDriver::BeginAndGetFilteredResponse(InternalResponse* aResponse,
bool aFoundOpaqueRedirect)
{
MOZ_ASSERT(aResponse);
AutoTArray<nsCString, 4> reqURLList;
mRequest->GetURLListWithoutFragment(reqURLList);
MOZ_ASSERT(!reqURLList.IsEmpty());
aResponse->SetURLList(reqURLList);
RefPtr<InternalResponse> filteredResponse;
if (aFoundOpaqueRedirect) {
filteredResponse = aResponse->OpaqueRedirectResponse();
} else {
switch (mRequest->GetResponseTainting()) {
case LoadTainting::Basic:
filteredResponse = aResponse->BasicResponse();
break;
case LoadTainting::CORS:
filteredResponse = aResponse->CORSResponse();
break;
case LoadTainting::Opaque: {
filteredResponse = aResponse->OpaqueResponse();
nsresult rv = filteredResponse->GeneratePaddingInfo();
if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; }
break;
}
default:
MOZ_CRASH("Unexpected case");
}
}
MOZ_ASSERT(filteredResponse);
MOZ_ASSERT(mObserver);
if (!ShouldCheckSRI(mRequest, filteredResponse)) {
mObserver->OnResponseAvailable(filteredResponse);
#ifdef DEBUG
mResponseAvailableCalled = true;
#endif
}
return filteredResponse.forget();
}
示例6: handle
bool
ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags)
{
AutoTArray<ImageContainer::OwningImage,4> images;
uint32_t generationCounter;
aContainer->GetCurrentImages(&images, &generationCounter);
if (mLastUpdateGenerationCounter == generationCounter) {
return true;
}
mLastUpdateGenerationCounter = generationCounter;
for (int32_t i = images.Length() - 1; i >= 0; --i) {
if (!images[i].mImage->IsValid()) {
// Don't try to update to an invalid image.
images.RemoveElementAt(i);
}
}
if (images.IsEmpty()) {
// This can happen if a ClearAllImages raced with SetCurrentImages from
// another thread and ClearImagesFromImageBridge ran after the
// SetCurrentImages call but before UpdateImageClientNow.
// This can also happen if all images in the list are invalid.
// We return true because the caller would attempt to recreate the
// ImageClient otherwise, and that isn't going to help.
return true;
}
nsTArray<Buffer> newBuffers;
AutoTArray<CompositableForwarder::TimedTextureClient,4> textures;
for (auto& img : images) {
Image* image = img.mImage;
#ifdef MOZ_WIDGET_GONK
if (image->GetFormat() == ImageFormat::OVERLAY_IMAGE) {
OverlayImage* overlayImage = static_cast<OverlayImage*>(image);
OverlaySource source;
if (overlayImage->GetSidebandStream().IsValid()) {
// Duplicate GonkNativeHandle::NhObj for ipc,
// since ParamTraits<GonkNativeHandle>::Write() absorbs native_handle_t.
RefPtr<GonkNativeHandle::NhObj> nhObj = overlayImage->GetSidebandStream().GetDupNhObj();
GonkNativeHandle handle(nhObj);
if (!handle.IsValid()) {
gfxWarning() << "ImageClientSingle::UpdateImage failed in GetDupNhObj";
return false;
}
source.handle() = OverlayHandle(handle);
} else {
source.handle() = OverlayHandle(overlayImage->GetOverlayId());
}
source.size() = overlayImage->GetSize();
GetForwarder()->UseOverlaySource(this, source, image->GetPictureRect());
continue;
}
#endif
RefPtr<TextureClient> texture = image->GetTextureClient(this);
const bool hasTextureClient = !!texture;
for (int32_t i = mBuffers.Length() - 1; i >= 0; --i) {
if (mBuffers[i].mImageSerial == image->GetSerial()) {
if (hasTextureClient) {
MOZ_ASSERT(image->GetTextureClient(this) == mBuffers[i].mTextureClient);
} else {
texture = mBuffers[i].mTextureClient;
}
// Remove this element from mBuffers so mBuffers only contains
// images that aren't present in 'images'
mBuffers.RemoveElementAt(i);
}
}
if (!texture) {
// Slow path, we should not be hitting it very often and if we do it means
// we are using an Image class that is not backed by textureClient and we
// should fix it.
if (image->GetFormat() == ImageFormat::PLANAR_YCBCR) {
PlanarYCbCrImage* ycbcr = static_cast<PlanarYCbCrImage*>(image);
const PlanarYCbCrData* data = ycbcr->GetData();
if (!data) {
return false;
}
texture = TextureClient::CreateForYCbCr(GetForwarder(),
data->mYSize, data->mCbCrSize, data->mStereoMode,
TextureFlags::DEFAULT | mTextureFlags
);
if (!texture) {
return false;
}
TextureClientAutoLock autoLock(texture, OpenMode::OPEN_WRITE_ONLY);
if (!autoLock.Succeeded()) {
return false;
}
bool status = UpdateYCbCrTextureClient(texture, *data);
MOZ_ASSERT(status);
if (!status) {
return false;
//.........这里部分代码省略.........
示例7: RemoveTexture
bool
ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags)
{
AutoTArray<ImageContainer::OwningImage,4> images;
uint32_t generationCounter;
aContainer->GetCurrentImages(&images, &generationCounter);
if (mLastUpdateGenerationCounter == generationCounter) {
return true;
}
mLastUpdateGenerationCounter = generationCounter;
for (int32_t i = images.Length() - 1; i >= 0; --i) {
if (!images[i].mImage->IsValid()) {
// Don't try to update to an invalid image.
images.RemoveElementAt(i);
}
}
if (images.IsEmpty()) {
// This can happen if a ClearAllImages raced with SetCurrentImages from
// another thread and ClearImagesFromImageBridge ran after the
// SetCurrentImages call but before UpdateImageClientNow.
// This can also happen if all images in the list are invalid.
// We return true because the caller would attempt to recreate the
// ImageClient otherwise, and that isn't going to help.
for (auto& b : mBuffers) {
RemoveTexture(b.mTextureClient);
}
mBuffers.Clear();
return true;
}
nsTArray<Buffer> newBuffers;
AutoTArray<CompositableForwarder::TimedTextureClient,4> textures;
for (auto& img : images) {
Image* image = img.mImage;
RefPtr<TextureClient> texture = image->GetTextureClient(GetForwarder());
const bool hasTextureClient = !!texture;
for (int32_t i = mBuffers.Length() - 1; i >= 0; --i) {
if (mBuffers[i].mImageSerial == image->GetSerial()) {
if (hasTextureClient) {
MOZ_ASSERT(image->GetTextureClient(GetForwarder()) == mBuffers[i].mTextureClient);
} else {
texture = mBuffers[i].mTextureClient;
}
// Remove this element from mBuffers so mBuffers only contains
// images that aren't present in 'images'
mBuffers.RemoveElementAt(i);
}
}
if (!texture) {
// Slow path, we should not be hitting it very often and if we do it means
// we are using an Image class that is not backed by textureClient and we
// should fix it.
texture = CreateTextureClientForImage(image, GetForwarder());
}
if (!texture) {
return false;
}
// We check if the texture's allocator is still open, since in between media
// decoding a frame and adding it to the compositable, we could have
// restarted the GPU process.
if (!texture->GetAllocator()->IPCOpen()) {
continue;
}
if (!AddTextureClient(texture)) {
return false;
}
CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
t->mTextureClient = texture;
t->mTimeStamp = img.mTimeStamp;
t->mPictureRect = image->GetPictureRect();
t->mFrameID = img.mFrameID;
t->mProducerID = img.mProducerID;
Buffer* newBuf = newBuffers.AppendElement();
newBuf->mImageSerial = image->GetSerial();
newBuf->mTextureClient = texture;
texture->SyncWithObject(GetForwarder()->GetSyncObject());
}
GetForwarder()->UseTextures(this, textures);
for (auto& b : mBuffers) {
RemoveTexture(b.mTextureClient);
}
mBuffers.SwapElements(newBuffers);
return true;
}
示例8: do_QueryFrame
nsMenuFrame*
nsMenuBarFrame::FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent)
{
uint32_t charCode;
aKeyEvent->GetCharCode(&charCode);
AutoTArray<uint32_t, 10> accessKeys;
WidgetKeyboardEvent* nativeKeyEvent =
aKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
if (nativeKeyEvent) {
nativeKeyEvent->GetAccessKeyCandidates(accessKeys);
}
if (accessKeys.IsEmpty() && charCode)
accessKeys.AppendElement(charCode);
if (accessKeys.IsEmpty())
return nullptr; // no character was pressed so just return
// Enumerate over our list of frames.
auto insertion = PresContext()->PresShell()->FrameConstructor()->
GetInsertionPoint(GetContent(), nullptr);
nsContainerFrame* immediateParent = insertion.mParentFrame;
if (!immediateParent)
immediateParent = this;
// Find a most preferred accesskey which should be returned.
nsIFrame* foundMenu = nullptr;
size_t foundIndex = accessKeys.NoIndex;
nsIFrame* currFrame = immediateParent->PrincipalChildList().FirstChild();
while (currFrame) {
nsIContent* current = currFrame->GetContent();
// See if it's a menu item.
if (nsXULPopupManager::IsValidMenuItem(current, false)) {
// Get the shortcut attribute.
nsAutoString shortcutKey;
current->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, shortcutKey);
if (!shortcutKey.IsEmpty()) {
ToLowerCase(shortcutKey);
const char16_t* start = shortcutKey.BeginReading();
const char16_t* end = shortcutKey.EndReading();
uint32_t ch = UTF16CharEnumerator::NextChar(&start, end);
size_t index = accessKeys.IndexOf(ch);
if (index != accessKeys.NoIndex &&
(foundIndex == accessKeys.NoIndex || index < foundIndex)) {
foundMenu = currFrame;
foundIndex = index;
}
}
}
currFrame = currFrame->GetNextSibling();
}
if (foundMenu) {
return do_QueryFrame(foundMenu);
}
// didn't find a matching menu item
#ifdef XP_WIN
// behavior on Windows - this item is on the menu bar, beep and deactivate the menu bar
if (mIsActive) {
nsCOMPtr<nsISound> soundInterface = do_CreateInstance("@mozilla.org/sound;1");
if (soundInterface)
soundInterface->Beep();
}
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
if (pm) {
nsIFrame* popup = pm->GetTopPopup(ePopupTypeAny);
if (popup)
pm->HidePopup(popup->GetContent(), true, true, true, false);
}
SetCurrentMenuItem(nullptr);
SetActive(false);
#endif // #ifdef XP_WIN
return nullptr;
}
示例9: SetCurrentFrames
void VideoFrameContainer::SetCurrentFrames(const VideoSegment& aSegment)
{
if (aSegment.IsEmpty()) {
return;
}
MutexAutoLock lock(mMutex);
// Collect any new frames produced in this iteration.
AutoTArray<ImageContainer::NonOwningImage,4> newImages;
PrincipalHandle lastPrincipalHandle = PRINCIPAL_HANDLE_NONE;
VideoSegment::ConstChunkIterator iter(aSegment);
while (!iter.IsEnded()) {
VideoChunk chunk = *iter;
const VideoFrame* frame = &chunk.mFrame;
if (*frame == mLastPlayedVideoFrame) {
iter.Next();
continue;
}
Image* image = frame->GetImage();
CONTAINER_LOG(LogLevel::Verbose,
("VideoFrameContainer %p writing video frame %p (%d x %d)",
this, image, frame->GetIntrinsicSize().width,
frame->GetIntrinsicSize().height));
if (frame->GetForceBlack()) {
if (!mBlackImage) {
mBlackImage = GetImageContainer()->CreatePlanarYCbCrImage();
if (mBlackImage) {
// Sets the image to a single black pixel, which will be scaled to
// fill the rendered size.
SetImageToBlackPixel(mBlackImage->AsPlanarYCbCrImage());
}
}
if (mBlackImage) {
image = mBlackImage;
}
}
// Don't append null image to the newImages.
if (!image) {
iter.Next();
continue;
}
newImages.AppendElement(ImageContainer::NonOwningImage(image, chunk.mTimeStamp));
lastPrincipalHandle = chunk.GetPrincipalHandle();
mLastPlayedVideoFrame = *frame;
iter.Next();
}
// Don't update if there are no changes.
if (newImages.IsEmpty()) {
return;
}
AutoTArray<ImageContainer::NonOwningImage,4> images;
bool principalHandleChanged =
lastPrincipalHandle != PRINCIPAL_HANDLE_NONE &&
lastPrincipalHandle != GetLastPrincipalHandleLocked();
// Add the frames from this iteration.
for (auto& image : newImages) {
image.mFrameID = NewFrameID();
images.AppendElement(image);
}
if (principalHandleChanged) {
UpdatePrincipalHandleForFrameIDLocked(lastPrincipalHandle,
newImages.LastElement().mFrameID);
}
SetCurrentFramesLocked(mLastPlayedVideoFrame.GetIntrinsicSize(), images);
nsCOMPtr<nsIRunnable> event =
new VideoFrameContainerInvalidateRunnable(this);
mMainThread->Dispatch(event.forget());
images.ClearAndRetainStorage();
}
示例10: StickyTimeDuration
//.........这里部分代码省略.........
TimeStamp startTimeStamp = ElapsedTimeToTimeStamp(intervalStartTime);
TimeStamp endTimeStamp = ElapsedTimeToTimeStamp(intervalEndTime);
if (mPendingState != PendingState::NotPending &&
(mPreviousTransitionPhase == TransitionPhase::Idle ||
mPreviousTransitionPhase == TransitionPhase::Pending))
{
currentPhase = TransitionPhase::Pending;
}
AutoTArray<AnimationEventInfo, 3> events;
auto appendTransitionEvent = [&](EventMessage aMessage,
const StickyTimeDuration& aElapsedTime,
const TimeStamp& aTimeStamp) {
double elapsedTime = aElapsedTime.ToSeconds();
if (aMessage == eTransitionCancel) {
elapsedTime = nsRFPService::ReduceTimePrecisionAsSecs(elapsedTime);
}
events.AppendElement(AnimationEventInfo(TransitionProperty(),
mOwningElement.Target(),
aMessage,
elapsedTime,
aTimeStamp,
this));
};
// Handle cancel events first
if ((mPreviousTransitionPhase != TransitionPhase::Idle &&
mPreviousTransitionPhase != TransitionPhase::After) &&
currentPhase == TransitionPhase::Idle) {
TimeStamp activeTimeStamp = ElapsedTimeToTimeStamp(aActiveTime);
appendTransitionEvent(eTransitionCancel, aActiveTime, activeTimeStamp);
}
// All other events
switch (mPreviousTransitionPhase) {
case TransitionPhase::Idle:
if (currentPhase == TransitionPhase::Pending ||
currentPhase == TransitionPhase::Before) {
appendTransitionEvent(eTransitionRun, intervalStartTime, zeroTimeStamp);
} else if (currentPhase == TransitionPhase::Active) {
appendTransitionEvent(eTransitionRun, intervalStartTime, zeroTimeStamp);
appendTransitionEvent(eTransitionStart,
intervalStartTime,
startTimeStamp);
} else if (currentPhase == TransitionPhase::After) {
appendTransitionEvent(eTransitionRun, intervalStartTime, zeroTimeStamp);
appendTransitionEvent(eTransitionStart,
intervalStartTime,
startTimeStamp);
appendTransitionEvent(eTransitionEnd, intervalEndTime, endTimeStamp);
}
break;
case TransitionPhase::Pending:
case TransitionPhase::Before:
if (currentPhase == TransitionPhase::Active) {
appendTransitionEvent(eTransitionStart,
intervalStartTime,
startTimeStamp);
} else if (currentPhase == TransitionPhase::After) {
appendTransitionEvent(eTransitionStart,
intervalStartTime,
startTimeStamp);
appendTransitionEvent(eTransitionEnd, intervalEndTime, endTimeStamp);
}
break;
case TransitionPhase::Active:
if (currentPhase == TransitionPhase::After) {
appendTransitionEvent(eTransitionEnd, intervalEndTime, endTimeStamp);
} else if (currentPhase == TransitionPhase::Before) {
appendTransitionEvent(eTransitionEnd,
intervalStartTime,
startTimeStamp);
}
break;
case TransitionPhase::After:
if (currentPhase == TransitionPhase::Active) {
appendTransitionEvent(eTransitionStart,
intervalEndTime,
startTimeStamp);
} else if (currentPhase == TransitionPhase::Before) {
appendTransitionEvent(eTransitionStart,
intervalEndTime,
startTimeStamp);
appendTransitionEvent(eTransitionEnd,
intervalStartTime,
endTimeStamp);
}
break;
}
mPreviousTransitionPhase = currentPhase;
if (!events.IsEmpty()) {
presContext->AnimationEventDispatcher()->QueueEvents(Move(events));
}
}
示例11: while
bool
IsInterfaceEqualToOrInheritedFrom(REFIID aInterface, REFIID aFrom,
unsigned long aVtableIndexHint)
{
if (aInterface == aFrom) {
return true;
}
// We expect this array to be length 1 but that is not guaranteed by the API.
AutoTArray<RefPtr<ITypeInfo>, 1> typeInfos;
// Grab aInterface's ITypeInfo so that we may obtain information about its
// inheritance hierarchy.
RefPtr<ITypeInfo> typeInfo;
if (RegisteredProxy::Find(aInterface, getter_AddRefs(typeInfo))) {
typeInfos.AppendElement(Move(typeInfo));
}
/**
* The main loop of this function searches the hierarchy of aInterface's
* parent interfaces, searching for aFrom.
*/
while (!typeInfos.IsEmpty()) {
RefPtr<ITypeInfo> curTypeInfo(Move(typeInfos.LastElement()));
typeInfos.RemoveElementAt(typeInfos.Length() - 1);
TYPEATTR* typeAttr = nullptr;
HRESULT hr = curTypeInfo->GetTypeAttr(&typeAttr);
if (FAILED(hr)) {
break;
}
bool isFromParentVtable = IsVtableIndexFromParentInterface(typeAttr,
aVtableIndexHint);
WORD numParentInterfaces = typeAttr->cImplTypes;
curTypeInfo->ReleaseTypeAttr(typeAttr);
typeAttr = nullptr;
if (!isFromParentVtable) {
// The vtable index cannot belong to this interface (otherwise the IIDs
// would already have matched and we would have returned true). Since we
// now also know that the vtable index cannot possibly be contained inside
// curTypeInfo's parent interface, there is no point searching any further
// up the hierarchy from here. OTOH we still should check any remaining
// entries that are still in the typeInfos array, so we continue.
continue;
}
for (WORD i = 0; i < numParentInterfaces; ++i) {
HREFTYPE refCookie;
hr = curTypeInfo->GetRefTypeOfImplType(i, &refCookie);
if (FAILED(hr)) {
continue;
}
RefPtr<ITypeInfo> nextTypeInfo;
hr = curTypeInfo->GetRefTypeInfo(refCookie,
getter_AddRefs(nextTypeInfo));
if (FAILED(hr)) {
continue;
}
hr = nextTypeInfo->GetTypeAttr(&typeAttr);
if (FAILED(hr)) {
continue;
}
IID nextIid = typeAttr->guid;
nextTypeInfo->ReleaseTypeAttr(typeAttr);
typeAttr = nullptr;
if (nextIid == aFrom) {
return true;
}
typeInfos.AppendElement(Move(nextTypeInfo));
}
}
return false;
}