blob: 1f99d670705356176b455aa782c8d9de808927f7 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "SkiaTextMetrics.h"
#include "wtf/MathExtras.h"
#include <SkPath.h>
namespace blink {
static hb_position_t SkiaScalarToHarfBuzzPosition(SkScalar value) {
// We treat HarfBuzz hb_position_t as 16.16 fixed-point.
static const int kHbPosition1 = 1 << 16;
return clampTo<int>(value * kHbPosition1);
}
SkiaTextMetrics::SkiaTextMetrics(const SkPaint* paint) : m_paint(paint) {
CHECK(m_paint->getTextEncoding() == SkPaint::kGlyphID_TextEncoding);
}
void SkiaTextMetrics::getGlyphWidthForHarfBuzz(hb_codepoint_t codepoint,
hb_position_t* width) {
DCHECK_LE(codepoint, 0xFFFFu);
CHECK(width);
SkScalar skWidth;
uint16_t glyph = codepoint;
m_paint->getTextWidths(&glyph, sizeof(glyph), &skWidth, nullptr);
if (!m_paint->isSubpixelText())
skWidth = SkScalarRoundToInt(skWidth);
*width = SkiaScalarToHarfBuzzPosition(skWidth);
}
void SkiaTextMetrics::getGlyphExtentsForHarfBuzz(hb_codepoint_t codepoint,
hb_glyph_extents_t* extents) {
DCHECK_LE(codepoint, 0xFFFFu);
CHECK(extents);
SkRect skBounds;
uint16_t glyph = codepoint;
m_paint->getTextWidths(&glyph, sizeof(glyph), nullptr, &skBounds);
if (!m_paint->isSubpixelText()) {
// Use roundOut() rather than round() to avoid rendering glyphs
// outside the visual overflow rect. crbug.com/452914.
SkIRect ir;
skBounds.roundOut(&ir);
skBounds.set(ir);
}
// Invert y-axis because Skia is y-grows-down but we set up HarfBuzz to be
// y-grows-up.
extents->x_bearing = SkiaScalarToHarfBuzzPosition(skBounds.fLeft);
extents->y_bearing = SkiaScalarToHarfBuzzPosition(-skBounds.fTop);
extents->width = SkiaScalarToHarfBuzzPosition(skBounds.width());
extents->height = SkiaScalarToHarfBuzzPosition(-skBounds.height());
}
void SkiaTextMetrics::getSkiaBoundsForGlyph(Glyph glyph, SkRect* bounds) {
#if OS(MACOSX)
// TODO(drott): Remove this once we have better metrics bounds
// on Mac, https://bugs.chromium.org/p/skia/issues/detail?id=5328
SkPath path;
m_paint->getTextPath(&glyph, sizeof(glyph), 0, 0, &path);
*bounds = path.getBounds();
#else
m_paint->getTextWidths(&glyph, sizeof(glyph), nullptr, bounds);
#endif
if (!m_paint->isSubpixelText()) {
SkIRect ir;
bounds->roundOut(&ir);
bounds->set(ir);
}
}
float SkiaTextMetrics::getSkiaWidthForGlyph(Glyph glyph) {
SkScalar skWidth;
m_paint->getTextWidths(&glyph, sizeof(glyph), &skWidth, nullptr);
if (!m_paint->isSubpixelText())
skWidth = SkScalarRoundToInt(skWidth);
return SkScalarToFloat(skWidth);
}
} // namespace blink