LCOV - code coverage report
Current view: top level - gfx/thebes - gfxMathTable.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 96 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 8 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* This Source Code Form is subject to the terms of the Mozilla Public
       2             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       3             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       4             : 
       5             : #include "gfxMathTable.h"
       6             : 
       7             : #include "harfbuzz/hb.h"
       8             : #include "harfbuzz/hb-ot.h"
       9             : 
      10             : #define FloatToFixed(f) (65536 * (f))
      11             : #define FixedToFloat(f) ((f) * (1.0 / 65536.0))
      12             : 
      13             : using namespace mozilla;
      14             : 
      15           0 : gfxMathTable::gfxMathTable(hb_face_t *aFace, gfxFloat aSize)
      16             : {
      17           0 :   mHBFont = hb_font_create(aFace);
      18           0 :   if (mHBFont) {
      19           0 :     hb_font_set_ppem(mHBFont, aSize, aSize);
      20           0 :     uint32_t scale = FloatToFixed(aSize);
      21           0 :     hb_font_set_scale(mHBFont, scale, scale);
      22             :   }
      23             : 
      24           0 :   mMathVariantCache.glyphID = 0;
      25           0 :   ClearCache();
      26           0 : }
      27             : 
      28           0 : gfxMathTable::~gfxMathTable()
      29             : {
      30           0 :   if (mHBFont) {
      31           0 :       hb_font_destroy(mHBFont);
      32             :   }
      33           0 : }
      34             : 
      35             : gfxFloat
      36           0 : gfxMathTable::Constant(MathConstant aConstant) const
      37             : {
      38           0 :   int32_t value = hb_ot_math_get_constant(mHBFont, static_cast<hb_ot_math_constant_t>(aConstant));
      39           0 :   if (aConstant == ScriptPercentScaleDown ||
      40           0 :       aConstant == ScriptScriptPercentScaleDown ||
      41             :       aConstant == RadicalDegreeBottomRaisePercent) {
      42           0 :     return value / 100.0;
      43             :   }
      44           0 :   return FixedToFloat(value);
      45             : }
      46             : 
      47             : gfxFloat
      48           0 : gfxMathTable::ItalicsCorrection(uint32_t aGlyphID) const
      49             : {
      50           0 :   return FixedToFloat(hb_ot_math_get_glyph_italics_correction(mHBFont, aGlyphID));
      51             : }
      52             : 
      53             : uint32_t
      54           0 : gfxMathTable::VariantsSize(uint32_t aGlyphID, bool aVertical,
      55             :                            uint16_t aSize) const
      56             : {
      57           0 :   UpdateMathVariantCache(aGlyphID, aVertical);
      58           0 :   if (aSize < kMaxCachedSizeCount) {
      59           0 :     return mMathVariantCache.sizes[aSize];
      60             :   }
      61             : 
      62             :   // If the size index exceeds the cache size, we just read the value with
      63             :   // hb_ot_math_get_glyph_variants.
      64           0 :   hb_direction_t direction = aVertical ? HB_DIRECTION_BTT : HB_DIRECTION_LTR;
      65             :   hb_ot_math_glyph_variant_t variant;
      66           0 :   unsigned int count = 1;
      67           0 :   hb_ot_math_get_glyph_variants(mHBFont, aGlyphID, direction, aSize, &count,
      68           0 :                                 &variant);
      69           0 :   return count > 0 ? variant.glyph : 0;
      70             : }
      71             : 
      72             : bool
      73           0 : gfxMathTable::VariantsParts(uint32_t aGlyphID, bool aVertical,
      74             :                             uint32_t aGlyphs[4]) const
      75             : {
      76           0 :   UpdateMathVariantCache(aGlyphID, aVertical);
      77           0 :   memcpy(aGlyphs, mMathVariantCache.parts, sizeof(mMathVariantCache.parts));
      78           0 :   return mMathVariantCache.arePartsValid;
      79             : }
      80             : 
      81             : void
      82           0 : gfxMathTable::ClearCache() const
      83             : {
      84           0 :   memset(mMathVariantCache.sizes, 0, sizeof(mMathVariantCache.sizes));
      85           0 :   memset(mMathVariantCache.parts, 0, sizeof(mMathVariantCache.parts));
      86           0 :   mMathVariantCache.arePartsValid = false;
      87           0 : }
      88             : 
      89             : void
      90           0 : gfxMathTable::UpdateMathVariantCache(uint32_t aGlyphID, bool aVertical) const
      91             : {
      92           0 :   if (aGlyphID == mMathVariantCache.glyphID &&
      93           0 :       aVertical == mMathVariantCache.vertical)
      94           0 :     return;
      95             : 
      96           0 :   mMathVariantCache.glyphID = aGlyphID;
      97           0 :   mMathVariantCache.vertical = aVertical;
      98           0 :   ClearCache();
      99             : 
     100             :   // Cache the first size variants.
     101           0 :   hb_direction_t direction = aVertical ? HB_DIRECTION_BTT : HB_DIRECTION_LTR;
     102             :   hb_ot_math_glyph_variant_t variant[kMaxCachedSizeCount];
     103           0 :   unsigned int count = kMaxCachedSizeCount;
     104           0 :   hb_ot_math_get_glyph_variants(mHBFont, aGlyphID, direction, 0, &count,
     105           0 :                                 variant);
     106           0 :   for (unsigned int i = 0; i < count; i++) {
     107           0 :     mMathVariantCache.sizes[i] = variant[i].glyph;
     108             :   }
     109             : 
     110             :   // Try and cache the parts of the glyph assembly.
     111             :   // XXXfredw The structure of the Open Type Math table is a bit more general
     112             :   // than the one currently used by the nsMathMLChar code, so we try to fallback
     113             :   // in reasonable way. We use the approach of the copyComponents function in
     114             :   // github.com/mathjax/MathJax-dev/blob/master/fonts/OpenTypeMath/fontUtil.py
     115             :   //
     116             :   // The nsMathMLChar code can use at most 3 non extender pieces (aGlyphs[0],
     117             :   // aGlyphs[1] and aGlyphs[2]) and the extenders between these pieces should
     118             :   // all be the same (aGlyphs[4]). Also, the parts of vertical assembly are
     119             :   // stored from bottom to top in the Open Type MATH table while they are
     120             :   // stored from top to bottom in nsMathMLChar.
     121             : 
     122             :   hb_ot_math_glyph_part_t parts[5];
     123           0 :   count = MOZ_ARRAY_LENGTH(parts);
     124           0 :   unsigned int offset = 0;
     125           0 :   if (hb_ot_math_get_glyph_assembly(mHBFont, aGlyphID, direction, offset, &count, parts, NULL) > MOZ_ARRAY_LENGTH(parts))
     126           0 :     return; // Not supported: Too many pieces.
     127           0 :   if (count <= 0)
     128           0 :     return; // Not supported: No pieces.
     129             : 
     130             :   // Count the number of non extender pieces
     131           0 :   uint16_t nonExtenderCount = 0;
     132           0 :   for (uint16_t i = 0; i < count; i++) {
     133           0 :     if (!(parts[i].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)) {
     134           0 :       nonExtenderCount++;
     135             :     }
     136             :   }
     137           0 :   if (nonExtenderCount > 3) {
     138             :     // Not supported: too many pieces
     139           0 :     return;
     140             :   }
     141             : 
     142             :   // Now browse the list of pieces
     143             : 
     144             :   // 0 = look for a left/bottom glyph
     145             :   // 1 = look for an extender between left/bottom and mid
     146             :   // 2 = look for a middle glyph
     147             :   // 3 = look for an extender between middle and right/top
     148             :   // 4 = look for a right/top glyph
     149             :   // 5 = no more piece expected
     150           0 :   uint8_t state = 0;
     151             : 
     152             :   // First extender char found.
     153           0 :   uint32_t extenderChar = 0;
     154             : 
     155           0 :   for (uint16_t i = 0; i < count; i++) {
     156             : 
     157           0 :     bool isExtender = parts[i].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER;
     158           0 :     uint32_t glyph = parts[i].glyph;
     159             : 
     160           0 :     if ((state == 1 || state == 2) && nonExtenderCount < 3) {
     161             :       // do not try to find a middle glyph
     162           0 :       state += 2;
     163             :     }
     164             : 
     165           0 :     if (isExtender) {
     166           0 :       if (!extenderChar) {
     167           0 :         extenderChar = glyph;
     168           0 :         mMathVariantCache.parts[3] = extenderChar;
     169           0 :       } else if (extenderChar != glyph)  {
     170             :         // Not supported: different extenders
     171           0 :         return;
     172             :       }
     173             : 
     174           0 :       if (state == 0) { // or state == 1
     175             :         // ignore left/bottom piece and multiple successive extenders
     176           0 :         state = 1;
     177           0 :       } else if (state == 2) { // or state == 3
     178             :         // ignore middle piece and multiple successive extenders
     179           0 :         state = 3;
     180           0 :       } else if (state >= 4) {
     181             :         // Not supported: unexpected extender
     182           0 :         return;
     183             :       }
     184             : 
     185           0 :       continue;
     186             :     }
     187             : 
     188           0 :     if (state == 0) {
     189             :       // copy left/bottom part
     190           0 :       mMathVariantCache.parts[aVertical ? 2 : 0] = glyph;
     191           0 :       state = 1;
     192           0 :       continue;
     193             :     }
     194             : 
     195           0 :     if (state == 1 || state == 2) {
     196             :       // copy middle part
     197           0 :       mMathVariantCache.parts[1] = glyph;
     198           0 :       state = 3;
     199           0 :       continue;
     200             :     }
     201             : 
     202           0 :     if (state == 3 || state == 4) {
     203             :       // copy right/top part
     204           0 :       mMathVariantCache.parts[aVertical ? 0 : 2] = glyph;
     205           0 :       state = 5;
     206             :     }
     207             : 
     208             :   }
     209             : 
     210           0 :   mMathVariantCache.arePartsValid = true;
     211             : }

Generated by: LCOV version 1.13