layout/generic/nsTextRunTransformations.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/generic/nsTextRunTransformations.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,175 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     1.5 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifndef NSTEXTRUNTRANSFORMATIONS_H_
    1.10 +#define NSTEXTRUNTRANSFORMATIONS_H_
    1.11 +
    1.12 +#include "mozilla/Attributes.h"
    1.13 +#include "mozilla/MemoryReporting.h"
    1.14 +#include "gfxFont.h"
    1.15 +
    1.16 +class nsTransformedTextRun;
    1.17 +class nsStyleContext;
    1.18 +
    1.19 +class nsTransformingTextRunFactory {
    1.20 +public:
    1.21 +  virtual ~nsTransformingTextRunFactory() {}
    1.22 +
    1.23 +  // Default 8-bit path just transforms to Unicode and takes that path
    1.24 +  nsTransformedTextRun* MakeTextRun(const uint8_t* aString, uint32_t aLength,
    1.25 +                                    const gfxFontGroup::Parameters* aParams,
    1.26 +                                    gfxFontGroup* aFontGroup, uint32_t aFlags,
    1.27 +                                    nsStyleContext** aStyles, bool aOwnsFactory = true);
    1.28 +  nsTransformedTextRun* MakeTextRun(const char16_t* aString, uint32_t aLength,
    1.29 +                                    const gfxFontGroup::Parameters* aParams,
    1.30 +                                    gfxFontGroup* aFontGroup, uint32_t aFlags,
    1.31 +                                    nsStyleContext** aStyles, bool aOwnsFactory = true);
    1.32 +
    1.33 +  virtual void RebuildTextRun(nsTransformedTextRun* aTextRun, gfxContext* aRefContext) = 0;
    1.34 +};
    1.35 +
    1.36 +/**
    1.37 + * Builds textruns that render their text using a font-variant (i.e.,
    1.38 + * smallcaps).
    1.39 + */
    1.40 +class nsFontVariantTextRunFactory : public nsTransformingTextRunFactory {
    1.41 +public:
    1.42 +  virtual void RebuildTextRun(nsTransformedTextRun* aTextRun, gfxContext* aRefContext) MOZ_OVERRIDE;
    1.43 +};
    1.44 +
    1.45 +/**
    1.46 + * Builds textruns that transform the text in some way (e.g., capitalize)
    1.47 + * and then render the text using some other textrun implementation.
    1.48 + */
    1.49 +class nsCaseTransformTextRunFactory : public nsTransformingTextRunFactory {
    1.50 +public:
    1.51 +  // We could add an optimization here so that when there is no inner
    1.52 +  // factory, no title-case conversion, and no upper-casing of SZLIG, we override
    1.53 +  // MakeTextRun (after making it virtual in the superclass) and have it
    1.54 +  // just convert the string to uppercase or lowercase and create the textrun
    1.55 +  // via the fontgroup.
    1.56 +  
    1.57 +  // Takes ownership of aInnerTransformTextRunFactory
    1.58 +  nsCaseTransformTextRunFactory(nsTransformingTextRunFactory* aInnerTransformingTextRunFactory,
    1.59 +                                bool aAllUppercase = false)
    1.60 +    : mInnerTransformingTextRunFactory(aInnerTransformingTextRunFactory),
    1.61 +      mAllUppercase(aAllUppercase) {}
    1.62 +
    1.63 +  virtual void RebuildTextRun(nsTransformedTextRun* aTextRun, gfxContext* aRefContext) MOZ_OVERRIDE;
    1.64 +
    1.65 +protected:
    1.66 +  nsAutoPtr<nsTransformingTextRunFactory> mInnerTransformingTextRunFactory;
    1.67 +  bool                                    mAllUppercase;
    1.68 +};
    1.69 +
    1.70 +/**
    1.71 + * So that we can reshape as necessary, we store enough information
    1.72 + * to fully rebuild the textrun contents.
    1.73 + */
    1.74 +class nsTransformedTextRun : public gfxTextRun {
    1.75 +public:
    1.76 +  static nsTransformedTextRun *Create(const gfxTextRunFactory::Parameters* aParams,
    1.77 +                                      nsTransformingTextRunFactory* aFactory,
    1.78 +                                      gfxFontGroup* aFontGroup,
    1.79 +                                      const char16_t* aString, uint32_t aLength,
    1.80 +                                      const uint32_t aFlags, nsStyleContext** aStyles,
    1.81 +                                      bool aOwnsFactory);
    1.82 +
    1.83 +  ~nsTransformedTextRun() {
    1.84 +    if (mOwnsFactory) {
    1.85 +      delete mFactory;
    1.86 +    }
    1.87 +  }
    1.88 +  
    1.89 +  void SetCapitalization(uint32_t aStart, uint32_t aLength,
    1.90 +                         bool* aCapitalization,
    1.91 +                         gfxContext* aRefContext);
    1.92 +  virtual bool SetPotentialLineBreaks(uint32_t aStart, uint32_t aLength,
    1.93 +                                        uint8_t* aBreakBefore,
    1.94 +                                        gfxContext* aRefContext);
    1.95 +  /**
    1.96 +   * Called after SetCapitalization and SetPotentialLineBreaks
    1.97 +   * are done and before we request any data from the textrun. Also always
    1.98 +   * called after a Create.
    1.99 +   */
   1.100 +  void FinishSettingProperties(gfxContext* aRefContext)
   1.101 +  {
   1.102 +    if (mNeedsRebuild) {
   1.103 +      mNeedsRebuild = false;
   1.104 +      mFactory->RebuildTextRun(this, aRefContext);
   1.105 +    }
   1.106 +  }
   1.107 +
   1.108 +  // override the gfxTextRun impls to account for additional members here
   1.109 +  virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) MOZ_MUST_OVERRIDE;
   1.110 +  virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) MOZ_MUST_OVERRIDE;
   1.111 +
   1.112 +  nsTransformingTextRunFactory       *mFactory;
   1.113 +  nsTArray<nsRefPtr<nsStyleContext> > mStyles;
   1.114 +  nsTArray<bool>                      mCapitalize;
   1.115 +  nsString                            mString;
   1.116 +  bool                                mOwnsFactory;
   1.117 +  bool                                mNeedsRebuild;
   1.118 +
   1.119 +private:
   1.120 +  nsTransformedTextRun(const gfxTextRunFactory::Parameters* aParams,
   1.121 +                       nsTransformingTextRunFactory* aFactory,
   1.122 +                       gfxFontGroup* aFontGroup,
   1.123 +                       const char16_t* aString, uint32_t aLength,
   1.124 +                       const uint32_t aFlags, nsStyleContext** aStyles,
   1.125 +                       bool aOwnsFactory)
   1.126 +    : gfxTextRun(aParams, aLength, aFontGroup, aFlags),
   1.127 +      mFactory(aFactory), mString(aString, aLength),
   1.128 +      mOwnsFactory(aOwnsFactory), mNeedsRebuild(true)
   1.129 +  {
   1.130 +    mCharacterGlyphs = reinterpret_cast<CompressedGlyph*>(this + 1);
   1.131 +
   1.132 +    uint32_t i;
   1.133 +    for (i = 0; i < aLength; ++i) {
   1.134 +      mStyles.AppendElement(aStyles[i]);
   1.135 +    }
   1.136 +  }
   1.137 +};
   1.138 +
   1.139 +/**
   1.140 + * Copy a given textrun, but merge certain characters into a single logical
   1.141 + * character. Glyphs for a character are added to the glyph list for the previous
   1.142 + * character and then the merged character is eliminated. Visually the results
   1.143 + * are identical.
   1.144 + *
   1.145 + * This is used for text-transform:uppercase when we encounter a SZLIG,
   1.146 + * whose uppercase form is "SS", or other ligature or precomposed form
   1.147 + * that expands to multiple codepoints during case transformation,
   1.148 + * and for Greek text when combining diacritics have been deleted.
   1.149 + *
   1.150 + * This function is unable to merge characters when they occur in different
   1.151 + * glyph runs. This only happens in tricky edge cases where a character was
   1.152 + * decomposed by case-mapping (e.g. there's no precomposed uppercase version
   1.153 + * of an accented lowercase letter), and then font-matching caused the
   1.154 + * diacritics to be assigned to a different font than the base character.
   1.155 + * In this situation, the diacritic(s) get discarded, which is less than
   1.156 + * ideal, but they probably weren't going to render very well anyway.
   1.157 + * Bug 543200 will improve this by making font-matching operate on entire
   1.158 + * clusters instead of individual codepoints.
   1.159 + *
   1.160 + * For simplicity, this produces a textrun containing all DetailedGlyphs,
   1.161 + * no simple glyphs. So don't call it unless you really have merging to do.
   1.162 + *
   1.163 + * @param aCharsToMerge when aCharsToMerge[i] is true, this character in aSrc
   1.164 + * is merged into the previous character
   1.165 + *
   1.166 + * @param aDeletedChars when aDeletedChars[i] is true, the character at this
   1.167 + * position in aDest was deleted (has no corresponding char in aSrc)
   1.168 + */
   1.169 +void
   1.170 +MergeCharactersInTextRun(gfxTextRun* aDest, gfxTextRun* aSrc,
   1.171 +                         const bool* aCharsToMerge, const bool* aDeletedChars);
   1.172 +
   1.173 +gfxTextRunFactory::Parameters
   1.174 +GetParametersForInner(nsTransformedTextRun* aTextRun, uint32_t* aFlags,
   1.175 +                      gfxContext* aRefContext);
   1.176 +
   1.177 +
   1.178 +#endif /*NSTEXTRUNTRANSFORMATIONS_H_*/

mercurial