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 |