diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /gfx/layers/composite/TextRenderer.cpp | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'gfx/layers/composite/TextRenderer.cpp')
-rw-r--r-- | gfx/layers/composite/TextRenderer.cpp | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/gfx/layers/composite/TextRenderer.cpp b/gfx/layers/composite/TextRenderer.cpp new file mode 100644 index 000000000..be59cb246 --- /dev/null +++ b/gfx/layers/composite/TextRenderer.cpp @@ -0,0 +1,173 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 "TextRenderer.h" +#include "FontData.h" +#include "png.h" +#include "mozilla/Base64.h" +#include "mozilla/layers/Compositor.h" +#include "mozilla/layers/TextureHost.h" +#include "mozilla/layers/Effects.h" + +namespace mozilla { +namespace layers { + +using namespace gfx; +using namespace std; + +const Float sBackgroundOpacity = 0.6f; +const SurfaceFormat sTextureFormat = SurfaceFormat::B8G8R8A8; + +static void PNGAPI info_callback(png_structp png_ptr, png_infop info_ptr) +{ + png_read_update_info(png_ptr, info_ptr); +} + +static void PNGAPI row_callback(png_structp png_ptr, png_bytep new_row, png_uint_32 row_num, int pass) +{ + MOZ_ASSERT(sTextureFormat == SurfaceFormat::B8G8R8A8); + + DataSourceSurface::MappedSurface map = static_cast<TextRenderer*>(png_get_progressive_ptr(png_ptr))->GetSurfaceMap(); + + uint32_t* dst = (uint32_t*)(map.mData + map.mStride * row_num); + + for (uint32_t x = 0; x < sTextureWidth; x++) { + // We blend to a transparent white background, this will make text readable + // even if it's on a dark background. Without hurting our ability to + // interact with the content behind the text. + Float alphaValue = Float(0xFF - new_row[x]) / 255.0f; + Float baseValue = sBackgroundOpacity * (1.0f - alphaValue); + Color pixelColor(baseValue, baseValue, baseValue, baseValue + alphaValue); + dst[x] = pixelColor.ToABGR(); + } +} + +TextRenderer::~TextRenderer() +{ + if (mGlyphBitmaps) { + mGlyphBitmaps->Unmap(); + } +} + +void +TextRenderer::RenderText(const string& aText, const IntPoint& aOrigin, + const Matrix4x4& aTransform, uint32_t aTextSize, + uint32_t aTargetPixelWidth) +{ + EnsureInitialized(); + + // For now we only have a bitmap font with a 16px cell size, so we just + // scale it up if the user wants larger text. + Float scaleFactor = Float(aTextSize) / Float(sCellHeight); + + aTargetPixelWidth /= scaleFactor; + + uint32_t numLines = 1; + uint32_t maxWidth = 0; + uint32_t lineWidth = 0; + // Calculate the size of the surface needed to draw all the glyphs. + for (uint32_t i = 0; i < aText.length(); i++) { + // Insert a line break if we go past the TargetPixelWidth. + // XXX - this has the downside of overrunning the intended width, causing + // things at the edge of a window to be cut off. + if (aText[i] == '\n' || (aText[i] == ' ' && lineWidth > aTargetPixelWidth)) { + numLines++; + lineWidth = 0; + continue; + } + + lineWidth += sGlyphWidths[uint32_t(aText[i])]; + maxWidth = std::max(lineWidth, maxWidth); + } + + // Create a surface to draw our glyphs to. + RefPtr<DataSourceSurface> textSurf = + Factory::CreateDataSourceSurface(IntSize(maxWidth, numLines * sCellHeight), sTextureFormat); + if (NS_WARN_IF(!textSurf)) { + return; + } + + DataSourceSurface::MappedSurface map; + if (NS_WARN_IF(!textSurf->Map(DataSourceSurface::MapType::READ_WRITE, &map))) { + return; + } + + // Initialize the surface to transparent white. + memset(map.mData, uint8_t(sBackgroundOpacity * 255.0f), + numLines * sCellHeight * map.mStride); + + uint32_t currentXPos = 0; + uint32_t currentYPos = 0; + + // Copy our glyphs onto the surface. + for (uint32_t i = 0; i < aText.length(); i++) { + if (aText[i] == '\n' || (aText[i] == ' ' && currentXPos > aTargetPixelWidth)) { + currentYPos += sCellHeight; + currentXPos = 0; + continue; + } + + uint32_t glyphXOffset = aText[i] % (sTextureWidth / sCellWidth) * sCellWidth * BytesPerPixel(sTextureFormat); + uint32_t truncatedLine = aText[i] / (sTextureWidth / sCellWidth); + uint32_t glyphYOffset = truncatedLine * sCellHeight * mMap.mStride; + + for (int y = 0; y < 16; y++) { + memcpy(map.mData + (y + currentYPos) * map.mStride + currentXPos * BytesPerPixel(sTextureFormat), + mMap.mData + glyphYOffset + y * mMap.mStride + glyphXOffset, + sGlyphWidths[uint32_t(aText[i])] * BytesPerPixel(sTextureFormat)); + } + + currentXPos += sGlyphWidths[uint32_t(aText[i])]; + } + + textSurf->Unmap(); + + RefPtr<DataTextureSource> src = mCompositor->CreateDataTextureSource(); + + if (!src->Update(textSurf)) { + // Upload failed. + return; + } + + RefPtr<EffectRGB> effect = new EffectRGB(src, true, SamplingFilter::LINEAR); + EffectChain chain; + chain.mPrimaryEffect = effect; + + Matrix4x4 transform = aTransform; + transform.PreScale(scaleFactor, scaleFactor, 1.0f); + mCompositor->DrawQuad(Rect(aOrigin.x, aOrigin.y, maxWidth, numLines * 16), + IntRect(-10000, -10000, 20000, 20000), chain, 1.0f, transform); +} + +void +TextRenderer::EnsureInitialized() +{ + if (mGlyphBitmaps) { + return; + } + + mGlyphBitmaps = Factory::CreateDataSourceSurface(IntSize(sTextureWidth, sTextureHeight), sTextureFormat); + if (NS_WARN_IF(!mGlyphBitmaps)) { + return; + } + + if (NS_WARN_IF(!mGlyphBitmaps->Map(DataSourceSurface::MapType::READ_WRITE, &mMap))) { + return; + } + + png_structp png_ptr = NULL; + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); + + png_set_progressive_read_fn(png_ptr, this, info_callback, row_callback, nullptr); + png_infop info_ptr = NULL; + info_ptr = png_create_info_struct(png_ptr); + + png_process_data(png_ptr, info_ptr, (uint8_t*)sFontPNG, sizeof(sFontPNG)); + + png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); +} + +} // namespace layers +} // namespace mozilla |