Example #1
0
void
LayerManager::StopFrameTimeRecording(uint32_t         aStartIndex,
                                     nsTArray<float>& aFrameIntervals,
                                     nsTArray<float>& aPaintTimes)
{
  uint32_t bufferSize = mRecording.mIntervals.Length();
  uint32_t length = mRecording.mNextIndex - aStartIndex;
  if (mRecording.mIsPaused || length > bufferSize || aStartIndex < mRecording.mCurrentRunStartIndex) {
    // aStartIndex is too old. Also if aStartIndex was issued before mRecordingNextIndex overflowed (uint32_t)
    //   and stopped after the overflow (would happen once every 828 days of constant 60fps).
    length = 0;
  }

  // Set length in advance to avoid possibly repeated reallocations (and OOM checks).
  if (!length || !aFrameIntervals.SetLength(length) || !aPaintTimes.SetLength(length)) {
    aFrameIntervals.Clear();
    aPaintTimes.Clear();
    return; // empty recording or OOM, return empty arrays.
  }

  uint32_t cyclicPos = aStartIndex % bufferSize;
  for (uint32_t i = 0; i < length; i++, cyclicPos++) {
    if (cyclicPos == bufferSize) {
      cyclicPos = 0;
    }
    aFrameIntervals[i] = mRecording.mIntervals[cyclicPos];
    aPaintTimes[i]     = mRecording.mPaints[cyclicPos];
  }
}
bool DWriteFontFileStream::Initialize(uint8_t* aData, uint32_t aSize) {
  if (!mData.SetLength(aSize, fallible)) {
    return false;
  }
  memcpy(mData.Elements(), aData, aSize);
  return true;
}
Example #3
0
bool
ReadIntoArray(nsIFile* aFile,
              nsTArray<uint8_t>& aOutDst,
              size_t aMaxLength)
{
  if (!FileExists(aFile)) {
    return false;
  }

  PRFileDesc* fd = nullptr;
  nsresult rv = aFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
  if (NS_FAILED(rv)) {
    return false;
  }

  int32_t length = PR_Seek(fd, 0, PR_SEEK_END);
  PR_Seek(fd, 0, PR_SEEK_SET);

  if (length < 0 || (size_t)length > aMaxLength) {
    NS_WARNING("EME file is longer than maximum allowed length");
    PR_Close(fd);
    return false;
  }
  aOutDst.SetLength(length);
  int32_t bytesRead = PR_Read(fd, aOutDst.Elements(), length);
  PR_Close(fd);
  return (bytesRead == length);
}
// add a continuation, return false on error if segment already has been seen
bool addContinuation(nsTArray<Continuation>& aArray, uint32_t aIndex,
                     const char *aValue, uint32_t aLength,
                     bool aNeedsPercentDecoding, bool aWasQuotedString)
{
  if (aIndex < aArray.Length() && aArray[aIndex].value) {
    NS_WARNING("duplicate RC2231 continuation segment #\n");
    return false;
  }

  if (aIndex > MAX_CONTINUATIONS) {
    NS_WARNING("RC2231 continuation segment # exceeds limit\n");
    return false;
  }

  if (aNeedsPercentDecoding && aWasQuotedString) {
    NS_WARNING("RC2231 continuation segment can't use percent encoding and quoted string form at the same time\n");
    return false;
  }

  Continuation cont(aValue, aLength, aNeedsPercentDecoding, aWasQuotedString);

  if (aArray.Length() <= aIndex) {
    aArray.SetLength(aIndex + 1);
  }
  aArray[aIndex] = cont;

  return true;
}
Example #5
0
// Getter for weighted regions: { top, bottom, left, right, weight }
nsresult
nsDOMCameraControl::Get(uint32_t aKey, nsTArray<CameraRegion>& aValue)
{
  nsTArray<ICameraControl::Region> regionArray;

  nsresult rv = mCameraControl->Get(aKey, regionArray);
  NS_ENSURE_SUCCESS(rv, rv);

  uint32_t length = regionArray.Length();
  DOM_CAMERA_LOGI("%s:%d : got %d regions\n", __func__, __LINE__, length);
  aValue.SetLength(length);

  for (uint32_t i = 0; i < length; ++i) {
    ICameraControl::Region& r = regionArray[i];
    CameraRegion& v = aValue[i];
    v.mTop = r.top;
    v.mLeft = r.left;
    v.mBottom = r.bottom;
    v.mRight = r.right;
    v.mWeight = r.weight;

    DOM_CAMERA_LOGI("region %d: top=%d, left=%d, bottom=%d, right=%d, weight=%u\n",
      i,
      v.mTop,
      v.mLeft,
      v.mBottom,
      v.mRight,
      v.mWeight
    );
  }

  return NS_OK;
}
void
nsSVGTextContainerFrame::CopyPositionList(nsTArray<float> *parentList,
                                        SVGUserUnitList *selfList,
                                        nsTArray<float> &dstList,
                                        uint32_t aOffset)
{
  dstList.Clear();

  uint32_t strLength = GetNumberOfChars();
  uint32_t parentCount = 0;
  if (parentList && parentList->Length() > aOffset) {
    parentCount = NS_MIN(parentList->Length() - aOffset, strLength);
  }

  uint32_t selfCount = NS_MIN(selfList->Length(), strLength);

  uint32_t count = NS_MAX(parentCount, selfCount);

  if (!dstList.SetLength(count))
    return;

  for (uint32_t i = 0; i < selfCount; i++) {
    dstList[i] = (*selfList)[i];
  }
  for (uint32_t i = selfCount; i < parentCount; i++) {
    dstList[i] = (*parentList)[aOffset + i];
  }

}
void
nsSVGTextContainerFrame::CopyRotateList(nsTArray<float> *parentList,
                                        const SVGNumberList *selfList,
                                        nsTArray<float> &dstList,
                                        uint32_t aOffset)
{
  dstList.Clear();

  uint32_t strLength = GetNumberOfChars();
  uint32_t parentCount = 0;
  if (parentList && parentList->Length() > aOffset) {
    parentCount = NS_MIN(parentList->Length() - aOffset, strLength);
  }

  uint32_t selfCount = NS_MIN(selfList ? selfList->Length() : 0, strLength);
  uint32_t count = NS_MAX(parentCount, selfCount);

  if (count > 0) {
    if (!dstList.SetLength(count))
      return;
    for (uint32_t i = 0; i < selfCount; i++) {
      dstList[i] = (*selfList)[i];
    }
    for (uint32_t i = selfCount; i < parentCount; i++) {
      dstList[i] = (*parentList)[aOffset + i];
    }
  } else if (parentList && !parentList->IsEmpty()) {
    // rotate is applied to extra characters too
    dstList.AppendElement((*parentList)[parentList->Length() - 1]);
  }
}
void detail::DoConversion(const nsTArray<nsString> &aUTF16Array,
                          nsTArray<nsCString> &aUTF8Array) {
  uint32_t count = aUTF16Array.Length();
  aUTF8Array.SetLength(count);
  for (uint32_t i = 0; i < count; ++i)
    CopyUTF16toUTF8(aUTF16Array[i], aUTF8Array[i]);
}
Example #9
0
nsresult
GDIFontEntry::CopyFontTable(uint32_t aTableTag, nsTArray<uint8_t>& aBuffer)
{
    if (!IsTrueType()) {
        return NS_ERROR_FAILURE;
    }

    AutoDC dc;
    AutoSelectFont font(dc.GetDC(), &mLogFont);
    if (font.IsValid()) {
        uint32_t tableSize =
            ::GetFontData(dc.GetDC(),
                          NativeEndian::swapToBigEndian(aTableTag),
                          0, nullptr, 0);
        if (tableSize != GDI_ERROR) {
            if (aBuffer.SetLength(tableSize, fallible)) {
                ::GetFontData(dc.GetDC(),
                              NativeEndian::swapToBigEndian(aTableTag), 0,
                              aBuffer.Elements(), tableSize);
                return NS_OK;
            }
            return NS_ERROR_OUT_OF_MEMORY;
        }
    }
    return NS_ERROR_FAILURE;
}
Example #10
0
    GMPErr Read(const nsCString& aRecordName,
                nsTArray<uint8_t>& aOutBytes) override
    {
        if (!IsOpen(aRecordName)) {
            return GMPClosedErr;
        }

        Record* record = nullptr;
        mRecords.Get(aRecordName, &record);
        MOZ_ASSERT(record && !!record->mFileDesc); // IsOpen() guarantees this.

        // Our error strategy is to report records with invalid contents as
        // containing 0 bytes. Zero length records are considered "deleted" by
        // the GMPStorage API.
        aOutBytes.SetLength(0);

        int32_t recordLength = 0;
        nsCString recordName;
        nsresult err = ReadRecordMetadata(record->mFileDesc,
                                          recordLength,
                                          recordName);
        if (NS_FAILED(err) || recordLength == 0) {
            // We failed to read the record metadata. Or the record is 0 length.
            // Treat damaged records as empty.
            // ReadRecordMetadata() could fail if the GMP opened a new record and
            // tried to read it before anything was written to it..
            return GMPNoErr;
        }

        if (!aRecordName.Equals(recordName)) {
            NS_WARNING("Record file contains some other record's contents!");
            return GMPRecordCorrupted;
        }

        // After calling ReadRecordMetadata, we should be ready to read the
        // record data.
        if (PR_Available(record->mFileDesc) != recordLength) {
            NS_WARNING("Record file length mismatch!");
            return GMPRecordCorrupted;
        }

        aOutBytes.SetLength(recordLength);
        int32_t bytesRead = PR_Read(record->mFileDesc, aOutBytes.Elements(), recordLength);
        return (bytesRead == recordLength) ? GMPNoErr : GMPRecordCorrupted;
    }
void ExtractDisplayAddresses(const nsCOMArray<msgIAddressObject> &aHeader,
                             nsTArray<nsString> &displayAddrs) {
  uint32_t count = aHeader.Length();

  displayAddrs.SetLength(count);
  for (uint32_t i = 0; i < count; i++) aHeader[i]->ToString(displayAddrs[i]);

  if (count == 1 && displayAddrs[0].IsEmpty()) displayAddrs.Clear();
}
Example #12
0
/* static */ bool
PushUtil::CopyArrayBufferToArray(const ArrayBuffer& aBuffer,
                                 nsTArray<uint8_t>& aArray)
{
  aBuffer.ComputeLengthAndData();
  return aArray.SetLength(aBuffer.Length(), fallible) &&
         aArray.ReplaceElementsAt(0, aBuffer.Length(), aBuffer.Data(),
                                  aBuffer.Length(), fallible);
}
Example #13
0
void
AudioNodeStream::UpMixDownMixChunk(const AudioChunk* aChunk,
                                   uint32_t aOutputChannelCount,
                                   nsTArray<const void*>& aOutputChannels,
                                   nsTArray<float>& aDownmixBuffer)
{
  static const float silenceChannel[WEBAUDIO_BLOCK_SIZE] = {0.f};

  aOutputChannels.AppendElements(aChunk->mChannelData);
  if (aOutputChannels.Length() < aOutputChannelCount) {
    if (mChannelInterpretation == ChannelInterpretation::Speakers) {
      AudioChannelsUpMix(&aOutputChannels, aOutputChannelCount, nullptr);
      NS_ASSERTION(aOutputChannelCount == aOutputChannels.Length(),
                   "We called GetAudioChannelsSuperset to avoid this");
    } else {
      // Fill up the remaining aOutputChannels by zeros
      for (uint32_t j = aOutputChannels.Length(); j < aOutputChannelCount; ++j) {
        aOutputChannels.AppendElement(silenceChannel);
      }
    }
  } else if (aOutputChannels.Length() > aOutputChannelCount) {
    if (mChannelInterpretation == ChannelInterpretation::Speakers) {
      nsAutoTArray<float*,GUESS_AUDIO_CHANNELS> outputChannels;
      outputChannels.SetLength(aOutputChannelCount);
      aDownmixBuffer.SetLength(aOutputChannelCount * WEBAUDIO_BLOCK_SIZE);
      for (uint32_t j = 0; j < aOutputChannelCount; ++j) {
        outputChannels[j] = &aDownmixBuffer[j * WEBAUDIO_BLOCK_SIZE];
      }

      AudioChannelsDownMix(aOutputChannels, outputChannels.Elements(),
                           aOutputChannelCount, WEBAUDIO_BLOCK_SIZE);

      aOutputChannels.SetLength(aOutputChannelCount);
      for (uint32_t j = 0; j < aOutputChannels.Length(); ++j) {
        aOutputChannels[j] = outputChannels[j];
      }
    } else {
      // Drop the remaining aOutputChannels
      aOutputChannels.RemoveElementsAt(aOutputChannelCount,
        aOutputChannels.Length() - aOutputChannelCount);
    }
  }
}
void ExtractAllAddresses(const nsCOMArray<msgIAddressObject> &aHeader,
                         nsTArray<nsString> &names,
                         nsTArray<nsString> &emails) {
  uint32_t count = aHeader.Length();

  // Prefill arrays before we start
  names.SetLength(count);
  emails.SetLength(count);

  for (uint32_t i = 0; i < count; i++) {
    aHeader[i]->GetName(names[i]);
    aHeader[i]->GetEmail(emails[i]);
  }

  if (count == 1 && names[0].IsEmpty() && emails[0].IsEmpty()) {
    names.Clear();
    emails.Clear();
  }
}
Example #15
0
bool
GetPreparsedData(HANDLE handle, nsTArray<uint8_t>& data)
{
  UINT size;
  if (GetRawInputDeviceInfo(handle, RIDI_PREPARSEDDATA, nullptr, &size) == kRawInputError) {
    return false;
  }
  data.SetLength(size);
  return GetRawInputDeviceInfo(handle, RIDI_PREPARSEDDATA,
                               data.Elements(), &size) > 0;
}
void
nsGridContainerFrame::CalculateTrackSizes(const LogicalSize& aPercentageBasis,
                                          const nsStylePosition* aStyle,
                                          nsTArray<TrackSize>& aColSizes,
                                          nsTArray<TrackSize>& aRowSizes)
{
  aColSizes.SetLength(mGridColEnd - 1);
  aRowSizes.SetLength(mGridRowEnd - 1);
  WritingMode wm = GetWritingMode();
  InitializeTrackSizes(aPercentageBasis.ISize(wm),
                       aStyle->mGridTemplateColumns.mMinTrackSizingFunctions,
                       aStyle->mGridTemplateColumns.mMaxTrackSizingFunctions,
                       aStyle->mGridAutoColumnsMin,
                       aStyle->mGridAutoColumnsMax,
                       aColSizes);
  InitializeTrackSizes(aPercentageBasis.BSize(wm),
                       aStyle->mGridTemplateRows.mMinTrackSizingFunctions,
                       aStyle->mGridTemplateRows.mMaxTrackSizingFunctions,
                       aStyle->mGridAutoRowsMin,
                       aStyle->mGridAutoRowsMax,
                       aRowSizes);
}
void
nsProfileCollector::BookmarkCounter::CountChildren(PRInt64 root, PRBool deep,
                                                   nsTArray<PRInt32> &count)
{
  count.SetLength(kLastBookmarkType);
  for (PRInt32 i = 0; i < kLastBookmarkType; ++i) {
    count[i] = 0;
  }

  nsCOMPtr<nsINavHistoryService> histSvc =
    do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID);
  if (!histSvc) {
    return;
  }

  nsCOMPtr<nsINavHistoryQuery> query;
  histSvc->GetNewQuery(getter_AddRefs(query));
  if (!query) {
    return;
  }

  query->SetFolders(&root, 1);
  query->SetOnlyBookmarked(PR_TRUE);

  nsCOMPtr<nsINavHistoryQueryOptions> options;
  histSvc->GetNewQueryOptions(getter_AddRefs(options));
  if (!options) {
    return;
  }

  // setting option breaks bookmark count
  // const PRUint16 groupMode = nsINavHistoryQueryOptions::GROUP_BY_FOLDER;
  // options->SetGroupingMode(&groupMode, 1);

  nsCOMPtr<nsINavHistoryResult> result;
  histSvc->ExecuteQuery(query, options, getter_AddRefs(result));
  if (!result) {
    return;
  }

  nsCOMPtr<nsINavHistoryContainerResultNode> rootNode;
  result->GetRoot(getter_AddRefs(rootNode));
  if (!rootNode) {
    return;
  }

  CountRecursive(rootNode, deep, count);
}
Example #18
0
/* static */ bool
PushUtil::CopyBufferSourceToArray(
  const OwningArrayBufferViewOrArrayBuffer& aSource, nsTArray<uint8_t>& aArray)
{
  if (aSource.IsArrayBuffer()) {
    return CopyArrayBufferToArray(aSource.GetAsArrayBuffer(), aArray);
  }
  if (aSource.IsArrayBufferView()) {
    const ArrayBufferView& view = aSource.GetAsArrayBufferView();
    view.ComputeLengthAndData();
    return aArray.SetLength(view.Length(), fallible) &&
           aArray.ReplaceElementsAt(0, view.Length(), view.Data(),
                                    view.Length(), fallible);
  }
  MOZ_CRASH("Uninitialized union: expected buffer or view");
}
nsresult
ICameraControl::GetListOfCameras(nsTArray<nsString>& aList)
{
  int32_t count = android::Camera::getNumberOfCameras();
  DOM_CAMERA_LOGI("getListOfCameras : getNumberOfCameras() returned %d\n", count);
  if (count <= 0) {
    aList.Clear();
    return NS_OK;
  }

  // Allocate 2 extra slots to reserve space for 'front' and 'back' cameras
  // at the front of the array--we will collapse any empty slots below.
  aList.SetLength(2);
  uint32_t extraIdx = 2;
  bool gotFront = false;
  bool gotBack = false;
  while (count--) {
    nsCString cameraName;
    nsresult result = GetCameraName(count, cameraName);
    if (result != NS_OK) {
      continue;
    }

    // The first camera we find named 'back' gets slot 0; and the first
    // we find named 'front' gets slot 1.  All others appear after these.
    if (cameraName.EqualsLiteral("back")) {
      CopyUTF8toUTF16(cameraName, aList[0]);
      gotBack = true;
    } else if (cameraName.EqualsLiteral("front")) {
      CopyUTF8toUTF16(cameraName, aList[1]);
      gotFront = true;
    } else {
      CopyUTF8toUTF16(cameraName, *aList.InsertElementAt(extraIdx));
      extraIdx++;
    }
  }

  if (!gotFront) {
    aList.RemoveElementAt(1);
  }

  if (!gotBack) {
    aList.RemoveElementAt(0);
  }

  return NS_OK;
}
Example #20
0
static void
BlacklistEntriesToDriverInfo(nsTArray<nsCString>& aBlacklistEntries,
                             nsTArray<GfxDriverInfo>& aDriverInfo)
{
    aDriverInfo.Clear();
    aDriverInfo.SetLength(aBlacklistEntries.Length());

    for (uint32_t i = 0; i < aBlacklistEntries.Length(); ++i) {
        nsCString blacklistEntry = aBlacklistEntries[i];
        GfxDriverInfo di;
        if (BlacklistEntryToDriverInfo(blacklistEntry, di)) {
            aDriverInfo[i] = di;
            // Prevent di falling out of scope from destroying the devices.
            di.mDeleteDevices = false;
        }
    }
}
void
InternalHeaders::GetAll(const nsACString& aName, nsTArray<nsCString>& aResults,
                        ErrorResult& aRv) const
{
  nsAutoCString lowerName;
  ToLowerCase(aName, lowerName);

  if (IsInvalidName(lowerName, aRv)) {
    return;
  }

  aResults.SetLength(0);
  for (uint32_t i = 0; i < mList.Length(); ++i) {
    if (lowerName == mList[i].mName) {
      aResults.AppendElement(mList[i].mValue);
    }
  }
}
Example #22
0
static void ReadFile(const char* aPath, nsTArray<uint8_t>& aBuffer) {
  FILE* f = fopen(aPath, "rb");
  ASSERT_NE(f, (FILE*)nullptr);

  int r = fseek(f, 0, SEEK_END);
  ASSERT_EQ(r, 0);

  long size = ftell(f);
  ASSERT_NE(size, -1);
  aBuffer.SetLength(size);

  r = fseek(f, 0, SEEK_SET);
  ASSERT_EQ(r, 0);

  size_t got = fread(aBuffer.Elements(), 1, size, f);
  ASSERT_EQ(got, size_t(size));

  r = fclose(f);
  ASSERT_EQ(r, 0);
}
Example #23
0
static void
BlacklistEntriesToDriverInfo(nsIDOMHTMLCollection* aBlacklistEntries,
                             nsTArray<GfxDriverInfo>& aDriverInfo)
{
  uint32_t length;
  if (NS_FAILED(aBlacklistEntries->GetLength(&length)))
    return;

  aDriverInfo.Clear();
  aDriverInfo.SetLength(length);
  for (uint32_t i = 0; i < length; ++i) {
    nsCOMPtr<nsIDOMNode> blacklistEntry;
    if (NS_SUCCEEDED(aBlacklistEntries->Item(i,
                                             getter_AddRefs(blacklistEntry))) &&
        blacklistEntry) {
      GfxDriverInfo di;
      if (BlacklistEntryToDriverInfo(blacklistEntry, di)) {
        aDriverInfo[i] = di;
        // Prevent di falling out of scope from destroying the devices.
        di.mDeleteDevices = false;
      }
    }
  }
}
bool
nsCaseTransformTextRunFactory::TransformString(
    const nsAString& aString,
    nsString& aConvertedString,
    bool aAllUppercase,
    const nsIAtom* aLanguage,
    nsTArray<bool>& aCharsToMergeArray,
    nsTArray<bool>& aDeletedCharsArray,
    nsTransformedTextRun* aTextRun,
    nsTArray<uint8_t>* aCanBreakBeforeArray,
    nsTArray<nsStyleContext*>* aStyleArray)
{
  NS_PRECONDITION(!aTextRun || (aCanBreakBeforeArray && aStyleArray),
                  "either none or all three optional parameters required");

  uint32_t length = aString.Length();
  const char16_t* str = aString.BeginReading();

  bool mergeNeeded = false;

  bool capitalizeDutchIJ = false;
  bool prevIsLetter = false;
  bool ntPrefix = false; // true immediately after a word-initial 'n' or 't'
                         // when doing Irish lowercasing
  uint32_t sigmaIndex = uint32_t(-1);
  nsIUGenCategory::nsUGenCategory cat;

  uint8_t style = aAllUppercase ? NS_STYLE_TEXT_TRANSFORM_UPPERCASE : 0;
  const nsIAtom* lang = aLanguage;

  LanguageSpecificCasingBehavior languageSpecificCasing = GetCasingFor(lang);
  mozilla::GreekCasing::State greekState;
  mozilla::IrishCasing::State irishState;
  uint32_t irishMark = uint32_t(-1); // location of possible prefix letter(s)

  for (uint32_t i = 0; i < length; ++i) {
    uint32_t ch = str[i];

    nsStyleContext* styleContext;
    if (aTextRun) {
      styleContext = aTextRun->mStyles[i];
      style = aAllUppercase ? NS_STYLE_TEXT_TRANSFORM_UPPERCASE :
        styleContext->StyleText()->mTextTransform;

      if (lang != styleContext->StyleFont()->mLanguage) {
        lang = styleContext->StyleFont()->mLanguage;
        languageSpecificCasing = GetCasingFor(lang);
        greekState.Reset();
        irishState.Reset();
        irishMark = uint32_t(-1);
      }
    }

    int extraChars = 0;
    const mozilla::unicode::MultiCharMapping *mcm;
    bool inhibitBreakBefore = false; // have we just deleted preceding hyphen?

    if (NS_IS_HIGH_SURROGATE(ch) && i < length - 1 &&
        NS_IS_LOW_SURROGATE(str[i + 1])) {
      ch = SURROGATE_TO_UCS4(ch, str[i + 1]);
    }

    switch (style) {
    case NS_STYLE_TEXT_TRANSFORM_LOWERCASE:
      if (languageSpecificCasing == eLSCB_Turkish) {
        if (ch == 'I') {
          ch = LATIN_SMALL_LETTER_DOTLESS_I;
          prevIsLetter = true;
          sigmaIndex = uint32_t(-1);
          break;
        }
        if (ch == LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE) {
          ch = 'i';
          prevIsLetter = true;
          sigmaIndex = uint32_t(-1);
          break;
        }
      }

      cat = mozilla::unicode::GetGenCategory(ch);

      if (languageSpecificCasing == eLSCB_Irish &&
          cat == nsIUGenCategory::kLetter) {
        // See bug 1018805 for Irish lowercasing requirements
        if (!prevIsLetter && (ch == 'n' || ch == 't')) {
          ntPrefix = true;
        } else {
          if (ntPrefix && mozilla::IrishCasing::IsUpperVowel(ch)) {
            aConvertedString.Append('-');
            ++extraChars;
          }
          ntPrefix = false;
        }
      } else {
        ntPrefix = false;
      }

      // Special lowercasing behavior for Greek Sigma: note that this is listed
      // as context-sensitive in Unicode's SpecialCasing.txt, but is *not* a
      // language-specific mapping; it applies regardless of the language of
      // the element.
      //
      // The lowercase mapping for CAPITAL SIGMA should be to SMALL SIGMA (i.e.
      // the non-final form) whenever there is a following letter, or when the
      // CAPITAL SIGMA occurs in isolation (neither preceded nor followed by a
      // LETTER); and to FINAL SIGMA when it is preceded by another letter but
      // not followed by one.
      //
      // To implement the context-sensitive nature of this mapping, we keep
      // track of whether the previous character was a letter. If not, CAPITAL
      // SIGMA will map directly to SMALL SIGMA. If the previous character
      // was a letter, CAPITAL SIGMA maps to FINAL SIGMA and we record the
      // position in the converted string; if we then encounter another letter,
      // that FINAL SIGMA is replaced with a standard SMALL SIGMA.

      // If sigmaIndex is not -1, it marks where we have provisionally mapped
      // a CAPITAL SIGMA to FINAL SIGMA; if we now find another letter, we
      // need to change it to SMALL SIGMA.
      if (sigmaIndex != uint32_t(-1)) {
        if (cat == nsIUGenCategory::kLetter) {
          aConvertedString.SetCharAt(GREEK_SMALL_LETTER_SIGMA, sigmaIndex);
        }
      }

      if (ch == GREEK_CAPITAL_LETTER_SIGMA) {
        // If preceding char was a letter, map to FINAL instead of SMALL,
        // and note where it occurred by setting sigmaIndex; we'll change it
        // to standard SMALL SIGMA later if another letter follows
        if (prevIsLetter) {
          ch = GREEK_SMALL_LETTER_FINAL_SIGMA;
          sigmaIndex = aConvertedString.Length();
        } else {
          // CAPITAL SIGMA not preceded by a letter is unconditionally mapped
          // to SMALL SIGMA
          ch = GREEK_SMALL_LETTER_SIGMA;
          sigmaIndex = uint32_t(-1);
        }
        prevIsLetter = true;
        break;
      }

      // ignore diacritics for the purpose of contextual sigma mapping;
      // otherwise, reset prevIsLetter appropriately and clear the
      // sigmaIndex marker
      if (cat != nsIUGenCategory::kMark) {
        prevIsLetter = (cat == nsIUGenCategory::kLetter);
        sigmaIndex = uint32_t(-1);
      }

      mcm = mozilla::unicode::SpecialLower(ch);
      if (mcm) {
        int j = 0;
        while (j < 2 && mcm->mMappedChars[j + 1]) {
          aConvertedString.Append(mcm->mMappedChars[j]);
          ++extraChars;
          ++j;
        }
        ch = mcm->mMappedChars[j];
        break;
      }

      ch = ToLowerCase(ch);
      break;

    case NS_STYLE_TEXT_TRANSFORM_UPPERCASE:
      if (languageSpecificCasing == eLSCB_Turkish && ch == 'i') {
        ch = LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE;
        break;
      }

      if (languageSpecificCasing == eLSCB_Greek) {
        ch = mozilla::GreekCasing::UpperCase(ch, greekState);
        break;
      }

      if (languageSpecificCasing == eLSCB_Irish) {
        bool mark;
        uint8_t action;
        ch = mozilla::IrishCasing::UpperCase(ch, irishState, mark, action);
        if (mark) {
          irishMark = aConvertedString.Length();
          break;
        } else if (action) {
          nsString& str = aConvertedString; // shorthand
          switch (action) {
          case 1:
            // lowercase a single prefix letter
            NS_ASSERTION(str.Length() > 0 && irishMark < str.Length(),
                         "bad irishMark!");
            str.SetCharAt(ToLowerCase(str[irishMark]), irishMark);
            irishMark = uint32_t(-1);
            break;
          case 2:
            // lowercase two prefix letters (immediately before current pos)
            NS_ASSERTION(str.Length() >= 2 && irishMark == str.Length() - 2,
                         "bad irishMark!");
            str.SetCharAt(ToLowerCase(str[irishMark]), irishMark);
            str.SetCharAt(ToLowerCase(str[irishMark + 1]), irishMark + 1);
            irishMark = uint32_t(-1);
            break;
          case 3:
            // lowercase one prefix letter, and delete following hyphen
            // (which must be the immediately-preceding char)
            NS_ASSERTION(str.Length() >= 2 && irishMark == str.Length() - 2,
                         "bad irishMark!");
            str.Replace(irishMark, 2, ToLowerCase(str[irishMark]));
            aDeletedCharsArray[irishMark + 1] = true;
            // Remove the trailing entries (corresponding to the deleted hyphen)
            // from the auxiliary arrays.
            aCharsToMergeArray.SetLength(aCharsToMergeArray.Length() - 1);
            if (aTextRun) {
              aStyleArray->SetLength(aStyleArray->Length() - 1);
              aCanBreakBeforeArray->SetLength(aCanBreakBeforeArray->Length() - 1);
              inhibitBreakBefore = true;
            }
            mergeNeeded = true;
            irishMark = uint32_t(-1);
            break;
          }
          // ch has been set to the uppercase for current char;
          // No need to check for SpecialUpper here as none of the characters
          // that could trigger an Irish casing action have special mappings.
          break;
        }
        // If we didn't have any special action to perform, fall through
        // to check for special uppercase (ß)
      }

      mcm = mozilla::unicode::SpecialUpper(ch);
      if (mcm) {
        int j = 0;
        while (j < 2 && mcm->mMappedChars[j + 1]) {
          aConvertedString.Append(mcm->mMappedChars[j]);
          ++extraChars;
          ++j;
        }
        ch = mcm->mMappedChars[j];
        break;
      }

      ch = ToUpperCase(ch);
      break;

    case NS_STYLE_TEXT_TRANSFORM_CAPITALIZE:
      if (aTextRun) {
        if (capitalizeDutchIJ && ch == 'j') {
          ch = 'J';
          capitalizeDutchIJ = false;
          break;
        }
        capitalizeDutchIJ = false;
        if (i < aTextRun->mCapitalize.Length() && aTextRun->mCapitalize[i]) {
          if (languageSpecificCasing == eLSCB_Turkish && ch == 'i') {
            ch = LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE;
            break;
          }
          if (languageSpecificCasing == eLSCB_Dutch && ch == 'i') {
            ch = 'I';
            capitalizeDutchIJ = true;
            break;
          }

          mcm = mozilla::unicode::SpecialTitle(ch);
          if (mcm) {
            int j = 0;
            while (j < 2 && mcm->mMappedChars[j + 1]) {
              aConvertedString.Append(mcm->mMappedChars[j]);
              ++extraChars;
              ++j;
            }
            ch = mcm->mMappedChars[j];
            break;
          }

          ch = ToTitleCase(ch);
        }
      }
      break;

    case NS_STYLE_TEXT_TRANSFORM_FULLWIDTH:
      ch = mozilla::unicode::GetFullWidth(ch);
      break;

    default:
      break;
    }

    if (ch == uint32_t(-1)) {
      aDeletedCharsArray.AppendElement(true);
      mergeNeeded = true;
    } else {
      aDeletedCharsArray.AppendElement(false);
      aCharsToMergeArray.AppendElement(false);
      if (aTextRun) {
        aStyleArray->AppendElement(styleContext);
        aCanBreakBeforeArray->AppendElement(inhibitBreakBefore ? false :
                                            aTextRun->CanBreakLineBefore(i));
      }

      if (IS_IN_BMP(ch)) {
        aConvertedString.Append(ch);
      } else {
        aConvertedString.Append(H_SURROGATE(ch));
        aConvertedString.Append(L_SURROGATE(ch));
        ++i;
        aDeletedCharsArray.AppendElement(true); // not exactly deleted, but the
                                                // trailing surrogate is skipped
        ++extraChars;
      }

      while (extraChars-- > 0) {
        mergeNeeded = true;
        aCharsToMergeArray.AppendElement(true);
        if (aTextRun) {
          aStyleArray->AppendElement(styleContext);
          aCanBreakBeforeArray->AppendElement(false);
        }
      }
    }
  }

  return mergeNeeded;
}
Example #25
0
nsresult
nsHyphenator::Hyphenate(const nsAString& aString,
                        nsTArray<bool>& aHyphens)
{
  if (!aHyphens.SetLength(aString.Length())) {
    return NS_ERROR_OUT_OF_MEMORY;
  }
  memset(aHyphens.Elements(), false, aHyphens.Length());

  bool inWord = false;
  uint32_t wordStart = 0, wordLimit = 0;
  uint32_t chLen;
  for (uint32_t i = 0; i < aString.Length(); i += chLen) {
    uint32_t ch = aString[i];
    chLen = 1;

    if (NS_IS_HIGH_SURROGATE(ch)) {
      if (i + 1 < aString.Length() && NS_IS_LOW_SURROGATE(aString[i+1])) {
        ch = SURROGATE_TO_UCS4(ch, aString[i+1]);
        chLen = 2;
      } else {
        NS_WARNING("unpaired surrogate found during hyphenation");
      }
    }

    nsIUGenCategory::nsUGenCategory cat = mozilla::unicode::GetGenCategory(ch);
    if (cat == nsIUGenCategory::kLetter || cat == nsIUGenCategory::kMark) {
      if (!inWord) {
        inWord = true;
        wordStart = i;
      }
      wordLimit = i + chLen;
      if (i + chLen < aString.Length()) {
        continue;
      }
    }

    if (inWord) {
      const PRUnichar *begin = aString.BeginReading();
      NS_ConvertUTF16toUTF8 utf8(begin + wordStart,
                                 wordLimit - wordStart);
      nsAutoTArray<char,200> utf8hyphens;
      utf8hyphens.SetLength(utf8.Length() + 5);
      char **rep = nullptr;
      int *pos = nullptr;
      int *cut = nullptr;
      int err = hnj_hyphen_hyphenate2((HyphenDict*)mDict,
                                      utf8.BeginReading(), utf8.Length(),
                                      utf8hyphens.Elements(), nullptr,
                                      &rep, &pos, &cut);
      if (!err) {
        // Surprisingly, hnj_hyphen_hyphenate2 converts the 'hyphens' buffer
        // from utf8 code unit indexing (which would match the utf8 input
        // string directly) to Unicode character indexing.
        // We then need to convert this to utf16 code unit offsets for Gecko.
        const char *hyphPtr = utf8hyphens.Elements();
        const PRUnichar *cur = begin + wordStart;
        const PRUnichar *end = begin + wordLimit;
        while (cur < end) {
          if (*hyphPtr & 0x01) {
            aHyphens[cur - begin] = true;
          }
          cur++;
          if (cur < end && NS_IS_LOW_SURROGATE(*cur) &&
              NS_IS_HIGH_SURROGATE(*(cur-1)))
          {
            cur++;
          }
          hyphPtr++;
        }
      }
    }
    
    inWord = false;
  }

  return NS_OK;
}
Example #26
0
nsresult
nsHyphenator::Hyphenate(const nsAString& aString,
                        nsTArray<PRPackedBool>& aHyphens)
{
  if (!aHyphens.SetLength(aString.Length())) {
    return NS_ERROR_OUT_OF_MEMORY;
  }
  memset(aHyphens.Elements(), PR_FALSE, aHyphens.Length());

  PRBool inWord = PR_FALSE;
  PRUint32 wordStart = 0, wordLimit = 0;
  for (PRUint32 i = 0; i < aString.Length(); i++) {
    PRUnichar ch = aString[i];

    nsIUGenCategory::nsUGenCategory cat = mCategories->Get(ch);
    if (cat == nsIUGenCategory::kLetter || cat == nsIUGenCategory::kMark) {
      if (!inWord) {
        inWord = PR_TRUE;
        wordStart = i;
      }
      wordLimit = i + 1;
      if (i < aString.Length() - 1) {
        continue;
      }
    }

    if (inWord) {
      NS_ConvertUTF16toUTF8 utf8(aString.BeginReading() + wordStart,
                                 wordLimit - wordStart);
      nsAutoTArray<char,200> utf8hyphens;
      utf8hyphens.SetLength(utf8.Length() + 5);
      char **rep = nsnull;
      int *pos = nsnull;
      int *cut = nsnull;
      int err = hnj_hyphen_hyphenate2((HyphenDict*)mDict,
                                      utf8.BeginReading(), utf8.Length(),
                                      utf8hyphens.Elements(), nsnull,
                                      &rep, &pos, &cut);
      if (!err) {
        PRUint32 utf16offset = wordStart;
        const char *cp = utf8.BeginReading();
        while (cp < utf8.EndReading()) {
          if (UTF8traits::isASCII(*cp)) { // single-byte utf8 char
            cp++;
            utf16offset++;
          } else if (UTF8traits::is2byte(*cp)) { // 2-byte sequence
            cp += 2;
            utf16offset++;
          } else if (UTF8traits::is3byte(*cp)) { // 3-byte sequence
            cp += 3;
            utf16offset++;
          } else { // must be a 4-byte sequence (no need to check validity,
                   // as this was just created with NS_ConvertUTF16toUTF8)
            NS_ASSERTION(UTF8traits::is4byte(*cp), "unexpected utf8 byte");
            cp += 4;
            utf16offset += 2;
          }
          NS_ASSERTION(cp <= utf8.EndReading(), "incomplete utf8 string?");
          NS_ASSERTION(utf16offset <= aString.Length(), "length mismatch?");
          if (utf8hyphens[cp - utf8.BeginReading() - 1] & 0x01) {
            aHyphens[utf16offset - 1] = PR_TRUE;
          }
        }
      }
    }
    
    inWord = PR_FALSE;
  }

  return NS_OK;
}