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

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       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 "TextRenderer.h"
       7             : #include "FontData.h"
       8             : #include "ConsolasFontData.h"
       9             : #include "png.h"
      10             : #include "mozilla/Base64.h"
      11             : #include "mozilla/layers/Compositor.h"
      12             : #include "mozilla/layers/TextureHost.h"
      13             : #include "mozilla/layers/Effects.h"
      14             : 
      15             : namespace mozilla {
      16             : namespace layers {
      17             : 
      18             : using namespace gfx;
      19             : using namespace std;
      20             : 
      21             : const Float sBackgroundOpacity = 0.8f;
      22             : const SurfaceFormat sTextureFormat = SurfaceFormat::B8G8R8A8;
      23             : 
      24           0 : static void PNGAPI info_callback(png_structp png_ptr, png_infop info_ptr)
      25             : {
      26           0 :   png_read_update_info(png_ptr, info_ptr);
      27           0 : }
      28             : 
      29           0 : static void PNGAPI row_callback(png_structp png_ptr, png_bytep new_row, png_uint_32 row_num, int pass)
      30             : {
      31             :   MOZ_ASSERT(sTextureFormat == SurfaceFormat::B8G8R8A8);
      32             : 
      33             :   TextRenderer::FontCache* cache =
      34           0 :     static_cast<TextRenderer::FontCache*>(png_get_progressive_ptr(png_ptr));
      35             : 
      36           0 :   uint32_t* dst = (uint32_t*)(cache->mMap.mData + cache->mMap.mStride * row_num);
      37             : 
      38           0 :   for (uint32_t x = 0; x < cache->mInfo->mTextureWidth; x++) {
      39             :     // We blend to a transparent white background, this will make text readable
      40             :     // even if it's on a dark background. Without hurting our ability to
      41             :     // interact with the content behind the text.
      42           0 :     Float alphaValue = Float(0xFF - new_row[x]) / 255.0f;
      43           0 :     Float baseValue = sBackgroundOpacity * (1.0f - alphaValue);
      44           0 :     Color pixelColor(baseValue, baseValue, baseValue, baseValue + alphaValue);
      45           0 :     dst[x] = pixelColor.ToABGR();
      46             :   }
      47           0 : }
      48             : 
      49           0 : TextRenderer::~TextRenderer()
      50             : {
      51           0 : }
      52             : 
      53           0 : TextRenderer::FontCache::~FontCache()
      54             : {
      55           0 :   mGlyphBitmaps->Unmap();
      56           0 : }
      57             : 
      58             : void
      59           0 : TextRenderer::RenderText(Compositor* aCompositor,
      60             :                          const string& aText,
      61             :                          const IntPoint& aOrigin,
      62             :                          const Matrix4x4& aTransform, uint32_t aTextSize,
      63             :                          uint32_t aTargetPixelWidth,
      64             :                          FontType aFontType)
      65             : {
      66           0 :   const FontBitmapInfo* info = GetFontInfo(aFontType);
      67             : 
      68             :   // For now we only have a bitmap font with a 24px cell size, so we just
      69             :   // scale it up if the user wants larger text.
      70           0 :   Float scaleFactor = Float(aTextSize) / Float(info->mCellHeight);
      71           0 :   aTargetPixelWidth /= scaleFactor;
      72             : 
      73             :   RefPtr<TextureSource> src = RenderText(
      74             :     aCompositor,
      75             :     aText,
      76             :     aTextSize,
      77             :     aTargetPixelWidth,
      78           0 :     aFontType);
      79           0 :   if (!src) {
      80           0 :     return;
      81             :   }
      82             : 
      83           0 :   RefPtr<EffectRGB> effect = new EffectRGB(src, true, SamplingFilter::LINEAR);
      84           0 :   EffectChain chain;
      85           0 :   chain.mPrimaryEffect = effect;
      86             : 
      87           0 :   Matrix4x4 transform = aTransform;
      88           0 :   transform.PreScale(scaleFactor, scaleFactor, 1.0f);
      89             : 
      90           0 :   IntRect drawRect(aOrigin, src->GetSize());
      91           0 :   IntRect clip(-10000, -10000, 20000, 20000);
      92           0 :   aCompositor->DrawQuad(Rect(drawRect), clip, chain, 1.0f, transform);
      93             : }
      94             : 
      95             : RefPtr<TextureSource>
      96           0 : TextRenderer::RenderText(TextureSourceProvider* aProvider,
      97             :                          const string& aText,
      98             :                          uint32_t aTextSize,
      99             :                          uint32_t aTargetPixelWidth,
     100             :                          FontType aFontType)
     101             : {
     102           0 :   if (!EnsureInitialized(aFontType)) {
     103           0 :     return nullptr;
     104             :   }
     105             : 
     106           0 :   FontCache* cache = mFonts[aFontType].get();
     107           0 :   const FontBitmapInfo* info = cache->mInfo;
     108             : 
     109           0 :   uint32_t numLines = 1;
     110           0 :   uint32_t maxWidth = 0;
     111           0 :   uint32_t lineWidth = 0;
     112             :   // Calculate the size of the surface needed to draw all the glyphs.
     113           0 :   for (uint32_t i = 0; i < aText.length(); i++) {
     114             :     // Insert a line break if we go past the TargetPixelWidth.
     115             :     // XXX - this has the downside of overrunning the intended width, causing
     116             :     // things at the edge of a window to be cut off.
     117           0 :     if (aText[i] == '\n' || (aText[i] == ' ' && lineWidth > aTargetPixelWidth)) {
     118           0 :       numLines++;
     119           0 :       lineWidth = 0;
     120           0 :       continue;
     121             :     }
     122             : 
     123           0 :     lineWidth += info->GetGlyphWidth(aText[i]);
     124           0 :     maxWidth = std::max(lineWidth, maxWidth);
     125             :   }
     126             : 
     127             :   // Create a surface to draw our glyphs to.
     128             :   RefPtr<DataSourceSurface> textSurf =
     129           0 :     Factory::CreateDataSourceSurface(IntSize(maxWidth, numLines * info->mCellHeight), sTextureFormat);
     130           0 :   if (NS_WARN_IF(!textSurf)) {
     131           0 :     return nullptr;
     132             :   }
     133             : 
     134             :   DataSourceSurface::MappedSurface map;
     135           0 :   if (NS_WARN_IF(!textSurf->Map(DataSourceSurface::MapType::READ_WRITE, &map))) {
     136           0 :     return nullptr;
     137             :   }
     138             : 
     139             :   // Initialize the surface to transparent white.
     140           0 :   memset(map.mData, uint8_t(sBackgroundOpacity * 255.0f),
     141           0 :          numLines * info->mCellHeight * map.mStride);
     142             : 
     143           0 :   uint32_t currentXPos = 0;
     144           0 :   uint32_t currentYPos = 0;
     145             : 
     146           0 :   const unsigned int kGlyphsPerLine = info->mTextureWidth / info->mCellWidth;
     147             : 
     148             :   // Copy our glyphs onto the surface.
     149           0 :   for (uint32_t i = 0; i < aText.length(); i++) {
     150           0 :     if (aText[i] == '\n' || (aText[i] == ' ' && currentXPos > aTargetPixelWidth)) {
     151           0 :       currentYPos += info->mCellHeight;
     152           0 :       currentXPos = 0;
     153           0 :       continue;
     154             :     }
     155             : 
     156           0 :     uint32_t index = aText[i] - info->mFirstChar;
     157           0 :     uint32_t glyphXOffset = (index % kGlyphsPerLine) * info->mCellWidth * BytesPerPixel(sTextureFormat);
     158           0 :     uint32_t truncatedLine = index / kGlyphsPerLine;
     159           0 :     uint32_t glyphYOffset =  truncatedLine * info->mCellHeight * cache->mMap.mStride;
     160             : 
     161           0 :     uint32_t glyphWidth = info->GetGlyphWidth(aText[i]);
     162             : 
     163           0 :     for (uint32_t y = 0; y < info->mCellHeight; y++) {
     164           0 :       memcpy(map.mData + (y + currentYPos) * map.mStride + currentXPos * BytesPerPixel(sTextureFormat),
     165           0 :              cache->mMap.mData + glyphYOffset + y * cache->mMap.mStride + glyphXOffset,
     166           0 :              glyphWidth * BytesPerPixel(sTextureFormat));
     167             :     }
     168             : 
     169           0 :     currentXPos += glyphWidth;
     170             :   }
     171             : 
     172           0 :   textSurf->Unmap();
     173             : 
     174           0 :   RefPtr<DataTextureSource> src = aProvider->CreateDataTextureSource();
     175             : 
     176           0 :   if (!src->Update(textSurf)) {
     177             :     // Upload failed.
     178           0 :     return nullptr;
     179             :   }
     180             : 
     181           0 :   return src;
     182             : }
     183             : 
     184             : /* static */ const FontBitmapInfo*
     185           0 : TextRenderer::GetFontInfo(FontType aType)
     186             : {
     187           0 :   switch (aType) {
     188             :   case FontType::Default:
     189           0 :     return &sDefaultCompositorFont;
     190             :   case FontType::FixedWidth:
     191           0 :     return &sFixedWidthCompositorFont;
     192             :   default:
     193           0 :     MOZ_ASSERT_UNREACHABLE("unknown font type");
     194             :     return nullptr;
     195             :   }
     196             : }
     197             : 
     198             : bool
     199           0 : TextRenderer::EnsureInitialized(FontType aType)
     200             : {
     201           0 :   if (mFonts[aType]) {
     202           0 :     return true;
     203             :   }
     204             : 
     205           0 :   const FontBitmapInfo* info = GetFontInfo(aType);
     206             : 
     207           0 :   IntSize size(info->mTextureWidth, info->mTextureHeight);
     208           0 :   RefPtr<DataSourceSurface> surface = Factory::CreateDataSourceSurface(size, sTextureFormat);
     209           0 :   if (NS_WARN_IF(!surface)) {
     210           0 :     return false;
     211             :   }
     212             : 
     213             :   DataSourceSurface::MappedSurface map;
     214           0 :   if (NS_WARN_IF(!surface->Map(DataSourceSurface::MapType::READ_WRITE, &map))) {
     215           0 :     return false;
     216             :   }
     217             : 
     218           0 :   UniquePtr<FontCache> cache = MakeUnique<FontCache>();
     219           0 :   cache->mGlyphBitmaps = surface;
     220           0 :   cache->mMap = map;
     221           0 :   cache->mInfo = info;
     222             : 
     223           0 :   png_structp png_ptr = NULL;
     224           0 :   png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
     225             : 
     226           0 :   png_set_progressive_read_fn(png_ptr, cache.get(), info_callback, row_callback, nullptr);
     227           0 :   png_infop info_ptr = NULL;
     228           0 :   info_ptr = png_create_info_struct(png_ptr);
     229             : 
     230           0 :   png_process_data(png_ptr, info_ptr, (uint8_t*)info->mPNG, info->mPNGLength);
     231             : 
     232           0 :   png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
     233             : 
     234           0 :   mFonts[aType] = Move(cache);
     235           0 :   return true;
     236             : }
     237             : 
     238             : } // namespace layers
     239             : } // namespace mozilla

Generated by: LCOV version 1.13