OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2016 Google Inc. |
| 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. |
| 6 */ |
| 7 |
| 8 #include <hb-ot.h> |
| 9 |
| 10 #include "SkShaper.h" |
| 11 #include "SkStream.h" |
| 12 #include "SkTextBlob.h" |
| 13 #include "SkTypeface.h" |
| 14 |
| 15 static const int FONT_SIZE_SCALE = 512; |
| 16 |
| 17 struct SkShaper::Impl { |
| 18 struct HBFontDel { |
| 19 void operator()(hb_font_t* f) { hb_font_destroy(f); } |
| 20 }; |
| 21 std::unique_ptr<hb_font_t, HBFontDel> fHarfBuzzFont; |
| 22 struct HBBufDel { |
| 23 void operator()(hb_buffer_t* b) { hb_buffer_destroy(b); } |
| 24 }; |
| 25 std::unique_ptr<hb_buffer_t, HBBufDel> fBuffer; |
| 26 sk_sp<SkTypeface> fTypeface; |
| 27 }; |
| 28 |
| 29 SkShaper::SkShaper(sk_sp<SkTypeface> tf) : fImpl(new Impl) { |
| 30 fImpl->fTypeface = tf ? std::move(tf) : SkTypeface::MakeDefault(); |
| 31 int index; |
| 32 std::unique_ptr<SkStreamAsset> asset(fImpl->fTypeface->openStream(&index)); |
| 33 size_t size = asset->getLength(); |
| 34 SkAutoMalloc autoMalloc(size); // TODO(halcanary): Avoid this malloc+copy. |
| 35 asset->read(autoMalloc.get(), size); |
| 36 asset = nullptr; |
| 37 void* ptr = autoMalloc.get(); |
| 38 hb_blob_t* blob = hb_blob_create((char*)autoMalloc.release(), size, |
| 39 HB_MEMORY_MODE_READONLY, ptr, sk_free); |
| 40 SkASSERT(blob); |
| 41 hb_blob_make_immutable(blob); |
| 42 |
| 43 struct HBFaceDel { |
| 44 void operator()(hb_face_t* f) { hb_face_destroy(f); } |
| 45 }; |
| 46 std::unique_ptr<hb_face_t, HBFaceDel> face(hb_face_create(blob, (unsigned)in
dex)); |
| 47 hb_blob_destroy(blob); |
| 48 SkASSERT(face); |
| 49 if (!face) { |
| 50 return; |
| 51 } |
| 52 hb_face_set_index(face.get(), (unsigned)index); |
| 53 hb_face_set_upem(face.get(), fImpl->fTypeface->getUnitsPerEm()); |
| 54 |
| 55 fImpl->fHarfBuzzFont.reset(hb_font_create(face.get())); |
| 56 SkASSERT(fImpl->fHarfBuzzFont); |
| 57 hb_font_set_scale(fImpl->fHarfBuzzFont.get(), FONT_SIZE_SCALE, FONT_SIZE_SCA
LE); |
| 58 hb_ot_font_set_funcs(fImpl->fHarfBuzzFont.get()); |
| 59 |
| 60 fImpl->fBuffer.reset(hb_buffer_create()); |
| 61 } |
| 62 |
| 63 SkShaper::~SkShaper() {} |
| 64 |
| 65 bool SkShaper::good() const { return fImpl->fHarfBuzzFont != nullptr; } |
| 66 |
| 67 SkScalar SkShaper::shape(SkTextBlobBuilder* builder, |
| 68 const SkPaint& srcPaint, |
| 69 const char* utf8text, |
| 70 size_t textBytes, |
| 71 SkPoint point) const { |
| 72 SkPaint paint(srcPaint); |
| 73 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); |
| 74 paint.setTypeface(fImpl->fTypeface); |
| 75 |
| 76 SkASSERT(builder); |
| 77 hb_buffer_t* buffer = fImpl->fBuffer.get(); |
| 78 hb_buffer_add_utf8(buffer, utf8text, -1, 0, -1); |
| 79 hb_buffer_guess_segment_properties(buffer); |
| 80 hb_shape(fImpl->fHarfBuzzFont.get(), buffer, nullptr, 0); |
| 81 unsigned len = hb_buffer_get_length(buffer); |
| 82 if (len == 0) { |
| 83 hb_buffer_clear_contents(buffer); |
| 84 return 0; |
| 85 } |
| 86 |
| 87 hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, NULL); |
| 88 hb_glyph_position_t* pos = |
| 89 hb_buffer_get_glyph_positions(buffer, NULL); |
| 90 auto runBuffer = builder->allocRunPos(paint, len); |
| 91 |
| 92 double x = point.x(); |
| 93 double y = point.y(); |
| 94 |
| 95 double textSizeY = paint.getTextSize() / (double)FONT_SIZE_SCALE; |
| 96 double textSizeX = textSizeY * paint.getTextScaleX(); |
| 97 |
| 98 for (unsigned i = 0; i < len; i++) { |
| 99 runBuffer.glyphs[i] = info[i].codepoint; |
| 100 reinterpret_cast<SkPoint*>(runBuffer.pos)[i] = |
| 101 SkPoint::Make(x + pos[i].x_offset * textSizeX, |
| 102 y - pos[i].y_offset * textSizeY); |
| 103 x += pos[i].x_advance * textSizeX; |
| 104 y += pos[i].y_advance * textSizeY; |
| 105 } |
| 106 hb_buffer_clear_contents(buffer); |
| 107 return (SkScalar)x; |
| 108 } |
OLD | NEW |