haiku/src/servers/app/FontCacheEntry.cpp

268 lines
6.4 KiB
C++
Raw Normal View History

/*
* Copyright 2007, Haiku. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Maxim Shemanarev <mcseemagg@yahoo.com>
* Stephan Aßmus <superstippi@gmx.de>
* Andrej Spielmann, <andrej.spielmann@seh.ox.ac.uk>
*/
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#include "FontCacheEntry.h"
#include <string.h>
#include <agg_array.h>
#include <Autolock.h>
#include "utf8_functions.h"
Patch by Andrej Spielmann (GSoC): * Simplified the subpixel related methods for the AGG "pixel format" template interface, the ones for the solid cover simply pass through the existing methods, so only one subpixel blending function is left which does the actual work (this removes a lot of the previously added code) * Implemented a new rasterizer based on the original AGG rasterizer which implements subpixel anti-aliasing for any generic AGG vector pipelines. It is now optionally used in Painter and AGGTextRenderer (for vector fonts, ie rotated, sheared or big enough fonts) depending on the global subpixel setting. * Put all subpixel variables into the new GlobalSubpixelSettings.h|cpp * Simplified DesktopSettings related classes a bit and renamed previous FontSubpixelAntialiasing to just SubpixelAntialiasing. * The private libbe functions for subpixel related settings moved from Font.cpp to InterfaceDefs.cpp where other such functions live. They are not related to fonts only anymore. * Removed the subpixel related settings again from the Fonts preflet and added them to the Appearance preflet instead. All of the above implements subpixel anti-aliasing on a global scale, which to my knowledge no other OS is doing at the moment. Any vector rendering can optionally use subpixel anti-aliasing in Haiku now. The bitmap cached fonts are still affected by the Freetype complile time #define to enable the patented subpixel rasterization (three times wide glyphs). Vector fonts and shapes are not affected though at the moment. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26755 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-08-03 17:40:41 +04:00
#include "GlobalSubpixelSettings.h"
Patch by Andrej Spielmann (GSoC): * Simplified the subpixel related methods for the AGG "pixel format" template interface, the ones for the solid cover simply pass through the existing methods, so only one subpixel blending function is left which does the actual work (this removes a lot of the previously added code) * Implemented a new rasterizer based on the original AGG rasterizer which implements subpixel anti-aliasing for any generic AGG vector pipelines. It is now optionally used in Painter and AGGTextRenderer (for vector fonts, ie rotated, sheared or big enough fonts) depending on the global subpixel setting. * Put all subpixel variables into the new GlobalSubpixelSettings.h|cpp * Simplified DesktopSettings related classes a bit and renamed previous FontSubpixelAntialiasing to just SubpixelAntialiasing. * The private libbe functions for subpixel related settings moved from Font.cpp to InterfaceDefs.cpp where other such functions live. They are not related to fonts only anymore. * Removed the subpixel related settings again from the Fonts preflet and added them to the Appearance preflet instead. All of the above implements subpixel anti-aliasing on a global scale, which to my knowledge no other OS is doing at the moment. Any vector rendering can optionally use subpixel anti-aliasing in Haiku now. The bitmap cached fonts are still affected by the Freetype complile time #define to enable the patented subpixel rasterization (three times wide glyphs). Vector fonts and shapes are not affected though at the moment. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26755 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-08-03 17:40:41 +04:00
BLocker
FontCacheEntry::sUsageUpdateLock("FontCacheEntry usage lock");
class FontCacheEntry::GlyphCachePool {
public:
enum block_size_e { block_size = 16384-16 };
GlyphCachePool()
: fAllocator(block_size)
{
memset(fGlyphs, 0, sizeof(fGlyphs));
}
const GlyphCache* FindGlyph(uint16 glyphCode) const
{
unsigned msb = (glyphCode >> 8) & 0xFF;
if (fGlyphs[msb])
return fGlyphs[msb][glyphCode & 0xFF];
return 0;
}
GlyphCache* CacheGlyph(uint16 glyphCode, unsigned glyphIndex,
unsigned dataSize, glyph_data_type dataType, const agg::rect_i& bounds,
float advanceX, float advanceY, float insetLeft, float insetRight)
{
unsigned msb = (glyphCode >> 8) & 0xFF;
if (fGlyphs[msb] == 0) {
fGlyphs[msb]
= (GlyphCache**)fAllocator.allocate(sizeof(GlyphCache*) * 256,
sizeof(GlyphCache*));
memset(fGlyphs[msb], 0, sizeof(GlyphCache*) * 256);
}
unsigned lsb = glyphCode & 0xFF;
if (fGlyphs[msb][lsb])
return NULL; // already exists, do not overwrite
GlyphCache* glyph
= (GlyphCache*)fAllocator.allocate(sizeof(GlyphCache),
sizeof(double));
if (glyph == NULL)
return NULL;
glyph->glyph_index = glyphIndex;
glyph->data = fAllocator.allocate(dataSize);
glyph->data_size = dataSize;
glyph->data_type = dataType;
glyph->bounds = bounds;
glyph->advance_x = advanceX;
glyph->advance_y = advanceY;
glyph->inset_left = insetLeft;
glyph->inset_right = insetRight;
return fGlyphs[msb][lsb] = glyph;
}
private:
agg::block_allocator fAllocator;
GlyphCache** fGlyphs[256];
};
// #pragma mark -
// constructor
FontCacheEntry::FontCacheEntry()
: MultiLocker("FontCacheEntry lock")
, Referenceable()
, fGlyphCache(new GlyphCachePool())
, fEngine()
, fLastUsedTime(LONGLONG_MIN)
, fUseCounter(0)
{
}
// destructor
FontCacheEntry::~FontCacheEntry()
{
//printf("~FontCacheEntry()\n");
delete fGlyphCache;
}
// Init
bool
FontCacheEntry::Init(const ServerFont& font)
{
glyph_rendering renderingType = _RenderTypeFor(font);
// TODO: encoding from font
FT_Encoding charMap = FT_ENCODING_NONE;
bool hinting = font.Hinting();
if (!fEngine.Init(font.Path(), 0, font.Size(), charMap,
renderingType, hinting)) {
fprintf(stderr, "FontCacheEntry::Init() - some error loading font "
"file %s\n", font.Path());
return false;
}
return true;
}
// HasGlyphs
bool
FontCacheEntry::HasGlyphs(const char* utf8String, ssize_t length) const
{
uint32 charCode;
const char* start = utf8String;
while ((charCode = UTF8ToCharCode(&utf8String))) {
if (!fGlyphCache->FindGlyph(charCode))
return false;
if (utf8String - start + 1 > length)
break;
}
return true;
}
// Glyph
const GlyphCache*
FontCacheEntry::Glyph(uint16 glyphCode)
{
const GlyphCache* glyph = fGlyphCache->FindGlyph(glyphCode);
if (glyph) {
return glyph;
} else {
if (fEngine.PrepareGlyph(glyphCode)) {
glyph = fGlyphCache->CacheGlyph(glyphCode,
fEngine.GlyphIndex(), fEngine.DataSize(),
fEngine.DataType(), fEngine.Bounds(),
fEngine.AdvanceX(), fEngine.AdvanceY(),
fEngine.InsetLeft(), fEngine.InsetRight());
fEngine.WriteGlyphTo(glyph->data);
return glyph;
}
}
return 0;
}
// InitAdaptors
void
FontCacheEntry::InitAdaptors(const GlyphCache* glyph,
double x, double y, GlyphMonoAdapter& monoAdapter,
GlyphGray8Adapter& gray8Adapter, GlyphPathAdapter& pathAdapter,
double scale)
{
if (!glyph)
return;
switch(glyph->data_type) {
case glyph_data_mono:
monoAdapter.init(glyph->data, glyph->data_size, x, y);
break;
case glyph_data_gray8:
gray8Adapter.init(glyph->data, glyph->data_size, x, y);
break;
case glyph_data_subpix:
gray8Adapter.init(glyph->data, glyph->data_size, x, y);
break;
case glyph_data_outline:
pathAdapter.init(glyph->data, glyph->data_size, x, y, scale);
break;
default:
break;
}
}
// GetKerning
bool
FontCacheEntry::GetKerning(uint16 glyphCode1, uint16 glyphCode2,
double* x, double* y)
{
return fEngine.GetKerning(glyphCode1, glyphCode2, x, y);
}
// GenerateSignature
/*static*/ void
FontCacheEntry::GenerateSignature(char* signature, size_t signatureSize,
const ServerFont& font)
{
glyph_rendering renderingType = _RenderTypeFor(font);
// TODO: read more of these from the font
FT_Encoding charMap = FT_ENCODING_NONE;
bool hinting = font.Hinting();
Patch by Andrej Spielmann (GSoC): * Simplified the subpixel related methods for the AGG "pixel format" template interface, the ones for the solid cover simply pass through the existing methods, so only one subpixel blending function is left which does the actual work (this removes a lot of the previously added code) * Implemented a new rasterizer based on the original AGG rasterizer which implements subpixel anti-aliasing for any generic AGG vector pipelines. It is now optionally used in Painter and AGGTextRenderer (for vector fonts, ie rotated, sheared or big enough fonts) depending on the global subpixel setting. * Put all subpixel variables into the new GlobalSubpixelSettings.h|cpp * Simplified DesktopSettings related classes a bit and renamed previous FontSubpixelAntialiasing to just SubpixelAntialiasing. * The private libbe functions for subpixel related settings moved from Font.cpp to InterfaceDefs.cpp where other such functions live. They are not related to fonts only anymore. * Removed the subpixel related settings again from the Fonts preflet and added them to the Appearance preflet instead. All of the above implements subpixel anti-aliasing on a global scale, which to my knowledge no other OS is doing at the moment. Any vector rendering can optionally use subpixel anti-aliasing in Haiku now. The bitmap cached fonts are still affected by the Freetype complile time #define to enable the patented subpixel rasterization (three times wide glyphs). Vector fonts and shapes are not affected though at the moment. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26755 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-08-03 17:40:41 +04:00
uint8 averageWeight = gSubpixelAverageWeight;
snprintf(signature, signatureSize, "%ld,%u,%d,%d,%.1f,%d,%d",
font.GetFamilyAndStyle(), charMap,
Patch by Andrej Spielmann (GSoC): * Simplified the subpixel related methods for the AGG "pixel format" template interface, the ones for the solid cover simply pass through the existing methods, so only one subpixel blending function is left which does the actual work (this removes a lot of the previously added code) * Implemented a new rasterizer based on the original AGG rasterizer which implements subpixel anti-aliasing for any generic AGG vector pipelines. It is now optionally used in Painter and AGGTextRenderer (for vector fonts, ie rotated, sheared or big enough fonts) depending on the global subpixel setting. * Put all subpixel variables into the new GlobalSubpixelSettings.h|cpp * Simplified DesktopSettings related classes a bit and renamed previous FontSubpixelAntialiasing to just SubpixelAntialiasing. * The private libbe functions for subpixel related settings moved from Font.cpp to InterfaceDefs.cpp where other such functions live. They are not related to fonts only anymore. * Removed the subpixel related settings again from the Fonts preflet and added them to the Appearance preflet instead. All of the above implements subpixel anti-aliasing on a global scale, which to my knowledge no other OS is doing at the moment. Any vector rendering can optionally use subpixel anti-aliasing in Haiku now. The bitmap cached fonts are still affected by the Freetype complile time #define to enable the patented subpixel rasterization (three times wide glyphs). Vector fonts and shapes are not affected though at the moment. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26755 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-08-03 17:40:41 +04:00
font.Face(), int(renderingType), font.Size(), hinting, averageWeight);
}
// UpdateUsage
void
FontCacheEntry::UpdateUsage()
{
// this is a static lock to prevent usage of too many semaphores,
// but on the other hand, it is not so nice to be using a lock
// here at all
// the hope is that the time is so short to hold this lock, that
// there is not much contention
BAutolock _(sUsageUpdateLock);
fLastUsedTime = system_time();
fUseCounter++;
}
// _RenderTypeFor
/*static*/ glyph_rendering
FontCacheEntry::_RenderTypeFor(const ServerFont& font)
{
Patch by Andrej Spielmann (GSoC): * Simplified the subpixel related methods for the AGG "pixel format" template interface, the ones for the solid cover simply pass through the existing methods, so only one subpixel blending function is left which does the actual work (this removes a lot of the previously added code) * Implemented a new rasterizer based on the original AGG rasterizer which implements subpixel anti-aliasing for any generic AGG vector pipelines. It is now optionally used in Painter and AGGTextRenderer (for vector fonts, ie rotated, sheared or big enough fonts) depending on the global subpixel setting. * Put all subpixel variables into the new GlobalSubpixelSettings.h|cpp * Simplified DesktopSettings related classes a bit and renamed previous FontSubpixelAntialiasing to just SubpixelAntialiasing. * The private libbe functions for subpixel related settings moved from Font.cpp to InterfaceDefs.cpp where other such functions live. They are not related to fonts only anymore. * Removed the subpixel related settings again from the Fonts preflet and added them to the Appearance preflet instead. All of the above implements subpixel anti-aliasing on a global scale, which to my knowledge no other OS is doing at the moment. Any vector rendering can optionally use subpixel anti-aliasing in Haiku now. The bitmap cached fonts are still affected by the Freetype complile time #define to enable the patented subpixel rasterization (three times wide glyphs). Vector fonts and shapes are not affected though at the moment. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26755 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-08-03 17:40:41 +04:00
glyph_rendering renderingType = gSubpixelAntialiasing ?
glyph_ren_subpix : glyph_ren_native_gray8;
if (font.Rotation() != 0.0 || font.Shear() != 90.0
|| font.FalseBoldWidth() != 0.0
|| font.Flags() & B_DISABLE_ANTIALIASING
|| font.Size() > 30
|| !font.Hinting()) {
renderingType = glyph_ren_outline;
}
Patch by Andrej Spielmann (GSoC): * Simplified the subpixel related methods for the AGG "pixel format" template interface, the ones for the solid cover simply pass through the existing methods, so only one subpixel blending function is left which does the actual work (this removes a lot of the previously added code) * Implemented a new rasterizer based on the original AGG rasterizer which implements subpixel anti-aliasing for any generic AGG vector pipelines. It is now optionally used in Painter and AGGTextRenderer (for vector fonts, ie rotated, sheared or big enough fonts) depending on the global subpixel setting. * Put all subpixel variables into the new GlobalSubpixelSettings.h|cpp * Simplified DesktopSettings related classes a bit and renamed previous FontSubpixelAntialiasing to just SubpixelAntialiasing. * The private libbe functions for subpixel related settings moved from Font.cpp to InterfaceDefs.cpp where other such functions live. They are not related to fonts only anymore. * Removed the subpixel related settings again from the Fonts preflet and added them to the Appearance preflet instead. All of the above implements subpixel anti-aliasing on a global scale, which to my knowledge no other OS is doing at the moment. Any vector rendering can optionally use subpixel anti-aliasing in Haiku now. The bitmap cached fonts are still affected by the Freetype complile time #define to enable the patented subpixel rasterization (three times wide glyphs). Vector fonts and shapes are not affected though at the moment. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26755 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-08-03 17:40:41 +04:00
return renderingType;
}