#include "config.h"
#if USE(ACCELERATED_COMPOSITING)
#include "CCFontAtlas.h"
#include "CCProxy.h"
#include "Font.h"
#include "FontCache.h"
#include "FontDescription.h"
#include "GraphicsContext.h"
#include "ImageBuffer.h"
#include "TextRun.h"
#define ATLAS_SIZE 128
#define FONT_HEIGHT 14
namespace WebCore {
using namespace std;
CCFontAtlas::CCFontAtlas()
: m_fontHeight(FONT_HEIGHT)
{
}
static void wrapPositionIfNeeded(IntPoint& position, int textWidth, int textHeight)
{
if (position.x() + textWidth > ATLAS_SIZE)
position = IntPoint(0, position.y() + textHeight);
}
void CCFontAtlas::generateAtlasForFont(GraphicsContext* atlasContext, const FontDescription& fontDescription, const Color& fontColor, const IntPoint& startingPosition, IntRect asciiToAtlasTable[128])
{
ASSERT(CCProxy::isMainThread());
ASSERT(m_atlas);
FontCachePurgePreventer fontCachePurgePreventer;
IntPoint position = startingPosition;
int textHeight = fontDescription.computedPixelSize();
int inflation = textHeight / 3;
Font font(fontDescription, 0, 0);
font.update(0);
atlasContext->setStrokeColor(fontColor, ColorSpaceDeviceRGB);
atlasContext->setFillColor(fontColor, ColorSpaceDeviceRGB);
{
int textWidth = textHeight / 2;
wrapPositionIfNeeded(position, textWidth, textHeight + inflation);
atlasContext->strokeRect(FloatRect(FloatPoint(position.x() + 1, position.y() - textHeight + 1 + inflation), FloatSize(textWidth - 2, textHeight - 2 - inflation)), 1);
asciiToAtlasTable[0] = IntRect(IntPoint(position.x(), position.y() - textHeight), IntSize(textWidth, textHeight + inflation));
position.setX(position.x() + textWidth);
}
for (LChar i = 1; i < 128; ++i) {
if (i < 32) {
asciiToAtlasTable[i] = asciiToAtlasTable[0];
continue;
}
String str;
str.append(i);
TextRun text(str);
int textWidth = round(font.width(text));
wrapPositionIfNeeded(position, textWidth, textHeight + inflation);
atlasContext->drawText(font, text, position);
asciiToAtlasTable[i] = IntRect(IntPoint(position.x(), position.y() - textHeight), IntSize(textWidth, textHeight + inflation));
position.setX(position.x() + textWidth);
}
}
void CCFontAtlas::initialize()
{
ASSERT(CCProxy::isMainThread());
ASSERT(!m_atlas);
m_atlas = ImageBuffer::create(IntSize(ATLAS_SIZE, ATLAS_SIZE));
GraphicsContext* atlasContext = m_atlas->context();
atlasContext->setFillColor(Color(0, 0, 0, 0), ColorSpaceDeviceRGB);
atlasContext->fillRect(FloatRect(0, 0, ATLAS_SIZE, ATLAS_SIZE));
FontDescription fontDescription;
fontDescription.setGenericFamily(FontDescription::MonospaceFamily);
fontDescription.setComputedSize(m_fontHeight);
generateAtlasForFont(atlasContext, fontDescription, Color(255, 0, 0), IntPoint(0, fontDescription.computedPixelSize()), m_asciiToRectTable);
}
void CCFontAtlas::drawText(GraphicsContext* targetContext, const String& text, const IntPoint& destPosition, const IntSize& clip) const
{
ASSERT(CCProxy::isImplThread());
ASSERT(m_atlas);
Vector<String> lines;
text.split('\n', lines);
IntPoint position = destPosition;
for (size_t i = 0; i < lines.size(); ++i) {
drawOneLineOfTextInternal(targetContext, lines[i], position);
position.setY(position.y() + m_fontHeight);
if (position.y() > clip.height())
return;
}
}
void CCFontAtlas::drawOneLineOfTextInternal(GraphicsContext* targetContext, const String& textLine, const IntPoint& destPosition) const
{
ASSERT(CCProxy::isImplThread());
ASSERT(m_atlas);
IntPoint position = destPosition;
for (unsigned i = 0; i < textLine.length(); ++i) {
int asciiIndex = (textLine[i] < 128) ? textLine[i] : 0;
IntRect glyphBounds = m_asciiToRectTable[asciiIndex];
targetContext->drawImageBuffer(m_atlas.get(), ColorSpaceDeviceRGB, position, glyphBounds);
position.setX(position.x() + glyphBounds.width());
}
}
void CCFontAtlas::drawDebugAtlas(GraphicsContext* targetContext, const IntPoint& destPosition) const
{
ASSERT(CCProxy::isImplThread());
ASSERT(m_atlas);
targetContext->drawImageBuffer(m_atlas.get(), ColorSpaceDeviceRGB, destPosition, IntRect(IntPoint::zero(), IntSize(ATLAS_SIZE, ATLAS_SIZE)));
}
}
#endif // USE(ACCELERATED_COMPOSITING)