Example #1
0
/* 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());
}
/* 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);
}
Example #3
0
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);
}
Example #4
0
//
// Builds the textual representation of a selector. Called by DOM 2 CSS 
// StyleRule:selectorText
//
void
nsCSSSelector::ToString(nsAString& aString, CSSStyleSheet* aSheet,
                        bool aAppend) const
{
  if (!aAppend)
   aString.Truncate();

  // selectors are linked from right-to-left, so the next selector in
  // the linked list actually precedes this one in the resulting string
  AutoTArray<const nsCSSSelector*, 8> stack;
  for (const nsCSSSelector *s = this; s; s = s->mNext) {
    stack.AppendElement(s);
  }

  while (!stack.IsEmpty()) {
    uint32_t index = stack.Length() - 1;
    const nsCSSSelector *s = stack.ElementAt(index);
    stack.RemoveElementAt(index);

    s->AppendToStringWithoutCombinators(aString, aSheet, false);

    // Append the combinator, if needed.
    if (!stack.IsEmpty()) {
      const nsCSSSelector *next = stack.ElementAt(index - 1);
      char16_t oper = s->mOperator;
      if (next->IsPseudoElement()) {
        NS_ASSERTION(oper == char16_t(':'),
                     "improperly chained pseudo element");
      } else {
        NS_ASSERTION(oper != char16_t(0),
                     "compound selector without combinator");

        aString.Append(char16_t(' '));
        if (oper != char16_t(' ')) {
          aString.Append(oper);
          aString.Append(char16_t(' '));
        }
      }
    }
  }
}
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;
}
Example #6
0
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();
}
Example #7
0
nsresult
RDFContentSinkImpl::PopContext(nsIRDFResource         *&aResource,
                               RDFContentSinkState     &aState,
                               RDFContentSinkParseMode &aParseMode)
{
    if ((nullptr == mContextStack) ||
        (mContextStack->IsEmpty())) {
        return NS_ERROR_NULL_POINTER;
    }

    uint32_t i = mContextStack->Length() - 1;
    RDFContextStackElement &e = mContextStack->ElementAt(i);

    aResource  = e.mResource;
    NS_IF_ADDREF(aResource);
    aState     = e.mState;
    aParseMode = e.mParseMode;

    mContextStack->RemoveElementAt(i);
    return NS_OK;
}
Example #8
0
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;
        }
      } else if (image->GetFormat() == ImageFormat::SURFACE_TEXTURE ||
                 image->GetFormat() == ImageFormat::EGLIMAGE) {
        gfx::IntSize size = image->GetSize();

        if (image->GetFormat() == ImageFormat::EGLIMAGE) {
          EGLImageImage* typedImage = image->AsEGLImageImage();
          texture = EGLImageTextureData::CreateTextureClient(
            typedImage, size, GetForwarder(), mTextureFlags);
#ifdef MOZ_WIDGET_ANDROID
        } else if (image->GetFormat() == ImageFormat::SURFACE_TEXTURE) {
          SurfaceTextureImage* typedImage = image->AsSurfaceTextureImage();
          texture = AndroidSurfaceTextureData::CreateTextureClient(
            typedImage->GetSurfaceTexture(), size, typedImage->GetOriginPos(),
            GetForwarder(), mTextureFlags
          );
#endif
        } else {
          MOZ_ASSERT(false, "Bad ImageFormat.");
        }
      } else {
        RefPtr<gfx::SourceSurface> surface = image->GetAsSourceSurface();
        MOZ_ASSERT(surface);
        texture = CreateTextureClientForDrawing(surface->GetFormat(), image->GetSize(),
                                                BackendSelector::Content, mTextureFlags);
        if (!texture) {
          return false;
        }

        MOZ_ASSERT(texture->CanExposeDrawTarget());

        if (!texture->Lock(OpenMode::OPEN_WRITE_ONLY)) {
          return false;
        }

        {
          // We must not keep a reference to the DrawTarget after it has been unlocked.
          DrawTarget* dt = texture->BorrowDrawTarget();
          if (!dt) {
            gfxWarning() << "ImageClientSingle::UpdateImage failed in BorrowDrawTarget";
            return false;
          }
          MOZ_ASSERT(surface.get());
          dt->CopySurface(surface, IntRect(IntPoint(), surface->GetSize()), IntPoint());
        }

        texture->Unlock();
      }
    }
    if (!texture || !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;
}
Example #9
0
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;
}
Example #10
0
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;
}
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();
}
void
CSSTransition::QueueEvents(const StickyTimeDuration& aActiveTime)
{
  if (!mOwningElement.IsSet()) {
    return;
  }

  nsPresContext* presContext = mOwningElement.GetPresContext();
  if (!presContext) {
    return;
  }

  static constexpr StickyTimeDuration zeroDuration = StickyTimeDuration();

  TransitionPhase currentPhase;
  StickyTimeDuration intervalStartTime;
  StickyTimeDuration intervalEndTime;

  if (!mEffect) {
    currentPhase = GetAnimationPhaseWithoutEffect<TransitionPhase>(*this);
  } else {
    ComputedTiming computedTiming = mEffect->GetComputedTiming();

    currentPhase = static_cast<TransitionPhase>(computedTiming.mPhase);
    intervalStartTime =
      std::max(std::min(StickyTimeDuration(-mEffect->SpecifiedTiming().Delay()),
                        computedTiming.mActiveDuration), zeroDuration);
    intervalEndTime =
      std::max(std::min((EffectEnd() - mEffect->SpecifiedTiming().Delay()),
                        computedTiming.mActiveDuration), zeroDuration);
  }

  // TimeStamps to use for ordering the events when they are dispatched. We
  // use a TimeStamp so we can compare events produced by different elements,
  // perhaps even with different timelines.
  // The zero timestamp is for transitionrun events where we ignore the delay
  // for the purpose of ordering events.
  TimeStamp zeroTimeStamp  = AnimationTimeToTimeStamp(zeroDuration);
  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));
  }
}
Example #13
0
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;
}