| 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 namespace { | |
| 18 struct HBFBlobDel { | |
| 19 void operator()(hb_blob_t* b) { hb_blob_destroy(b); } | |
| 20 }; | |
| 21 | |
| 22 std::unique_ptr<hb_blob_t, HBFBlobDel> stream_to_blob(std::unique_ptr<SkStreamAs
set> asset) { | |
| 23 size_t size = asset->getLength(); | |
| 24 std::unique_ptr<hb_blob_t, HBFBlobDel> blob; | |
| 25 if (const void* base = asset->getMemoryBase()) { | |
| 26 blob.reset(hb_blob_create((char*)base, size, | |
| 27 HB_MEMORY_MODE_READONLY, asset.release(), | |
| 28 [](void* p) { delete (SkStreamAsset*)p; })); | |
| 29 } else { | |
| 30 // SkDebugf("Extra SkStreamAsset copy\n"); | |
| 31 SkAutoMalloc autoMalloc(size); | |
| 32 asset->read(autoMalloc.get(), size); | |
| 33 void* ptr = autoMalloc.get(); | |
| 34 blob.reset(hb_blob_create((char*)autoMalloc.release(), size, | |
| 35 HB_MEMORY_MODE_READONLY, ptr, sk_free)); | |
| 36 } | |
| 37 SkASSERT(blob); | |
| 38 hb_blob_make_immutable(blob.get()); | |
| 39 return blob; | |
| 40 } | |
| 41 } // namespace | |
| 42 | |
| 43 struct SkShaper::Impl { | |
| 44 struct HBFontDel { | |
| 45 void operator()(hb_font_t* f) { hb_font_destroy(f); } | |
| 46 }; | |
| 47 std::unique_ptr<hb_font_t, HBFontDel> fHarfBuzzFont; | |
| 48 struct HBBufDel { | |
| 49 void operator()(hb_buffer_t* b) { hb_buffer_destroy(b); } | |
| 50 }; | |
| 51 std::unique_ptr<hb_buffer_t, HBBufDel> fBuffer; | |
| 52 sk_sp<SkTypeface> fTypeface; | |
| 53 }; | |
| 54 | |
| 55 SkShaper::SkShaper(sk_sp<SkTypeface> tf) : fImpl(new Impl) { | |
| 56 fImpl->fTypeface = tf ? std::move(tf) : SkTypeface::MakeDefault(); | |
| 57 int index; | |
| 58 std::unique_ptr<hb_blob_t, HBFBlobDel> blob( | |
| 59 stream_to_blob(std::unique_ptr<SkStreamAsset>( | |
| 60 fImpl->fTypeface->openStream(&index)))); | |
| 61 struct HBFaceDel { | |
| 62 void operator()(hb_face_t* f) { hb_face_destroy(f); } | |
| 63 }; | |
| 64 std::unique_ptr<hb_face_t, HBFaceDel> face( | |
| 65 hb_face_create(blob.get(), (unsigned)index)); | |
| 66 SkASSERT(face); | |
| 67 if (!face) { | |
| 68 return; | |
| 69 } | |
| 70 hb_face_set_index(face.get(), (unsigned)index); | |
| 71 hb_face_set_upem(face.get(), fImpl->fTypeface->getUnitsPerEm()); | |
| 72 | |
| 73 fImpl->fHarfBuzzFont.reset(hb_font_create(face.get())); | |
| 74 SkASSERT(fImpl->fHarfBuzzFont); | |
| 75 hb_font_set_scale(fImpl->fHarfBuzzFont.get(), FONT_SIZE_SCALE, FONT_SIZE_SCA
LE); | |
| 76 hb_ot_font_set_funcs(fImpl->fHarfBuzzFont.get()); | |
| 77 | |
| 78 fImpl->fBuffer.reset(hb_buffer_create()); | |
| 79 } | |
| 80 | |
| 81 SkShaper::~SkShaper() {} | |
| 82 | |
| 83 bool SkShaper::good() const { return fImpl->fHarfBuzzFont != nullptr; } | |
| 84 | |
| 85 SkScalar SkShaper::shape(SkTextBlobBuilder* builder, | |
| 86 const SkPaint& srcPaint, | |
| 87 const char* utf8text, | |
| 88 size_t textBytes, | |
| 89 SkPoint point) const { | |
| 90 SkPaint paint(srcPaint); | |
| 91 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); | |
| 92 paint.setTypeface(fImpl->fTypeface); | |
| 93 | |
| 94 SkASSERT(builder); | |
| 95 hb_buffer_t* buffer = fImpl->fBuffer.get(); | |
| 96 hb_buffer_add_utf8(buffer, utf8text, -1, 0, -1); | |
| 97 hb_buffer_guess_segment_properties(buffer); | |
| 98 hb_shape(fImpl->fHarfBuzzFont.get(), buffer, nullptr, 0); | |
| 99 unsigned len = hb_buffer_get_length(buffer); | |
| 100 if (len == 0) { | |
| 101 hb_buffer_clear_contents(buffer); | |
| 102 return 0; | |
| 103 } | |
| 104 | |
| 105 hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, NULL); | |
| 106 hb_glyph_position_t* pos = | |
| 107 hb_buffer_get_glyph_positions(buffer, NULL); | |
| 108 auto runBuffer = builder->allocRunPos(paint, len); | |
| 109 | |
| 110 double x = point.x(); | |
| 111 double y = point.y(); | |
| 112 | |
| 113 double textSizeY = paint.getTextSize() / (double)FONT_SIZE_SCALE; | |
| 114 double textSizeX = textSizeY * paint.getTextScaleX(); | |
| 115 | |
| 116 for (unsigned i = 0; i < len; i++) { | |
| 117 runBuffer.glyphs[i] = info[i].codepoint; | |
| 118 reinterpret_cast<SkPoint*>(runBuffer.pos)[i] = | |
| 119 SkPoint::Make(x + pos[i].x_offset * textSizeX, | |
| 120 y - pos[i].y_offset * textSizeY); | |
| 121 x += pos[i].x_advance * textSizeX; | |
| 122 y += pos[i].y_advance * textSizeY; | |
| 123 } | |
| 124 hb_buffer_clear_contents(buffer); | |
| 125 return (SkScalar)x; | |
| 126 } | |
| OLD | NEW |