#include "config.h"
#include "Font.h"
#include "FontData.h"
#include "FontFallbackList.h"
#include "GlyphBuffer.h"
#include "GraphicsContext.h"
#include "IntRect.h"
#include "NotImplemented.h"
#include "TextStyle.h"
#include "UniscribeController.h"
#include <ApplicationServices/ApplicationServices.h>
#include <WebKitSystemInterface/WebKitSystemInterface.h>
#include <wtf/MathExtras.h>
namespace WebCore {
const int syntheticObliqueAngle = 14;
void Font::drawGlyphs(GraphicsContext* graphicsContext, const FontData* font, const GlyphBuffer& glyphBuffer,
int from, int numGlyphs, const FloatPoint& point) const
{
CGContextRef cgContext = graphicsContext->platformContext();
uint32_t oldFontSmoothingStyle = wkSetFontSmoothingStyle(cgContext);
const FontPlatformData& platformData = font->platformData();
CGContextSetFont(cgContext, platformData.cgFont());
CGAffineTransform matrix = CGAffineTransformIdentity;
matrix.b = -matrix.b;
matrix.d = -matrix.d;
if (platformData.syntheticOblique())
{
static float skew = -tanf(syntheticObliqueAngle * acosf(0) / 90);
matrix = CGAffineTransformConcat(matrix, CGAffineTransformMake(1, 0, skew, 1, 0, 0));
}
FloatSize translation = glyphBuffer.offsetAt(from);
if (translation.width() || translation.height())
CGAffineTransformTranslate(matrix, translation.width(), translation.height());
CGContextSetTextMatrix(cgContext, matrix);
CGContextSetFontSize(cgContext, platformData.size());
CGContextSetTextPosition(cgContext, point.x(), point.y());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
if (font->m_syntheticBoldOffset) {
CGContextSetTextPosition(cgContext, point.x() + font->m_syntheticBoldOffset, point.y());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
}
wkRestoreFontSmoothingStyle(cgContext, oldFontSmoothingStyle);
}
FloatRect Font::selectionRectForComplexText(const TextRun& run, const TextStyle& style, const IntPoint& point, int h,
int from, int to) const
{
UniscribeController it(this, run, style);
it.advance(from);
float beforeWidth = it.runWidthSoFar();
it.advance(to);
float afterWidth = it.runWidthSoFar();
if (style.rtl()) {
it.advance(run.length());
float totalWidth = it.runWidthSoFar();
return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h);
}
return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
}
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const TextStyle& style, const FloatPoint& point,
int from, int to) const
{
GlyphBuffer glyphBuffer;
float startX = point.x();
UniscribeController controller(this, run, style);
controller.advance(from);
float beforeWidth = controller.runWidthSoFar();
controller.advance(to, &glyphBuffer);
if (glyphBuffer.isEmpty())
return;
float afterWidth = controller.runWidthSoFar();
if (style.rtl()) {
controller.advance(run.length());
startX += controller.runWidthSoFar() - afterWidth;
} else
startX += beforeWidth;
FloatPoint startPoint(startX, point.y());
drawGlyphBuffer(context, glyphBuffer, run, style, startPoint);
}
float Font::floatWidthForComplexText(const TextRun& run, const TextStyle& style) const
{
UniscribeController controller(this, run, style);
controller.advance(run.length());
return controller.runWidthSoFar();
}
int Font::offsetForPositionForComplexText(const TextRun& run, const TextStyle& style, int x, bool includePartialGlyphs) const
{
UniscribeController controller(this, run, style);
return controller.offsetForPosition(x, includePartialGlyphs);
}
}