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

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "gfxFontMissingGlyphs.h"
       7             : 
       8             : #include "gfxUtils.h"
       9             : #include "mozilla/gfx/2D.h"
      10             : #include "mozilla/gfx/Helpers.h"
      11             : #include "mozilla/gfx/PathHelpers.h"
      12             : #include "mozilla/RefPtr.h"
      13             : #include "nsDeviceContext.h"
      14             : #include "nsLayoutUtils.h"
      15             : 
      16             : using namespace mozilla;
      17             : using namespace mozilla::gfx;
      18             : 
      19             : #define CHAR_BITS(b00, b01, b02, b10, b11, b12, b20, b21, b22, b30, b31, b32, b40, b41, b42) \
      20             :   ((b00 << 0) | (b01 << 1) | (b02 << 2) | (b10 << 3) | (b11 << 4) | (b12 << 5) | \
      21             :    (b20 << 6) | (b21 << 7) | (b22 << 8) | (b30 << 9) | (b31 << 10) | (b32 << 11) | \
      22             :    (b40 << 12) | (b41 << 13) | (b42 << 14))
      23             : 
      24             : static const uint16_t glyphMicroFont[16] = {
      25             :   CHAR_BITS(0, 1, 0,
      26             :             1, 0, 1,
      27             :             1, 0, 1,
      28             :             1, 0, 1,
      29             :             0, 1, 0),
      30             :   CHAR_BITS(0, 1, 0,
      31             :             0, 1, 0,
      32             :             0, 1, 0,
      33             :             0, 1, 0,
      34             :             0, 1, 0),
      35             :   CHAR_BITS(1, 1, 1,
      36             :             0, 0, 1,
      37             :             1, 1, 1,
      38             :             1, 0, 0,
      39             :             1, 1, 1),
      40             :   CHAR_BITS(1, 1, 1,
      41             :             0, 0, 1,
      42             :             1, 1, 1,
      43             :             0, 0, 1,
      44             :             1, 1, 1),
      45             :   CHAR_BITS(1, 0, 1,
      46             :             1, 0, 1,
      47             :             1, 1, 1,
      48             :             0, 0, 1,
      49             :             0, 0, 1),
      50             :   CHAR_BITS(1, 1, 1,
      51             :             1, 0, 0,
      52             :             1, 1, 1,
      53             :             0, 0, 1,
      54             :             1, 1, 1),
      55             :   CHAR_BITS(1, 1, 1,
      56             :             1, 0, 0,
      57             :             1, 1, 1,
      58             :             1, 0, 1,
      59             :             1, 1, 1),
      60             :   CHAR_BITS(1, 1, 1,
      61             :             0, 0, 1,
      62             :             0, 0, 1,
      63             :             0, 0, 1,
      64             :             0, 0, 1),
      65             :   CHAR_BITS(0, 1, 0,
      66             :             1, 0, 1,
      67             :             0, 1, 0,
      68             :             1, 0, 1,
      69             :             0, 1, 0),
      70             :   CHAR_BITS(1, 1, 1,
      71             :             1, 0, 1,
      72             :             1, 1, 1,
      73             :             0, 0, 1,
      74             :             0, 0, 1),
      75             :   CHAR_BITS(1, 1, 1,
      76             :             1, 0, 1,
      77             :             1, 1, 1,
      78             :             1, 0, 1,
      79             :             1, 0, 1),
      80             :   CHAR_BITS(1, 1, 0,
      81             :             1, 0, 1,
      82             :             1, 1, 0,
      83             :             1, 0, 1,
      84             :             1, 1, 0),
      85             :   CHAR_BITS(0, 1, 1,
      86             :             1, 0, 0,
      87             :             1, 0, 0,
      88             :             1, 0, 0,
      89             :             0, 1, 1),
      90             :   CHAR_BITS(1, 1, 0,
      91             :             1, 0, 1,
      92             :             1, 0, 1,
      93             :             1, 0, 1,
      94             :             1, 1, 0),
      95             :   CHAR_BITS(1, 1, 1,
      96             :             1, 0, 0,
      97             :             1, 1, 1,
      98             :             1, 0, 0,
      99             :             1, 1, 1),
     100             :   CHAR_BITS(1, 1, 1,
     101             :             1, 0, 0,
     102             :             1, 1, 1,
     103             :             1, 0, 0,
     104             :             1, 0, 0)
     105             : };
     106             : 
     107             : /* Parameters that control the rendering of hexboxes. They look like this:
     108             : 
     109             :         BMP codepoints           non-BMP codepoints
     110             :       (U+0000 - U+FFFF)         (U+10000 - U+10FFFF)
     111             : 
     112             :          +---------+              +-------------+ 
     113             :          |         |              |             |
     114             :          | HHH HHH |              | HHH HHH HHH |
     115             :          | HHH HHH |              | HHH HHH HHH |
     116             :          | HHH HHH |              | HHH HHH HHH |
     117             :          | HHH HHH |              | HHH HHH HHH |
     118             :          | HHH HHH |              | HHH HHH HHH |
     119             :          |         |              |             |
     120             :          | HHH HHH |              | HHH HHH HHH |
     121             :          | HHH HHH |              | HHH HHH HHH |
     122             :          | HHH HHH |              | HHH HHH HHH |
     123             :          | HHH HHH |              | HHH HHH HHH |
     124             :          | HHH HHH |              | HHH HHH HHH |
     125             :          |         |              |             |
     126             :          +---------+              +-------------+
     127             : */
     128             : 
     129             : /** Width of a minifont glyph (see above) */
     130             : static const int MINIFONT_WIDTH = 3;
     131             : /** Height of a minifont glyph (see above) */
     132             : static const int MINIFONT_HEIGHT = 5;
     133             : /**
     134             :  * Gap between minifont glyphs (both horizontal and vertical) and also
     135             :  * the minimum desired gap between the box border and the glyphs
     136             :  */
     137             : static const int HEX_CHAR_GAP = 1;
     138             : /**
     139             :  * The amount of space between the vertical edge of the glyphbox and the
     140             :  * box border. We make this nonzero so that when multiple missing glyphs
     141             :  * occur consecutively there's a gap between their rendered boxes.
     142             :  */
     143             : static const int BOX_HORIZONTAL_INSET = 1;
     144             : /** The width of the border */
     145             : static const int BOX_BORDER_WIDTH = 1;
     146             : /**
     147             :  * The scaling factor for the border opacity; this is multiplied by the current
     148             :  * opacity being used to draw the text.
     149             :  */
     150             : static const Float BOX_BORDER_OPACITY = 0.5;
     151             : /**
     152             :  * Draw a single hex character using the current color. A nice way to do this
     153             :  * would be to fill in an A8 image surface and then use it as a mask
     154             :  * to paint the current color. Tragically this doesn't currently work with the
     155             :  * Quartz cairo backend which doesn't generally support masking with surfaces.
     156             :  * So for now we just paint a bunch of rectangles...
     157             :  */
     158             : #ifndef MOZ_GFX_OPTIMIZE_MOBILE
     159             : static void
     160           0 : DrawHexChar(uint32_t aDigit, const Point& aPt, DrawTarget& aDrawTarget,
     161             :             const Pattern &aPattern)
     162             : {
     163             :     // To avoid the potential for seams showing between rects when we're under
     164             :     // a transform we concat all the rects into a PathBuilder and fill the
     165             :     // resulting Path (rather than using DrawTarget::FillRect).
     166           0 :     RefPtr<PathBuilder> builder = aDrawTarget.CreatePathBuilder();
     167           0 :     uint32_t glyphBits = glyphMicroFont[aDigit];
     168           0 :     for (int y = 0; y < MINIFONT_HEIGHT; ++y) {
     169           0 :         for (int x = 0; x < MINIFONT_WIDTH; ++x) {
     170           0 :             if (glyphBits & 1) {
     171           0 :                 Rect r(aPt.x + x, aPt.y + y, 1, 1);
     172           0 :                 MaybeSnapToDevicePixels(r, aDrawTarget, true);
     173           0 :                 builder->MoveTo(r.TopLeft());
     174           0 :                 builder->LineTo(r.TopRight());
     175           0 :                 builder->LineTo(r.BottomRight());
     176           0 :                 builder->LineTo(r.BottomLeft());
     177           0 :                 builder->Close();
     178             :             }
     179           0 :             glyphBits >>= 1;
     180             :         }
     181             :     }
     182           0 :     RefPtr<Path> path = builder->Finish();
     183           0 :     aDrawTarget.Fill(path, aPattern);
     184           0 : }
     185             : #endif // MOZ_GFX_OPTIMIZE_MOBILE
     186             : 
     187             : void
     188           0 : gfxFontMissingGlyphs::DrawMissingGlyph(uint32_t aChar,
     189             :                                        const Rect& aRect,
     190             :                                        DrawTarget& aDrawTarget,
     191             :                                        const Pattern& aPattern,
     192             :                                        uint32_t aAppUnitsPerDevPixel)
     193             : {
     194             :     // If we're currently drawing with some kind of pattern, we just draw the
     195             :     // missing-glyph data in black.
     196           0 :     ColorPattern color = aPattern.GetType() == PatternType::COLOR ?
     197             :         static_cast<const ColorPattern&>(aPattern) :
     198           0 :         ColorPattern(ToDeviceColor(Color(0.f, 0.f, 0.f, 1.f)));
     199             : 
     200             :     // Stroke a rectangle so that the stroke's left edge is inset one pixel
     201             :     // from the left edge of the glyph box and the stroke's right edge
     202             :     // is inset one pixel from the right edge of the glyph box.
     203           0 :     Float halfBorderWidth = BOX_BORDER_WIDTH / 2.0;
     204           0 :     Float borderLeft = aRect.X() + BOX_HORIZONTAL_INSET + halfBorderWidth;
     205           0 :     Float borderRight = aRect.XMost() - BOX_HORIZONTAL_INSET - halfBorderWidth;
     206           0 :     Rect borderStrokeRect(borderLeft, aRect.Y() + halfBorderWidth,
     207             :                           borderRight - borderLeft,
     208           0 :                           aRect.Height() - 2.0 * halfBorderWidth);
     209           0 :     if (!borderStrokeRect.IsEmpty()) {
     210           0 :         ColorPattern adjustedColor = color;
     211           0 :         color.mColor.a *= BOX_BORDER_OPACITY;
     212             : #ifdef MOZ_GFX_OPTIMIZE_MOBILE
     213             :         aDrawTarget.FillRect(borderStrokeRect, adjustedColor);
     214             : #else
     215           0 :         StrokeOptions strokeOptions(BOX_BORDER_WIDTH);
     216           0 :         aDrawTarget.StrokeRect(borderStrokeRect, adjustedColor, strokeOptions);
     217             : #endif
     218             :     }
     219             : 
     220             : #ifndef MOZ_GFX_OPTIMIZE_MOBILE
     221           0 :     Point center = aRect.Center();
     222           0 :     Float halfGap = HEX_CHAR_GAP / 2.f;
     223           0 :     Float top = -(MINIFONT_HEIGHT + halfGap);
     224             :     // We always want integer scaling, otherwise the "bitmap" glyphs will look
     225             :     // even uglier than usual when zoomed
     226             :     int32_t devPixelsPerCSSPx =
     227           0 :         std::max<int32_t>(1, nsDeviceContext::AppUnitsPerCSSPixel() /
     228           0 :                              aAppUnitsPerDevPixel);
     229           0 :     AutoRestoreTransform autoRestoreTransform(&aDrawTarget);
     230             :     aDrawTarget.SetTransform(
     231           0 :       aDrawTarget.GetTransform().PreTranslate(center).
     232             :                                  PreScale(devPixelsPerCSSPx,
     233           0 :                                           devPixelsPerCSSPx));
     234           0 :     if (aChar < 0x10000) {
     235           0 :         if (aRect.Width() >= 2 * (MINIFONT_WIDTH + HEX_CHAR_GAP) &&
     236           0 :             aRect.Height() >= 2 * MINIFONT_HEIGHT + HEX_CHAR_GAP) {
     237             :             // Draw 4 digits for BMP
     238           0 :             Float left = -(MINIFONT_WIDTH + halfGap);
     239           0 :             DrawHexChar((aChar >> 12) & 0xF,
     240           0 :                         Point(left, top), aDrawTarget, color);
     241           0 :             DrawHexChar((aChar >> 8) & 0xF,
     242           0 :                         Point(halfGap, top), aDrawTarget, color);
     243           0 :             DrawHexChar((aChar >> 4) & 0xF,
     244           0 :                         Point(left, halfGap), aDrawTarget, color);
     245           0 :             DrawHexChar(aChar & 0xF,
     246           0 :                         Point(halfGap, halfGap), aDrawTarget, color);
     247             :         }
     248             :     } else {
     249           0 :         if (aRect.Width() >= 3 * (MINIFONT_WIDTH + HEX_CHAR_GAP) &&
     250           0 :             aRect.Height() >= 2 * MINIFONT_HEIGHT + HEX_CHAR_GAP) {
     251             :             // Draw 6 digits for non-BMP
     252           0 :             Float first = -(MINIFONT_WIDTH * 1.5 + HEX_CHAR_GAP);
     253           0 :             Float second = -(MINIFONT_WIDTH / 2.0);
     254           0 :             Float third = (MINIFONT_WIDTH / 2.0 + HEX_CHAR_GAP);
     255           0 :             DrawHexChar((aChar >> 20) & 0xF,
     256           0 :                         Point(first, top), aDrawTarget, color);
     257           0 :             DrawHexChar((aChar >> 16) & 0xF,
     258           0 :                         Point(second, top), aDrawTarget, color);
     259           0 :             DrawHexChar((aChar >> 12) & 0xF,
     260           0 :                         Point(third, top), aDrawTarget, color);
     261           0 :             DrawHexChar((aChar >> 8) & 0xF,
     262           0 :                         Point(first, halfGap), aDrawTarget, color);
     263           0 :             DrawHexChar((aChar >> 4) & 0xF,
     264           0 :                         Point(second, halfGap), aDrawTarget, color);
     265           0 :             DrawHexChar(aChar & 0xF,
     266           0 :                         Point(third, halfGap), aDrawTarget, color);
     267             :         }
     268             :     }
     269             : #endif
     270           0 : }
     271             : 
     272             : Float
     273           0 : gfxFontMissingGlyphs::GetDesiredMinWidth(uint32_t aChar,
     274             :                                          uint32_t aAppUnitsPerDevPixel)
     275             : {
     276             : /**
     277             :  * The minimum desired width for a missing-glyph glyph box. I've laid it out
     278             :  * like this so you can see what goes where.
     279             :  */
     280             :     Float width = BOX_HORIZONTAL_INSET + BOX_BORDER_WIDTH + HEX_CHAR_GAP +
     281             :         MINIFONT_WIDTH + HEX_CHAR_GAP + MINIFONT_WIDTH +
     282             :          ((aChar < 0x10000) ? 0 : HEX_CHAR_GAP + MINIFONT_WIDTH) +
     283           0 :         HEX_CHAR_GAP + BOX_BORDER_WIDTH + BOX_HORIZONTAL_INSET;
     284             :     // Note that this will give us floating-point division, so the width will
     285             :     // -not- be snapped to integer multiples of its basic pixel value
     286           0 :     width *= Float(nsDeviceContext::AppUnitsPerCSSPixel()) / aAppUnitsPerDevPixel;
     287           0 :     return width;
     288             : }

Generated by: LCOV version 1.13