Skip to content

Commit

Permalink
Fix required bounds for text using shaped text w/the font of each tex…
Browse files Browse the repository at this point in the history
…t run

This fixes the required output image size to render text in different
languages when the text does't support the full range of the specified
chars/code points.
  • Loading branch information
dacap committed Apr 16, 2024
1 parent 61ec7cd commit 33728fc
Showing 1 changed file with 51 additions and 6 deletions.
57 changes: 51 additions & 6 deletions src/app/util/render_text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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::Rect(rc.x, 0, rc.w, height);
}
}
}

private:
gfx::RectF m_bounds;
};

} // anonymous namespace

doc::ImageRef render_text(
const text::FontMgrRef& fontMgr,
const FontInfo& fontInfo,
Expand Down Expand Up @@ -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;

Expand All @@ -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(
Expand Down

0 comments on commit 33728fc

Please sign in to comment.