This source file includes following definitions.
- canReturnFallbackFontsForComplexText
- canExpandAroundIdeographsInComplexText
- paintGlyphs
- drawGlyphs
- drawComplexText
- drawEmphasisMarksForComplexText
- getGlyphsAndAdvancesForComplexText
- floatWidthForComplexText
- offsetForPositionForComplexText
- selectionRectForComplexText
#include "config.h"
#include "platform/fonts/Font.h"
#include "platform/NotImplemented.h"
#include "platform/fonts/FontPlatformFeatures.h"
#include "platform/fonts/SimpleFontData.h"
#include "platform/fonts/harfbuzz/HarfBuzzShaper.h"
#include "platform/fonts/GlyphBuffer.h"
#include "platform/geometry/FloatRect.h"
#include "platform/graphics/GraphicsContext.h"
#include "SkPaint.h"
#include "SkTemplates.h"
#include "wtf/unicode/Unicode.h"
namespace WebCore {
bool FontPlatformFeatures::canReturnFallbackFontsForComplexText()
{
return false;
}
bool FontPlatformFeatures::canExpandAroundIdeographsInComplexText()
{
return false;
}
static void paintGlyphs(GraphicsContext* gc, const SimpleFontData* font,
const GlyphBufferGlyph* glyphs, unsigned numGlyphs,
SkPoint* pos, const FloatRect& textRect)
{
TextDrawingModeFlags textMode = gc->textDrawingMode();
if (textMode & TextModeFill) {
SkPaint paint;
gc->setupPaintForFilling(&paint);
font->platformData().setupPaint(&paint, gc);
gc->adjustTextRenderMode(&paint);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
gc->drawPosText(glyphs, numGlyphs << 1, pos, textRect, paint);
}
if ((textMode & TextModeStroke)
&& gc->strokeStyle() != NoStroke
&& gc->strokeThickness() > 0) {
SkPaint paint;
gc->setupPaintForStroking(&paint);
font->platformData().setupPaint(&paint, gc);
gc->adjustTextRenderMode(&paint);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
if (textMode & TextModeFill) {
paint.setLooper(0);
}
gc->drawPosText(glyphs, numGlyphs << 1, pos, textRect, paint);
}
}
void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs,
const FloatPoint& point, const FloatRect& textRect) const
{
SkASSERT(sizeof(GlyphBufferGlyph) == sizeof(uint16_t));
SkScalar x = SkFloatToScalar(point.x());
SkScalar y = SkFloatToScalar(point.y());
SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
SkPoint* pos = storage.get();
const OpenTypeVerticalData* verticalData = font->verticalData();
if (font->platformData().orientation() == Vertical && verticalData) {
AffineTransform savedMatrix = gc->getCTM();
gc->concatCTM(AffineTransform(0, -1, 1, 0, point.x(), point.y()));
gc->concatCTM(AffineTransform(1, 0, 0, 1, -point.x(), -point.y()));
const unsigned kMaxBufferLength = 256;
Vector<FloatPoint, kMaxBufferLength> translations;
const FontMetrics& metrics = font->fontMetrics();
SkScalar verticalOriginX = SkFloatToScalar(point.x() + metrics.floatAscent() - metrics.floatAscent(IdeographicBaseline));
float horizontalOffset = point.x();
unsigned glyphIndex = 0;
while (glyphIndex < numGlyphs) {
unsigned chunkLength = std::min(kMaxBufferLength, numGlyphs - glyphIndex);
const GlyphBufferGlyph* glyphs = glyphBuffer.glyphs(from + glyphIndex);
translations.resize(chunkLength);
verticalData->getVerticalTranslationsForGlyphs(font, &glyphs[0], chunkLength, reinterpret_cast<float*>(&translations[0]));
x = verticalOriginX;
y = SkFloatToScalar(point.y() + horizontalOffset - point.x());
float currentWidth = 0;
for (unsigned i = 0; i < chunkLength; ++i, ++glyphIndex) {
pos[i].set(
x + SkIntToScalar(lroundf(translations[i].x())),
y + -SkIntToScalar(-lroundf(currentWidth - translations[i].y())));
currentWidth += glyphBuffer.advanceAt(from + glyphIndex).width();
}
horizontalOffset += currentWidth;
paintGlyphs(gc, font, glyphs, chunkLength, pos, textRect);
}
gc->setCTM(savedMatrix);
return;
}
const GlyphBufferAdvance* adv = glyphBuffer.advances(from);
for (unsigned i = 0; i < numGlyphs; i++) {
pos[i].set(x, y);
x += SkFloatToScalar(adv[i].width());
y += SkFloatToScalar(adv[i].height());
}
const GlyphBufferGlyph* glyphs = glyphBuffer.glyphs(from);
paintGlyphs(gc, font, glyphs, numGlyphs, pos, textRect);
}
void Font::drawComplexText(GraphicsContext* gc, const TextRunPaintInfo& runInfo, const FloatPoint& point) const
{
if (!runInfo.run.length())
return;
TextDrawingModeFlags textMode = gc->textDrawingMode();
bool fill = textMode & TextModeFill;
bool stroke = (textMode & TextModeStroke)
&& gc->strokeStyle() != NoStroke
&& gc->strokeThickness() > 0;
if (!fill && !stroke)
return;
GlyphBuffer glyphBuffer;
HarfBuzzShaper shaper(this, runInfo.run);
shaper.setDrawRange(runInfo.from, runInfo.to);
if (!shaper.shape(&glyphBuffer))
return;
FloatPoint adjustedPoint = shaper.adjustStartPoint(point);
drawGlyphBuffer(gc, runInfo, glyphBuffer, adjustedPoint);
}
void Font::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const
{
GlyphBuffer glyphBuffer;
float initialAdvance = getGlyphsAndAdvancesForComplexText(runInfo.run, runInfo.from, runInfo.to, glyphBuffer, ForTextEmphasis);
if (glyphBuffer.isEmpty())
return;
drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
}
float Font::getGlyphsAndAdvancesForComplexText(const TextRun& run, int from, int to, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
{
HarfBuzzShaper shaper(this, run, HarfBuzzShaper::ForTextEmphasis);
shaper.setDrawRange(from, to);
shaper.shape(&glyphBuffer);
return 0;
}
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* , GlyphOverflow* glyphOverflow) const
{
HarfBuzzShaper shaper(this, run);
if (!shaper.shape())
return 0;
if (glyphOverflow) {
glyphOverflow->top = std::max<int>(glyphOverflow->top, ceilf(-shaper.glyphBoundingBox().top()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent()));
glyphOverflow->bottom = std::max<int>(glyphOverflow->bottom, ceilf(shaper.glyphBoundingBox().bottom()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent()));
glyphOverflow->left = std::max<int>(0, ceilf(-shaper.glyphBoundingBox().left()));
glyphOverflow->right = std::max<int>(0, ceilf(shaper.glyphBoundingBox().right() - shaper.totalWidth()));
}
return shaper.totalWidth();
}
int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat,
bool includePartialGlyphs) const
{
HarfBuzzShaper shaper(this, run);
if (!shaper.shape())
return 0;
return shaper.offsetForPosition(xFloat);
}
FloatRect Font::selectionRectForComplexText(const TextRun& run,
const FloatPoint& point, int height,
int from, int to) const
{
HarfBuzzShaper shaper(this, run);
if (!shaper.shape())
return FloatRect();
return shaper.selectionRect(point, height, from, to);
}
}