Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/gfx/thebes/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 6 kB image not shown  

Quelle  gfxMathTable.cpp   Sprache: C

 
/* 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 http://mozilla.org/MPL/2.0/. */


#include "gfxMathTable.h"

#include "harfbuzz/hb.h"
#include "harfbuzz/hb-ot.h"

#define FloatToFixed(f) (65536 * (f))
#define FixedToFloat(f) ((f) * (1.0 / 65536.0))

using namespace mozilla;

gfxMathTable::gfxMathTable(hb_face_t* aFace, gfxFloat aSize) {
  mMathVariantCache.vertical = false;
  mHBFont = hb_font_create(aFace);
  if (mHBFont) {
    hb_font_set_ppem(mHBFont, aSize, aSize);
    uint32_t scale = FloatToFixed(aSize);
    hb_font_set_scale(mHBFont, scale, scale);
  }

  mMathVariantCache.glyphID = 0;
  ClearCache();
}

gfxMathTable::~gfxMathTable() {
  if (mHBFont) {
    hb_font_destroy(mHBFont);
  }
}

gfxFloat gfxMathTable::Constant(MathConstant aConstant) const {
  int32_t value = hb_ot_math_get_constant(
      mHBFont, static_cast<hb_ot_math_constant_t>(aConstant));
  if (aConstant == ScriptPercentScaleDown ||
      aConstant == ScriptScriptPercentScaleDown ||
      aConstant == RadicalDegreeBottomRaisePercent) {
    return value / 100.0;
  }
  return FixedToFloat(value);
}

gfxFloat gfxMathTable::ItalicsCorrection(uint32_t aGlyphID) const {
  return FixedToFloat(
      hb_ot_math_get_glyph_italics_correction(mHBFont, aGlyphID));
}

uint32_t gfxMathTable::VariantsSize(uint32_t aGlyphID, bool aVertical,
                                    uint16_t aSize) const {
  UpdateMathVariantCache(aGlyphID, aVertical);
  if (aSize < kMaxCachedSizeCount) {
    return mMathVariantCache.sizes[aSize];
  }

  // If the size index exceeds the cache size, we just read the value with
  // hb_ot_math_get_glyph_variants.
  hb_direction_t direction = aVertical ? HB_DIRECTION_BTT : HB_DIRECTION_LTR;
  hb_ot_math_glyph_variant_t variant;
  unsigned int count = 1;
  hb_ot_math_get_glyph_variants(mHBFont, aGlyphID, direction, aSize, &count,
                                &variant);
  return count > 0 ? variant.glyph : 0;
}

bool gfxMathTable::VariantsParts(uint32_t aGlyphID, bool aVertical,
                                 uint32_t aGlyphs[4]) const {
  UpdateMathVariantCache(aGlyphID, aVertical);
  memcpy(aGlyphs, mMathVariantCache.parts, sizeof(mMathVariantCache.parts));
  return mMathVariantCache.arePartsValid;
}

void gfxMathTable::ClearCache() const {
  memset(mMathVariantCache.sizes, 0, sizeof(mMathVariantCache.sizes));
  memset(mMathVariantCache.parts, 0, sizeof(mMathVariantCache.parts));
  mMathVariantCache.arePartsValid = false;
}

void gfxMathTable::UpdateMathVariantCache(uint32_t aGlyphID,
                                          bool aVertical) const {
  if (aGlyphID == mMathVariantCache.glyphID &&
      aVertical == mMathVariantCache.vertical)
    return;

  mMathVariantCache.glyphID = aGlyphID;
  mMathVariantCache.vertical = aVertical;
  ClearCache();

  // Cache the first size variants.
  hb_direction_t direction = aVertical ? HB_DIRECTION_BTT : HB_DIRECTION_LTR;
  hb_ot_math_glyph_variant_t variant[kMaxCachedSizeCount];
  unsigned int count = kMaxCachedSizeCount;
  hb_ot_math_get_glyph_variants(mHBFont, aGlyphID, direction, 0, &count,
                                variant);
  for (unsigned int i = 0; i < count; i++) {
    mMathVariantCache.sizes[i] = variant[i].glyph;
  }

  // Try and cache the parts of the glyph assembly.
  // XXXfredw The structure of the Open Type Math table is a bit more general
  // than the one currently used by the nsMathMLChar code, so we try to fallback
  // in reasonable way. We use the approach of the copyComponents function in
  // github.com/mathjax/MathJax-dev/blob/master/fonts/OpenTypeMath/fontUtil.py
  //
  // The nsMathMLChar code can use at most 3 non extender pieces (aGlyphs[0],
  // aGlyphs[1] and aGlyphs[2]) and the extenders between these pieces should
  // all be the same (aGlyphs[4]). Also, the parts of vertical assembly are
  // stored from bottom to top in the Open Type MATH table while they are
  // stored from top to bottom in nsMathMLChar.

  hb_ot_math_glyph_part_t parts[5];
  count = std::size(parts);
  unsigned int offset = 0;
  if (hb_ot_math_get_glyph_assembly(mHBFont, aGlyphID, direction, offset,
                                    &count, parts, NULL) > std::size(parts))
    return;                // Not supported: Too many pieces.
  if (count <= 0) return;  // Not supported: No pieces.

  // Count the number of non extender pieces
  uint16_t nonExtenderCount = 0;
  for (uint16_t i = 0; i < count; i++) {
    if (!(parts[i].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)) {
      nonExtenderCount++;
    }
  }
  if (nonExtenderCount > 3) {
    // Not supported: too many pieces
    return;
  }

  // Now browse the list of pieces

  // 0 = look for a left/bottom glyph
  // 1 = look for an extender between left/bottom and mid
  // 2 = look for a middle glyph
  // 3 = look for an extender between middle and right/top
  // 4 = look for a right/top glyph
  // 5 = no more piece expected
  uint8_t state = 0;

  // First extender char found.
  uint32_t extenderChar = 0;

  for (uint16_t i = 0; i < count; i++) {
    bool isExtender = parts[i].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER;
    uint32_t glyph = parts[i].glyph;

    if ((state == 1 || state == 2) && nonExtenderCount < 3) {
      // do not try to find a middle glyph
      state += 2;
    }

    if (isExtender) {
      if (!extenderChar) {
        extenderChar = glyph;
        mMathVariantCache.parts[3] = extenderChar;
      } else if (extenderChar != glyph) {
        // Not supported: different extenders
        return;
      }

      if (state == 0) {  // or state == 1
        // ignore left/bottom piece and multiple successive extenders
        state = 1;
      } else if (state == 2) {  // or state == 3
        // ignore middle piece and multiple successive extenders
        state = 3;
      } else if (state >= 4) {
        // Not supported: unexpected extender
        return;
      }

      continue;
    }

    if (state == 0) {
      // copy left/bottom part
      mMathVariantCache.parts[aVertical ? 2 : 0] = glyph;
      state = 1;
      continue;
    }

    if (state == 1 || state == 2) {
      // copy middle part
      mMathVariantCache.parts[1] = glyph;
      state = 3;
      continue;
    }

    if (state == 3 || state == 4) {
      // copy right/top part
      mMathVariantCache.parts[aVertical ? 0 : 2] = glyph;
      state = 5;
    }
  }

  mMathVariantCache.arePartsValid = true;
}

92%


¤ Dauer der Verarbeitung: 0.16 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.