#include "config.h"
#include "Font.h"
#include "GlyphBuffer.h"
#include "GraphicsContext.h"
#include "PlatformContextSkia.h"
#include "PlatformSupport.h"
#include "SimpleFontData.h"
#include "SkCanvas.h"
#include "SkPaint.h"
#include "SkTypeface.h"
#include "SkTypeface_mac.h"
namespace WebCore {
bool Font::canReturnFallbackFontsForComplexText()
{
return true;
}
bool Font::canExpandAroundIdeographsInComplexText()
{
return true;
}
static void setupPaint(SkPaint* paint, const SimpleFontData* fontData, const Font* font, bool shouldAntialias, bool shouldSmoothFonts)
{
const FontPlatformData& platformData = fontData->platformData();
const float textSize = platformData.m_size >= 0 ? platformData.m_size : 12;
paint->setAntiAlias(shouldAntialias);
paint->setEmbeddedBitmapText(false);
paint->setTextSize(SkFloatToScalar(textSize));
paint->setVerticalText(platformData.orientation() == Vertical);
SkTypeface* typeface = SkCreateTypefaceFromCTFont(platformData.ctFont());
SkAutoUnref autoUnref(typeface);
paint->setTypeface(typeface);
paint->setFakeBoldText(platformData.m_syntheticBold);
paint->setTextSkewX(platformData.m_syntheticOblique ? -SK_Scalar1 / 4 : 0);
paint->setAutohinted(false); paint->setLCDRenderText(shouldSmoothFonts);
paint->setSubpixelText(true);
}
void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
const GlyphBuffer& glyphBuffer, int from, int numGlyphs,
const FloatPoint& point) const {
COMPILE_ASSERT(sizeof(GlyphBufferGlyph) == sizeof(uint16_t), GlyphBufferGlyphSize_equals_uint16_t);
bool shouldSmoothFonts = true;
bool shouldAntialias = true;
switch (fontDescription().fontSmoothing()) {
case Antialiased:
shouldSmoothFonts = false;
break;
case SubpixelAntialiased:
break;
case NoSmoothing:
shouldAntialias = false;
shouldSmoothFonts = false;
break;
case AutoSmoothing:
break;
}
if (!shouldUseSmoothing() || PlatformSupport::layoutTestMode())
shouldSmoothFonts = false;
const GlyphBufferGlyph* glyphs = glyphBuffer.glyphs(from);
SkScalar x = SkFloatToScalar(point.x());
SkScalar y = SkFloatToScalar(point.y());
if (font->platformData().orientation() == Vertical)
y += SkFloatToScalar(font->fontMetrics().floatAscent(IdeographicBaseline) - font->fontMetrics().floatAscent());
const GlyphBufferAdvance* adv = glyphBuffer.advances(from);
SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
SkPoint* pos = storage.get();
for (int i = 0; i < numGlyphs; i++) {
pos[i].set(x, y);
x += SkFloatToScalar(adv[i].width);
y += SkFloatToScalar(adv[i].height);
}
SkCanvas* canvas = gc->platformContext()->canvas();
if (font->platformData().orientation() == Vertical) {
canvas->save();
canvas->rotate(-90);
SkMatrix rotator;
rotator.reset();
rotator.setRotate(90);
rotator.mapPoints(pos, numGlyphs);
}
TextDrawingModeFlags textMode = gc->platformContext()->getTextDrawingMode();
if (textMode & TextModeFill) {
SkPaint paint;
gc->platformContext()->setupPaintForFilling(&paint);
setupPaint(&paint, font, this, shouldAntialias, shouldSmoothFonts);
gc->platformContext()->adjustTextRenderMode(&paint);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
canvas->drawPosText(glyphs, numGlyphs * sizeof(uint16_t), pos, paint);
}
if ((textMode & TextModeStroke)
&& gc->platformContext()->getStrokeStyle() != NoStroke
&& gc->platformContext()->getStrokeThickness() > 0) {
SkPaint paint;
gc->platformContext()->setupPaintForStroking(&paint, 0, 0);
setupPaint(&paint, font, this, shouldAntialias, shouldSmoothFonts);
gc->platformContext()->adjustTextRenderMode(&paint);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
if (textMode & TextModeFill) {
paint.setLooper(0);
}
canvas->drawPosText(glyphs, numGlyphs * sizeof(uint16_t), pos, paint);
}
if (font->platformData().orientation() == Vertical)
canvas->restore();
}
}