michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef NSTEXTFRAMEUTILS_H_ michael@0: #define NSTEXTFRAMEUTILS_H_ michael@0: michael@0: #include "gfxSkipChars.h" michael@0: michael@0: class nsIContent; michael@0: struct nsStyleText; michael@0: michael@0: #define BIG_TEXT_NODE_SIZE 4096 michael@0: michael@0: #define CH_NBSP 160 michael@0: #define CH_SHY 173 michael@0: #define CH_CJKSP 12288 // U+3000 IDEOGRAPHIC SPACE (CJK Full-Width Space) michael@0: michael@0: class nsTextFrameUtils { michael@0: public: michael@0: // These constants are used as textrun flags for textframe textruns. michael@0: enum { michael@0: // The following flags are set by TransformText michael@0: michael@0: // the text has at least one untransformed tab character michael@0: TEXT_HAS_TAB = 0x010000, michael@0: // the original text has at least one soft hyphen character michael@0: TEXT_HAS_SHY = 0x020000, michael@0: TEXT_WAS_TRANSFORMED = 0x040000, michael@0: TEXT_UNUSED_FLAG = 0x080000, michael@0: michael@0: // The following flags are set by nsTextFrame michael@0: michael@0: TEXT_IS_SIMPLE_FLOW = 0x100000, michael@0: TEXT_INCOMING_WHITESPACE = 0x200000, michael@0: TEXT_TRAILING_WHITESPACE = 0x400000, michael@0: TEXT_COMPRESSED_LEADING_WHITESPACE = 0x800000, michael@0: TEXT_NO_BREAKS = 0x1000000, michael@0: TEXT_IS_TRANSFORMED = 0x2000000, michael@0: // This gets set if there's a break opportunity at the end of the textrun. michael@0: // We normally don't use this break opportunity because the following text michael@0: // will have a break opportunity at the start, but it's useful for line michael@0: // layout to know about it in case the following content is not text michael@0: TEXT_HAS_TRAILING_BREAK = 0x4000000, michael@0: michael@0: // This is set if the textrun was created for a textframe whose michael@0: // NS_FRAME_IS_IN_SINGLE_CHAR_MI flag is set. This occurs if the textframe michael@0: // belongs to a MathML element whose embedded text consists of a michael@0: // single character. michael@0: TEXT_IS_SINGLE_CHAR_MI = 0x8000000 michael@0: michael@0: // The following are defined by gfxTextRunWordCache rather than here, michael@0: // so that it also has access to the _INCOMING flag michael@0: // TEXT_TRAILING_ARABICCHAR michael@0: // TEXT_INCOMING_ARABICCHAR michael@0: michael@0: // This is defined in gfxTextRunFactory to allow access in gfxFont. michael@0: // TEXT_USE_MATH_SCRIPT michael@0: }; michael@0: michael@0: // These constants are used in TransformText to represent context information michael@0: // from previous textruns. michael@0: enum { michael@0: INCOMING_NONE = 0, michael@0: INCOMING_WHITESPACE = 1, michael@0: INCOMING_ARABICCHAR = 2 michael@0: }; michael@0: michael@0: /** michael@0: * Returns true if aChars/aLength are something that make a space michael@0: * character not be whitespace when they follow the space character. michael@0: * For now, this is true if and only if aChars starts with a ZWJ. (This michael@0: * is what Uniscribe assumes.) michael@0: */ michael@0: static bool michael@0: IsSpaceCombiningSequenceTail(const char16_t* aChars, int32_t aLength) { michael@0: return aLength > 0 && aChars[0] == 0x200D; // ZWJ michael@0: } michael@0: michael@0: enum CompressionMode { michael@0: COMPRESS_NONE, michael@0: COMPRESS_WHITESPACE, michael@0: COMPRESS_WHITESPACE_NEWLINE, michael@0: DISCARD_NEWLINE michael@0: }; michael@0: michael@0: /** michael@0: * Create a text run from a run of Unicode text. The text may have whitespace michael@0: * compressed. A preformatted tab is sent to the text run as a single space. michael@0: * (Tab spacing must be performed by textframe later.) Certain other michael@0: * characters are discarded. michael@0: * michael@0: * @param aCompressWhitespace control what is compressed to a michael@0: * single space character: no compression, compress spaces (not followed michael@0: * by combining mark) and tabs, compress those plus newlines, or michael@0: * no compression except newlines are discarded. michael@0: * @param aIncomingFlags a flag indicating whether there was whitespace michael@0: * or an Arabic character preceding this text. We set it to indicate if michael@0: * there's an Arabic character or whitespace preceding the end of this text. michael@0: */ michael@0: static char16_t* TransformText(const char16_t* aText, uint32_t aLength, michael@0: char16_t* aOutput, michael@0: CompressionMode aCompression, michael@0: uint8_t * aIncomingFlags, michael@0: gfxSkipChars* aSkipChars, michael@0: uint32_t* aAnalysisFlags); michael@0: michael@0: static uint8_t* TransformText(const uint8_t* aText, uint32_t aLength, michael@0: uint8_t* aOutput, michael@0: CompressionMode aCompression, michael@0: uint8_t * aIncomingFlags, michael@0: gfxSkipChars* aSkipChars, michael@0: uint32_t* aAnalysisFlags); michael@0: michael@0: static void michael@0: AppendLineBreakOffset(nsTArray* aArray, uint32_t aOffset) michael@0: { michael@0: if (aArray->Length() > 0 && (*aArray)[aArray->Length() - 1] == aOffset) michael@0: return; michael@0: aArray->AppendElement(aOffset); michael@0: } michael@0: michael@0: static uint32_t michael@0: ComputeApproximateLengthWithWhitespaceCompression(nsIContent *aContent, michael@0: const nsStyleText michael@0: *aStyleText); michael@0: }; michael@0: michael@0: class nsSkipCharsRunIterator { michael@0: public: michael@0: enum LengthMode { michael@0: LENGTH_UNSKIPPED_ONLY = false, michael@0: LENGTH_INCLUDES_SKIPPED = true michael@0: }; michael@0: nsSkipCharsRunIterator(const gfxSkipCharsIterator& aStart, michael@0: LengthMode aLengthIncludesSkipped, uint32_t aLength) michael@0: : mIterator(aStart), mRemainingLength(aLength), mRunLength(0), michael@0: mVisitSkipped(false), michael@0: mLengthIncludesSkipped(aLengthIncludesSkipped) { michael@0: } michael@0: void SetVisitSkipped() { mVisitSkipped = true; } michael@0: void SetOriginalOffset(int32_t aOffset) { michael@0: mIterator.SetOriginalOffset(aOffset); michael@0: } michael@0: void SetSkippedOffset(uint32_t aOffset) { michael@0: mIterator.SetSkippedOffset(aOffset); michael@0: } michael@0: michael@0: // guaranteed to return only positive-length runs michael@0: bool NextRun(); michael@0: bool IsSkipped() const { return mSkipped; } michael@0: // Always returns something > 0 michael@0: int32_t GetRunLength() const { return mRunLength; } michael@0: const gfxSkipCharsIterator& GetPos() const { return mIterator; } michael@0: int32_t GetOriginalOffset() const { return mIterator.GetOriginalOffset(); } michael@0: uint32_t GetSkippedOffset() const { return mIterator.GetSkippedOffset(); } michael@0: michael@0: private: michael@0: gfxSkipCharsIterator mIterator; michael@0: int32_t mRemainingLength; michael@0: int32_t mRunLength; michael@0: bool mSkipped; michael@0: bool mVisitSkipped; michael@0: bool mLengthIncludesSkipped; michael@0: }; michael@0: michael@0: #endif /*NSTEXTFRAMEUTILS_H_*/