зеркало из https://github.com/mozilla/gecko-dev.git
Allow TextRenderer to render multiple fonts. (bug 1352151 part 8, r=bas)
--HG-- extra : rebase_source : a3e588eaae57326654b945c2711276b6d71c442e
This commit is contained in:
Родитель
70f688f03e
Коммит
3ffc9da44f
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -29,11 +29,12 @@ static void PNGAPI row_callback(png_structp png_ptr, png_bytep new_row, png_uint
|
|||
{
|
||||
MOZ_ASSERT(sTextureFormat == SurfaceFormat::B8G8R8A8);
|
||||
|
||||
DataSourceSurface::MappedSurface map = static_cast<TextRenderer*>(png_get_progressive_ptr(png_ptr))->GetSurfaceMap();
|
||||
TextRenderer::FontCache* cache =
|
||||
static_cast<TextRenderer::FontCache*>(png_get_progressive_ptr(png_ptr));
|
||||
|
||||
uint32_t* dst = (uint32_t*)(map.mData + map.mStride * row_num);
|
||||
uint32_t* dst = (uint32_t*)(cache->mMap.mData + cache->mMap.mStride * row_num);
|
||||
|
||||
for (uint32_t x = 0; x < sTextureWidth; x++) {
|
||||
for (uint32_t x = 0; x < cache->mInfo->mTextureWidth; 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.
|
||||
|
@ -46,9 +47,11 @@ static void PNGAPI row_callback(png_structp png_ptr, png_bytep new_row, png_uint
|
|||
|
||||
TextRenderer::~TextRenderer()
|
||||
{
|
||||
if (mGlyphBitmaps) {
|
||||
mGlyphBitmaps->Unmap();
|
||||
}
|
||||
|
||||
TextRenderer::FontCache::~FontCache()
|
||||
{
|
||||
mGlyphBitmaps->Unmap();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -56,19 +59,22 @@ TextRenderer::RenderText(Compositor* aCompositor,
|
|||
const string& aText,
|
||||
const IntPoint& aOrigin,
|
||||
const Matrix4x4& aTransform, uint32_t aTextSize,
|
||||
uint32_t aTargetPixelWidth)
|
||||
uint32_t aTargetPixelWidth,
|
||||
FontType aFontType)
|
||||
{
|
||||
const FontBitmapInfo* info = GetFontInfo(aFontType);
|
||||
|
||||
// For now we only have a bitmap font with a 16px cell size, so we just
|
||||
// For now we only have a bitmap font with a 24px cell size, so we just
|
||||
// scale it up if the user wants larger text.
|
||||
Float scaleFactor = Float(aTextSize) / Float(sCellHeight);
|
||||
Float scaleFactor = Float(aTextSize) / Float(info->mCellHeight);
|
||||
aTargetPixelWidth /= scaleFactor;
|
||||
|
||||
RefPtr<TextureSource> src = RenderText(
|
||||
aCompositor,
|
||||
aText,
|
||||
aTextSize,
|
||||
aTargetPixelWidth);
|
||||
aTargetPixelWidth,
|
||||
aFontType);
|
||||
if (!src) {
|
||||
return;
|
||||
}
|
||||
|
@ -89,9 +95,15 @@ RefPtr<TextureSource>
|
|||
TextRenderer::RenderText(TextureSourceProvider* aProvider,
|
||||
const string& aText,
|
||||
uint32_t aTextSize,
|
||||
uint32_t aTargetPixelWidth)
|
||||
uint32_t aTargetPixelWidth,
|
||||
FontType aFontType)
|
||||
{
|
||||
EnsureInitialized();
|
||||
if (!EnsureInitialized(aFontType)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FontCache* cache = mFonts[aFontType].get();
|
||||
const FontBitmapInfo* info = cache->mInfo;
|
||||
|
||||
uint32_t numLines = 1;
|
||||
uint32_t maxWidth = 0;
|
||||
|
@ -107,13 +119,13 @@ TextRenderer::RenderText(TextureSourceProvider* aProvider,
|
|||
continue;
|
||||
}
|
||||
|
||||
lineWidth += sGlyphWidths[uint32_t(aText[i])];
|
||||
lineWidth += info->GetGlyphWidth(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);
|
||||
Factory::CreateDataSourceSurface(IntSize(maxWidth, numLines * info->mCellHeight), sTextureFormat);
|
||||
if (NS_WARN_IF(!textSurf)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -125,30 +137,35 @@ TextRenderer::RenderText(TextureSourceProvider* aProvider,
|
|||
|
||||
// Initialize the surface to transparent white.
|
||||
memset(map.mData, uint8_t(sBackgroundOpacity * 255.0f),
|
||||
numLines * sCellHeight * map.mStride);
|
||||
numLines * info->mCellHeight * map.mStride);
|
||||
|
||||
uint32_t currentXPos = 0;
|
||||
uint32_t currentYPos = 0;
|
||||
|
||||
const unsigned int kGlyphsPerLine = info->mTextureWidth / info->mCellWidth;
|
||||
|
||||
// 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;
|
||||
currentYPos += info->mCellHeight;
|
||||
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;
|
||||
uint32_t index = aText[i] - info->mFirstChar;
|
||||
uint32_t glyphXOffset = (index % kGlyphsPerLine) * info->mCellWidth * BytesPerPixel(sTextureFormat);
|
||||
uint32_t truncatedLine = index / kGlyphsPerLine;
|
||||
uint32_t glyphYOffset = truncatedLine * info->mCellHeight * cache->mMap.mStride;
|
||||
|
||||
for (int y = 0; y < 16; y++) {
|
||||
uint32_t glyphWidth = info->GetGlyphWidth(aText[i]);
|
||||
|
||||
for (uint32_t y = 0; y < info->mCellHeight; 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));
|
||||
cache->mMap.mData + glyphYOffset + y * cache->mMap.mStride + glyphXOffset,
|
||||
glyphWidth * BytesPerPixel(sTextureFormat));
|
||||
}
|
||||
|
||||
currentXPos += sGlyphWidths[uint32_t(aText[i])];
|
||||
currentXPos += glyphWidth;
|
||||
}
|
||||
|
||||
textSurf->Unmap();
|
||||
|
@ -163,32 +180,56 @@ TextRenderer::RenderText(TextureSourceProvider* aProvider,
|
|||
return src;
|
||||
}
|
||||
|
||||
void
|
||||
TextRenderer::EnsureInitialized()
|
||||
/* static */ const FontBitmapInfo*
|
||||
TextRenderer::GetFontInfo(FontType aType)
|
||||
{
|
||||
if (mGlyphBitmaps) {
|
||||
return;
|
||||
switch (aType) {
|
||||
case FontType::Default:
|
||||
return &sDefaultCompositorFont;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("unknown font type");
|
||||
}
|
||||
}
|
||||
|
||||
mGlyphBitmaps = Factory::CreateDataSourceSurface(IntSize(sTextureWidth, sTextureHeight), sTextureFormat);
|
||||
if (NS_WARN_IF(!mGlyphBitmaps)) {
|
||||
return;
|
||||
bool
|
||||
TextRenderer::EnsureInitialized(FontType aType)
|
||||
{
|
||||
if (mFonts[aType]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!mGlyphBitmaps->Map(DataSourceSurface::MapType::READ_WRITE, &mMap))) {
|
||||
return;
|
||||
const FontBitmapInfo* info = GetFontInfo(aType);
|
||||
|
||||
IntSize size(info->mTextureWidth, info->mTextureHeight);
|
||||
RefPtr<DataSourceSurface> surface = Factory::CreateDataSourceSurface(size, sTextureFormat);
|
||||
if (NS_WARN_IF(!surface)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DataSourceSurface::MappedSurface map;
|
||||
if (NS_WARN_IF(!surface->Map(DataSourceSurface::MapType::READ_WRITE, &map))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UniquePtr<FontCache> cache = MakeUnique<FontCache>();
|
||||
cache->mGlyphBitmaps = surface;
|
||||
cache->mMap = map;
|
||||
cache->mInfo = info;
|
||||
|
||||
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_set_progressive_read_fn(png_ptr, cache.get(), 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_process_data(png_ptr, info_ptr, (uint8_t*)info->mPNG, info->mPNGLength);
|
||||
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
||||
|
||||
mFonts[aType] = Move(cache);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#ifndef GFX_TextRenderer_H
|
||||
#define GFX_TextRenderer_H
|
||||
|
||||
#include "mozilla/EnumeratedArray.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include <string>
|
||||
|
@ -16,6 +17,7 @@ namespace layers {
|
|||
class Compositor;
|
||||
class TextureSource;
|
||||
class TextureSourceProvider;
|
||||
struct FontBitmapInfo;
|
||||
|
||||
class TextRenderer
|
||||
{
|
||||
|
@ -24,32 +26,64 @@ class TextRenderer
|
|||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(TextRenderer)
|
||||
|
||||
enum class FontType {
|
||||
Default,
|
||||
NumTypes
|
||||
};
|
||||
|
||||
explicit TextRenderer()
|
||||
: mMap({nullptr, 0})
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
RefPtr<TextureSource>
|
||||
RenderText(TextureSourceProvider* aProvider,
|
||||
const std::string& aText,
|
||||
uint32_t aTextSize,
|
||||
uint32_t aTargetPixelWidth);
|
||||
uint32_t aTargetPixelWidth,
|
||||
FontType aFontType);
|
||||
|
||||
void RenderText(Compositor* aCompositor,
|
||||
const std::string& aText,
|
||||
const gfx::IntPoint& aOrigin,
|
||||
const gfx::Matrix4x4& aTransform, uint32_t aTextSize,
|
||||
uint32_t aTargetPixelWidth);
|
||||
uint32_t aTargetPixelWidth,
|
||||
FontType aFontType = FontType::Default);
|
||||
|
||||
gfx::DataSourceSurface::MappedSurface& GetSurfaceMap() { return mMap; }
|
||||
struct FontCache {
|
||||
~FontCache();
|
||||
RefPtr<gfx::DataSourceSurface> mGlyphBitmaps;
|
||||
gfx::DataSourceSurface::MappedSurface mMap;
|
||||
const FontBitmapInfo* mInfo;
|
||||
};
|
||||
|
||||
protected:
|
||||
// Note that this may still fail to set mGlyphBitmaps to a valid value
|
||||
// if the underlying CreateDataSourceSurface fails for some reason.
|
||||
void EnsureInitialized();
|
||||
bool EnsureInitialized(FontType aType);
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> mGlyphBitmaps;
|
||||
gfx::DataSourceSurface::MappedSurface mMap;
|
||||
static const FontBitmapInfo* GetFontInfo(FontType aType);
|
||||
|
||||
private:
|
||||
EnumeratedArray<FontType, FontType::NumTypes, UniquePtr<FontCache>> mFonts;
|
||||
};
|
||||
|
||||
struct FontBitmapInfo {
|
||||
Maybe<unsigned int> mGlyphWidth;
|
||||
Maybe<const unsigned short*> mGlyphWidths;
|
||||
unsigned int mTextureWidth;
|
||||
unsigned int mTextureHeight;
|
||||
unsigned int mCellWidth;
|
||||
unsigned int mCellHeight;
|
||||
unsigned int mFirstChar;
|
||||
const unsigned char* mPNG;
|
||||
size_t mPNGLength;
|
||||
|
||||
unsigned int GetGlyphWidth(char aGlyph) const {
|
||||
if (mGlyphWidth) {
|
||||
return mGlyphWidth.value();
|
||||
}
|
||||
MOZ_ASSERT(unsigned(aGlyph) >= mFirstChar);
|
||||
return mGlyphWidths.value()[unsigned(aGlyph) - mFirstChar];
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -868,6 +868,9 @@ CompositorD3D11::ClearRect(const gfx::Rect& aRect)
|
|||
}
|
||||
|
||||
mContext->Draw(4, 0);
|
||||
|
||||
// Restore the default blend state.
|
||||
mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
|
|
Загрузка…
Ссылка в новой задаче