void
ResponsiveImageSelector::MaybeAppendDefaultCandidate()
{
  if (mDefaultSourceURL.IsEmpty()) {
    return;
  }

  int numCandidates = mCandidates.Length();

  // https://html.spec.whatwg.org/multipage/embedded-content.html#update-the-source-set
  // step 4.1.3:
  // If child has a src attribute whose value is not the empty string and source
  // set does not contain an image source with a density descriptor value of 1,
  // and no image source with a width descriptor, append child's src attribute
  // value to source set.
  for (int i = 0; i < numCandidates; i++) {
    if (mCandidates[i].IsComputedFromWidth()) {
      return;
    } else if (mCandidates[i].Density(this) == 1.0) {
      return;
    }
  }

  ResponsiveImageCandidate defaultCandidate;
  defaultCandidate.SetParameterDefault();
  defaultCandidate.SetURLSpec(mDefaultSourceURL);
  // We don't use MaybeAppend since we want to keep this even if it can never
  // match, as it may if the source set changes.
  mCandidates.AppendElement(defaultCandidate);
}
void
ResponsiveImageDescriptors::FillCandidate(ResponsiveImageCandidate &aCandidate)
{
  if (!Valid()) {
    aCandidate.SetParameterInvalid();
  } else if (mWidth.isSome()) {
    MOZ_ASSERT(mDensity.isNothing()); // Shouldn't be valid

    aCandidate.SetParameterAsComputedWidth(*mWidth);
  } else if (mDensity.isSome()) {
    MOZ_ASSERT(mWidth.isNothing()); // Shouldn't be valid

    aCandidate.SetParameterAsDensity(*mDensity);
  } else {
    // A valid set of descriptors with no density nor width (e.g. an empty set)
    // becomes 1.0 density, per spec
    aCandidate.SetParameterAsDensity(1.0);
  }
}
void
ResponsiveImageSelector::AppendCandidateIfUnique(const ResponsiveImageCandidate & aCandidate)
{
  int numCandidates = mCandidates.Length();

  // With the exception of Default, which should not be added until we are done
  // building the list.
  if (aCandidate.Type() == ResponsiveImageCandidate::eCandidateType_Default) {
    return;
  }

  // Discard candidates with identical parameters, they will never match
  for (int i = 0; i < numCandidates; i++) {
    if (mCandidates[i].HasSameParameter(aCandidate)) {
      return;
    }
  }

  mCandidates.AppendElement(aCandidate);
}
Пример #4
0
void
ResponsiveImageSelector::AppendCandidateIfUnique(const ResponsiveImageCandidate & aCandidate)
{
  int numCandidates = mCandidates.Length();

  // With the exception of Default, which should not be added until we are done
  // building the list, the spec forbids mixing width and explicit density
  // selectors in the same set.
  if (numCandidates && mCandidates[0].Type() != aCandidate.Type()) {
    return;
  }

  // Discard candidates with identical parameters, they will never match
  for (int i = 0; i < numCandidates; i++) {
    if (mCandidates[i].HasSameParameter(aCandidate)) {
      return;
    }
  }

  mCandidates.AppendElement(aCandidate);
}
// http://www.whatwg.org/specs/web-apps/current-work/#processing-the-image-candidates
bool
ResponsiveImageSelector::SetCandidatesFromSourceSet(const nsAString & aSrcSet)
{
  ClearSelectedCandidate();

  nsCOMPtr<nsIURI> docBaseURI = mOwnerNode ? mOwnerNode->GetBaseURI() : nullptr;

  if (!docBaseURI) {
    MOZ_ASSERT(false,
               "Should not be parsing SourceSet without a document");
    return false;
  }

  mCandidates.Clear();

  nsAString::const_iterator iter, end;
  aSrcSet.BeginReading(iter);
  aSrcSet.EndReading(end);

  // Read URL / descriptor pairs
  while (iter != end) {
    nsAString::const_iterator url, urlEnd, descriptor;

    // Skip whitespace and commas.
    // Extra commas at this point are a non-fatal syntax error.
    for (; iter != end && (nsContentUtils::IsHTMLWhitespace(*iter) ||
                           *iter == char16_t(',')); ++iter);

    if (iter == end) {
      break;
    }

    url = iter;

    // Find end of url
    for (;iter != end && !nsContentUtils::IsHTMLWhitespace(*iter); ++iter);

    // Omit trailing commas from URL.
    // Multiple commas are a non-fatal error.
    while (iter != url) {
      if (*(--iter) != char16_t(',')) {
        iter++;
        break;
      }
    }

    const nsDependentSubstring &urlStr = Substring(url, iter);

    MOZ_ASSERT(url != iter, "Shouldn't have empty URL at this point");

    ResponsiveImageCandidate candidate;
    if (candidate.ConsumeDescriptors(iter, end)) {
      candidate.SetURLSpec(urlStr);
      AppendCandidateIfUnique(candidate);
    }
  }

  bool parsedCandidates = mCandidates.Length() > 0;

  // Re-add default to end of list
  MaybeAppendDefaultCandidate();

  return parsedCandidates;
}