author moz-wptsync-bot <>
Thu, 08 Nov 2018 08:22:51 +0000
changeset 506788 f62150dda3664620284888933718cef568d96558
parent 459284 e9b8c798e67de86db459ce020218664487744270
child 508163 6f3709b3878117466168c40affa7bca0b60cf75b
permissions -rw-r--r--
Bug 1505638 [wpt PR 13972] - Update wpt metadata, a=testonly wpt-pr: 13972 wpt-type: metadata

/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at */


#include "gfxFont.h"

#include "harfbuzz/hb.h"
#include "nsUnicodeProperties.h"
#include "mozilla/gfx/2D.h"

class gfxHarfBuzzShaper : public gfxFontShaper {
    explicit gfxHarfBuzzShaper(gfxFont *aFont);
    virtual ~gfxHarfBuzzShaper();

     * For HarfBuzz font callback functions, font_data is a ptr to a
     * FontCallbackData struct
    struct FontCallbackData {
        gfxHarfBuzzShaper* mShaper;
        // initialized to a DrawTarget owned by our caller on every call to
        // ShapeText
        mozilla::gfx::DrawTarget* MOZ_NON_OWNING_REF mDrawTarget;

    bool Initialize();

    bool ShapeText(DrawTarget      *aDrawTarget,
                   const char16_t *aText,
                   uint32_t         aOffset,
                   uint32_t         aLength,
                   Script           aScript,
                   bool             aVertical,
                   RoundingFlags    aRounding,
                   gfxShapedText   *aShapedText) override;

    // get a given font table in harfbuzz blob form
    hb_blob_t * GetFontTable(hb_tag_t aTag) const;

    // map unicode character to glyph ID
    hb_codepoint_t GetNominalGlyph(hb_codepoint_t unicode) const;
    hb_codepoint_t GetVariationGlyph(hb_codepoint_t unicode,
                                     hb_codepoint_t variation_selector) const;

    // get harfbuzz glyph advance, in font design units
    hb_position_t GetGlyphHAdvance(hb_codepoint_t glyph) const;

    hb_position_t GetGlyphVAdvance(hb_codepoint_t glyph) const;

    void GetGlyphVOrigin(mozilla::gfx::DrawTarget& aDT,
                         hb_codepoint_t aGlyph,
                         hb_position_t *aX, hb_position_t *aY) const;

    // get harfbuzz horizontal advance in 16.16 fixed point format.
    static hb_position_t
    HBGetGlyphHAdvance(hb_font_t *font, void *font_data,
                       hb_codepoint_t glyph, void *user_data);

    // get harfbuzz vertical advance in 16.16 fixed point format.
    static hb_position_t
    HBGetGlyphVAdvance(hb_font_t *font, void *font_data,
                       hb_codepoint_t glyph, void *user_data);

    static hb_bool_t
    HBGetGlyphVOrigin(hb_font_t *font, void *font_data,
                      hb_codepoint_t glyph,
                      hb_position_t *x, hb_position_t *y,
                      void *user_data);

    hb_position_t GetHKerning(uint16_t aFirstGlyph,
                              uint16_t aSecondGlyph) const;

    hb_bool_t GetGlyphExtents(hb_codepoint_t aGlyph,
                              hb_glyph_extents_t *aExtents) const;

    bool UseVerticalPresentationForms() const
        return mUseVerticalPresentationForms;

    static hb_script_t
    GetHBScriptUsedForShaping(Script aScript) {
        // Decide what harfbuzz script code will be used for shaping
        hb_script_t hbScript;
        if (aScript <= Script::INHERITED) {
            // For unresolved "common" or "inherited" runs,
            // default to Latin for now.
            hbScript = HB_SCRIPT_LATIN;
        } else {
            hbScript =
        return hbScript;

    static hb_codepoint_t
    GetVerticalPresentationForm(hb_codepoint_t aUnicode);

    nsresult SetGlyphsFromRun(gfxShapedText  *aShapedText,
                              uint32_t        aOffset,
                              uint32_t        aLength,
                              const char16_t *aText,
                              bool            aVertical,
                              RoundingFlags   aRounding);

    // retrieve glyph positions, applying advance adjustments and attachments
    // returns results in appUnits
    nscoord GetGlyphPositions(gfxContext *aContext,
                              nsTArray<nsPoint>& aPositions,
                              uint32_t aAppUnitsPerDevUnit);

    void InitializeVertical();
    bool LoadHmtxTable();

    struct Glyf { // we only need the bounding-box at the beginning
                  // of the glyph record, not the actual outline data
        mozilla::AutoSwap_PRInt16 numberOfContours;
        mozilla::AutoSwap_PRInt16 xMin;
        mozilla::AutoSwap_PRInt16 yMin;
        mozilla::AutoSwap_PRInt16 xMax;
        mozilla::AutoSwap_PRInt16 yMax;

    const Glyf *FindGlyf(hb_codepoint_t aGlyph, bool *aEmptyGlyf) const;

    // harfbuzz face object: we acquire a reference from the font entry
    // on shaper creation, and release it in our destructor
    hb_face_t         *mHBFace;

    // size-specific font object, owned by the gfxHarfBuzzShaper
    hb_font_t         *mHBFont;

    // harfbuzz buffer for the shaping process
    hb_buffer_t       *mBuffer;

    FontCallbackData   mCallbackData;

    // Following table references etc are declared "mutable" because the
    // harfbuzz callback functions take a const ptr to the shaper, but
    // wish to cache tables here to avoid repeatedly looking them up
    // in the font.

    // Old-style TrueType kern table, if we're not doing GPOS kerning
    mutable hb_blob_t *mKernTable;

    // Cached copy of the hmtx table.
    mutable hb_blob_t *mHmtxTable;

    // For vertical fonts, cached vmtx and VORG table, if present.
    mutable hb_blob_t *mVmtxTable;
    mutable hb_blob_t *mVORGTable;
    // And for vertical TrueType (not CFF) fonts that have vmtx,
    // we also use loca and glyf to get glyph bounding boxes.
    mutable hb_blob_t *mLocaTable;
    mutable hb_blob_t *mGlyfTable;

    // Cached pointer to cmap subtable to be used for char-to-glyph mapping.
    // This comes from GetFontTablePtr; if it is non-null, our destructor
    // must call ReleaseFontTablePtr to avoid permanently caching the table.
    mutable hb_blob_t *mCmapTable;
    mutable int32_t    mCmapFormat;
    mutable uint32_t   mSubtableOffset;
    mutable uint32_t   mUVSTableOffset;

    // Cached copy of numLongMetrics field from the hhea table,
    // for use when looking up glyph metrics; initialized to 0 by the
    // constructor so we can tell it hasn't been set yet.
    // This is a signed value so that we can use -1 to indicate
    // an error (if the hhea table was not available).
    mutable int32_t    mNumLongHMetrics;
    // Similarly for vhea if it's a vertical font.
    mutable int32_t    mNumLongVMetrics;

    // Default y-coordinate for glyph vertical origin, used if the font
    // does not actually have vertical-layout metrics.
    mutable gfxFloat mDefaultVOrg;

    // Whether the font implements GetGlyph, or we should read tables
    // directly
    bool mUseFontGetGlyph;
    // Whether the font implements GetGlyphWidth, or we should read tables
    // directly to get ideal widths
    bool mUseFontGlyphWidths;

    bool mInitialized;
    bool mVerticalInitialized;

    // Whether to use vertical presentation forms for CJK characters
    // when available (only set if the 'vert' feature is not available).
    bool mUseVerticalPresentationForms;

    // these are set from the FindGlyf callback on first use of the glyf data
    mutable bool mLoadedLocaGlyf;
    mutable bool mLocaLongOffsets;