Fix text bounds using shaped text w/the font of each text run

This fixes the required output image size to render text in different
languages when the text doesn't support the full range of the
specified chars/code points, and multiple fonts/text runs are used.
This commit is contained in:
David Capello 2024-04-16 11:01:26 -03:00
parent bc63d2f660
commit cf67842760

View File

@ -21,17 +21,50 @@
#include "doc/primitives.h"
#include "text/draw_text.h"
#include "text/font_metrics.h"
#include "text/text_blob.h"
#ifdef LAF_SKIA
#include "app/util/shader_helpers.h"
#include "os/skia/skia_surface.h"
#endif
#include <cmath>
#include <memory>
#include <stdexcept>
namespace app {
namespace {
class MeasureHandler : public text::TextBlob::RunHandler {
public:
MeasureHandler() : m_bounds(0, 0, 1, 1) {
}
const gfx::RectF& bounds() const {
return m_bounds;
}
// text::TextBlob::RunHandler impl
void commitRunBuffer(text::TextBlob::RunInfo& info) override {
ASSERT(info.font);
if (info.clusters &&
info.glyphCount > 0) {
const float height = info.font->metrics(nullptr);
for (int i=0; i<info.glyphCount; ++i) {
auto rc = info.getGlyphBounds(i);
m_bounds |= gfx::RectF(rc.x, 0, rc.w, height);
}
}
}
private:
gfx::RectF m_bounds;
};
} // anonymous namespace
doc::ImageRef render_text(
const text::FontMgrRef& fontMgr,
const FontInfo& fontInfo,
@ -74,12 +107,24 @@ doc::ImageRef render_text(
paint.style(os::Paint::StrokeAndFill);
paint.color(color);
text::TextBlobRef blob;
gfx::RectF bounds;
bounds.w = font->measureText(text, &bounds, &paint);
text::FontMetrics metrics;
bounds.w += 1;
bounds.h = font->metrics(&metrics);
if (fontInfo.type() == FontInfo::Type::System) {
// For native fonts we have to measure all text runs which might
// use different fonts (e.g. if the given font is not enough to
// shape other code points/languages).
MeasureHandler handler;
blob = text::TextBlob::MakeWithShaper(fontMgr, font, text, &handler);
bounds = handler.bounds();
}
else {
font->measureText(text, &bounds, &paint);
bounds.w += 1 + std::abs(bounds.x);
text::FontMetrics metrics;
bounds.h = font->metrics(&metrics);
}
if (bounds.w < 1) bounds.w = 1;
if (bounds.h < 1) bounds.h = 1;
@ -89,8 +134,8 @@ doc::ImageRef render_text(
sk_sp<SkSurface> skSurface = wrap_docimage_in_sksurface(image.get());
os::SurfaceRef surface = base::make_ref<os::SkiaSurface>(skSurface);
if (fontInfo.type() == FontInfo::Type::System) {
text::draw_text_with_shaper(
surface.get(), fontMgr, font, text, gfx::PointF(0, 0), &paint);
text::draw_text(surface.get(), blob,
gfx::PointF(0, 0), &paint);
}
else {
text::draw_text(