Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/gfx/harfbuzz_font_skia.h" | 5 #include "ui/gfx/harfbuzz_font_skia.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <limits> | 10 #include <limits> |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 26 // Maps from code points to glyph indices in a font. | 26 // Maps from code points to glyph indices in a font. |
| 27 typedef std::map<uint32_t, uint16_t> GlyphCache; | 27 typedef std::map<uint32_t, uint16_t> GlyphCache; |
| 28 | 28 |
| 29 typedef std::pair<HarfBuzzFace, GlyphCache> FaceCache; | 29 typedef std::pair<HarfBuzzFace, GlyphCache> FaceCache; |
| 30 | 30 |
| 31 // Font data provider for HarfBuzz using Skia. Copied from Blink. | 31 // Font data provider for HarfBuzz using Skia. Copied from Blink. |
| 32 // TODO(ckocagil): Eliminate the duplication. http://crbug.com/368375 | 32 // TODO(ckocagil): Eliminate the duplication. http://crbug.com/368375 |
| 33 struct FontData { | 33 struct FontData { |
| 34 FontData(GlyphCache* glyph_cache) : glyph_cache_(glyph_cache) {} | 34 FontData(GlyphCache* glyph_cache) : glyph_cache_(glyph_cache) {} |
| 35 | 35 |
| 36 SkPaint paint_; | 36 cc::PaintFlags flags_; |
| 37 GlyphCache* glyph_cache_; | 37 GlyphCache* glyph_cache_; |
| 38 }; | 38 }; |
| 39 | 39 |
| 40 // Deletes the object at the given pointer after casting it to the given type. | 40 // Deletes the object at the given pointer after casting it to the given type. |
| 41 template<typename Type> | 41 template<typename Type> |
| 42 void DeleteByType(void* data) { | 42 void DeleteByType(void* data) { |
| 43 Type* typed_data = reinterpret_cast<Type*>(data); | 43 Type* typed_data = reinterpret_cast<Type*>(data); |
| 44 delete typed_data; | 44 delete typed_data; |
| 45 } | 45 } |
| 46 | 46 |
| 47 template<typename Type> | 47 template<typename Type> |
| 48 void DeleteArrayByType(void* data) { | 48 void DeleteArrayByType(void* data) { |
| 49 Type* typed_data = reinterpret_cast<Type*>(data); | 49 Type* typed_data = reinterpret_cast<Type*>(data); |
| 50 delete[] typed_data; | 50 delete[] typed_data; |
| 51 } | 51 } |
| 52 | 52 |
| 53 // Outputs the |width| and |extents| of the glyph with index |codepoint| in | 53 // Outputs the |width| and |extents| of the glyph with index |codepoint| in |
| 54 // |paint|'s font. | 54 // |paint|'s font. |
| 55 void GetGlyphWidthAndExtents(SkPaint* paint, | 55 void GetGlyphWidthAndExtents(cc::PaintFlags* flags, |
| 56 hb_codepoint_t codepoint, | 56 hb_codepoint_t codepoint, |
| 57 hb_position_t* width, | 57 hb_position_t* width, |
| 58 hb_glyph_extents_t* extents) { | 58 hb_glyph_extents_t* extents) { |
| 59 SkPaint paint(cc::ToSkPaint(*flags)); | |
| 60 | |
| 59 DCHECK_LE(codepoint, std::numeric_limits<uint16_t>::max()); | 61 DCHECK_LE(codepoint, std::numeric_limits<uint16_t>::max()); |
| 60 paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); | 62 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); |
| 61 | 63 |
| 62 SkScalar sk_width; | 64 SkScalar sk_width; |
| 63 SkRect sk_bounds; | 65 SkRect sk_bounds; |
| 64 uint16_t glyph = static_cast<uint16_t>(codepoint); | 66 uint16_t glyph = static_cast<uint16_t>(codepoint); |
| 65 | 67 |
| 66 paint->getTextWidths(&glyph, sizeof(glyph), &sk_width, &sk_bounds); | 68 paint.getTextWidths(&glyph, sizeof(glyph), &sk_width, &sk_bounds); |
| 67 if (width) | 69 if (width) |
| 68 *width = SkiaScalarToHarfBuzzUnits(sk_width); | 70 *width = SkiaScalarToHarfBuzzUnits(sk_width); |
| 69 if (extents) { | 71 if (extents) { |
| 70 // Invert y-axis because Skia is y-grows-down but we set up HarfBuzz to be | 72 // Invert y-axis because Skia is y-grows-down but we set up HarfBuzz to be |
| 71 // y-grows-up. | 73 // y-grows-up. |
| 72 extents->x_bearing = SkiaScalarToHarfBuzzUnits(sk_bounds.fLeft); | 74 extents->x_bearing = SkiaScalarToHarfBuzzUnits(sk_bounds.fLeft); |
| 73 extents->y_bearing = SkiaScalarToHarfBuzzUnits(-sk_bounds.fTop); | 75 extents->y_bearing = SkiaScalarToHarfBuzzUnits(-sk_bounds.fTop); |
| 74 extents->width = SkiaScalarToHarfBuzzUnits(sk_bounds.width()); | 76 extents->width = SkiaScalarToHarfBuzzUnits(sk_bounds.width()); |
| 75 extents->height = SkiaScalarToHarfBuzzUnits(-sk_bounds.height()); | 77 extents->height = SkiaScalarToHarfBuzzUnits(-sk_bounds.height()); |
| 76 } | 78 } |
| 77 } | 79 } |
| 78 | 80 |
| 79 // Writes the |glyph| index for the given |unicode| code point. Returns whether | 81 // Writes the |glyph| index for the given |unicode| code point. Returns whether |
| 80 // the glyph exists, i.e. it is not a missing glyph. | 82 // the glyph exists, i.e. it is not a missing glyph. |
| 81 hb_bool_t GetGlyph(hb_font_t* font, | 83 hb_bool_t GetGlyph(hb_font_t* font, |
| 82 void* data, | 84 void* data, |
| 83 hb_codepoint_t unicode, | 85 hb_codepoint_t unicode, |
| 84 hb_codepoint_t variation_selector, | 86 hb_codepoint_t variation_selector, |
| 85 hb_codepoint_t* glyph, | 87 hb_codepoint_t* glyph, |
| 86 void* user_data) { | 88 void* user_data) { |
| 87 FontData* font_data = reinterpret_cast<FontData*>(data); | 89 FontData* font_data = reinterpret_cast<FontData*>(data); |
| 88 GlyphCache* cache = font_data->glyph_cache_; | 90 GlyphCache* cache = font_data->glyph_cache_; |
| 89 | 91 |
| 90 bool exists = cache->count(unicode) != 0; | 92 bool exists = cache->count(unicode) != 0; |
| 91 if (!exists) { | 93 if (!exists) { |
| 92 SkPaint* paint = &font_data->paint_; | 94 font_data->flags_.setTextEncoding(cc::PaintFlags::kUTF32_TextEncoding); |
| 93 paint->setTextEncoding(SkPaint::kUTF32_TextEncoding); | 95 SkPaint paint(cc::ToSkPaint(font_data->flags_)); |
|
enne (OOO)
2017/02/27 01:56:21
Similar to my comments on https://codereview.chrom
| |
| 94 paint->textToGlyphs(&unicode, sizeof(hb_codepoint_t), &(*cache)[unicode]); | 96 paint.textToGlyphs(&unicode, sizeof(hb_codepoint_t), &(*cache)[unicode]); |
| 95 } | 97 } |
| 96 *glyph = (*cache)[unicode]; | 98 *glyph = (*cache)[unicode]; |
| 97 return !!*glyph; | 99 return !!*glyph; |
| 98 } | 100 } |
| 99 | 101 |
| 100 // Returns the horizontal advance value of the |glyph|. | 102 // Returns the horizontal advance value of the |glyph|. |
| 101 hb_position_t GetGlyphHorizontalAdvance(hb_font_t* font, | 103 hb_position_t GetGlyphHorizontalAdvance(hb_font_t* font, |
| 102 void* data, | 104 void* data, |
| 103 hb_codepoint_t glyph, | 105 hb_codepoint_t glyph, |
| 104 void* user_data) { | 106 void* user_data) { |
| 105 FontData* font_data = reinterpret_cast<FontData*>(data); | 107 FontData* font_data = reinterpret_cast<FontData*>(data); |
| 106 hb_position_t advance = 0; | 108 hb_position_t advance = 0; |
| 107 | 109 |
| 108 GetGlyphWidthAndExtents(&font_data->paint_, glyph, &advance, 0); | 110 GetGlyphWidthAndExtents(&font_data->flags_, glyph, &advance, 0); |
| 109 return advance; | 111 return advance; |
| 110 } | 112 } |
| 111 | 113 |
| 112 hb_bool_t GetGlyphHorizontalOrigin(hb_font_t* font, | 114 hb_bool_t GetGlyphHorizontalOrigin(hb_font_t* font, |
| 113 void* data, | 115 void* data, |
| 114 hb_codepoint_t glyph, | 116 hb_codepoint_t glyph, |
| 115 hb_position_t* x, | 117 hb_position_t* x, |
| 116 hb_position_t* y, | 118 hb_position_t* y, |
| 117 void* user_data) { | 119 void* user_data) { |
| 118 // Just return true, like the HarfBuzz-FreeType implementation. | 120 // Just return true, like the HarfBuzz-FreeType implementation. |
| 119 return true; | 121 return true; |
| 120 } | 122 } |
| 121 | 123 |
| 122 hb_position_t GetGlyphKerning(FontData* font_data, | 124 hb_position_t GetGlyphKerning(FontData* font_data, |
| 123 hb_codepoint_t first_glyph, | 125 hb_codepoint_t first_glyph, |
| 124 hb_codepoint_t second_glyph) { | 126 hb_codepoint_t second_glyph) { |
| 125 SkTypeface* typeface = font_data->paint_.getTypeface(); | 127 SkTypeface* typeface = font_data->flags_.getTypeface(); |
| 126 const uint16_t glyphs[2] = { static_cast<uint16_t>(first_glyph), | 128 const uint16_t glyphs[2] = { static_cast<uint16_t>(first_glyph), |
| 127 static_cast<uint16_t>(second_glyph) }; | 129 static_cast<uint16_t>(second_glyph) }; |
| 128 int32_t kerning_adjustments[1] = { 0 }; | 130 int32_t kerning_adjustments[1] = { 0 }; |
| 129 | 131 |
| 130 if (!typeface->getKerningPairAdjustments(glyphs, 2, kerning_adjustments)) | 132 if (!typeface->getKerningPairAdjustments(glyphs, 2, kerning_adjustments)) |
| 131 return 0; | 133 return 0; |
| 132 | 134 |
| 133 SkScalar upm = SkIntToScalar(typeface->getUnitsPerEm()); | 135 SkScalar upm = SkIntToScalar(typeface->getUnitsPerEm()); |
| 134 SkScalar size = font_data->paint_.getTextSize(); | 136 SkScalar size = font_data->flags_.getTextSize(); |
| 135 return SkiaScalarToHarfBuzzUnits(SkIntToScalar(kerning_adjustments[0]) * | 137 return SkiaScalarToHarfBuzzUnits(SkIntToScalar(kerning_adjustments[0]) * |
| 136 size / upm); | 138 size / upm); |
| 137 } | 139 } |
| 138 | 140 |
| 139 hb_position_t GetGlyphHorizontalKerning(hb_font_t* font, | 141 hb_position_t GetGlyphHorizontalKerning(hb_font_t* font, |
| 140 void* data, | 142 void* data, |
| 141 hb_codepoint_t left_glyph, | 143 hb_codepoint_t left_glyph, |
| 142 hb_codepoint_t right_glyph, | 144 hb_codepoint_t right_glyph, |
| 143 void* user_data) { | 145 void* user_data) { |
| 144 FontData* font_data = reinterpret_cast<FontData*>(data); | 146 FontData* font_data = reinterpret_cast<FontData*>(data); |
| 145 if (font_data->paint_.isVerticalText()) { | 147 if (font_data->flags_.isVerticalText()) { |
| 146 // We don't support cross-stream kerning. | 148 // We don't support cross-stream kerning. |
| 147 return 0; | 149 return 0; |
| 148 } | 150 } |
| 149 | 151 |
| 150 return GetGlyphKerning(font_data, left_glyph, right_glyph); | 152 return GetGlyphKerning(font_data, left_glyph, right_glyph); |
| 151 } | 153 } |
| 152 | 154 |
| 153 hb_position_t GetGlyphVerticalKerning(hb_font_t* font, | 155 hb_position_t GetGlyphVerticalKerning(hb_font_t* font, |
| 154 void* data, | 156 void* data, |
| 155 hb_codepoint_t top_glyph, | 157 hb_codepoint_t top_glyph, |
| 156 hb_codepoint_t bottom_glyph, | 158 hb_codepoint_t bottom_glyph, |
| 157 void* user_data) { | 159 void* user_data) { |
| 158 FontData* font_data = reinterpret_cast<FontData*>(data); | 160 FontData* font_data = reinterpret_cast<FontData*>(data); |
| 159 if (!font_data->paint_.isVerticalText()) { | 161 if (!font_data->flags_.isVerticalText()) { |
| 160 // We don't support cross-stream kerning. | 162 // We don't support cross-stream kerning. |
| 161 return 0; | 163 return 0; |
| 162 } | 164 } |
| 163 | 165 |
| 164 return GetGlyphKerning(font_data, top_glyph, bottom_glyph); | 166 return GetGlyphKerning(font_data, top_glyph, bottom_glyph); |
| 165 } | 167 } |
| 166 | 168 |
| 167 // Writes the |extents| of |glyph|. | 169 // Writes the |extents| of |glyph|. |
| 168 hb_bool_t GetGlyphExtents(hb_font_t* font, | 170 hb_bool_t GetGlyphExtents(hb_font_t* font, |
| 169 void* data, | 171 void* data, |
| 170 hb_codepoint_t glyph, | 172 hb_codepoint_t glyph, |
| 171 hb_glyph_extents_t* extents, | 173 hb_glyph_extents_t* extents, |
| 172 void* user_data) { | 174 void* user_data) { |
| 173 FontData* font_data = reinterpret_cast<FontData*>(data); | 175 FontData* font_data = reinterpret_cast<FontData*>(data); |
| 174 | 176 |
| 175 GetGlyphWidthAndExtents(&font_data->paint_, glyph, 0, extents); | 177 GetGlyphWidthAndExtents(&font_data->flags_, glyph, 0, extents); |
| 176 return true; | 178 return true; |
| 177 } | 179 } |
| 178 | 180 |
| 179 class FontFuncs { | 181 class FontFuncs { |
| 180 public: | 182 public: |
| 181 FontFuncs() : font_funcs_(hb_font_funcs_create()) { | 183 FontFuncs() : font_funcs_(hb_font_funcs_create()) { |
| 182 hb_font_funcs_set_glyph_func(font_funcs_, GetGlyph, 0, 0); | 184 hb_font_funcs_set_glyph_func(font_funcs_, GetGlyph, 0, 0); |
| 183 hb_font_funcs_set_glyph_h_advance_func( | 185 hb_font_funcs_set_glyph_h_advance_func( |
| 184 font_funcs_, GetGlyphHorizontalAdvance, 0, 0); | 186 font_funcs_, GetGlyphHorizontalAdvance, 0, 0); |
| 185 hb_font_funcs_set_glyph_h_kerning_func( | 187 hb_font_funcs_set_glyph_h_kerning_func( |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 267 static std::map<SkFontID, FaceCache> face_caches; | 269 static std::map<SkFontID, FaceCache> face_caches; |
| 268 | 270 |
| 269 FaceCache* face_cache = &face_caches[skia_face->uniqueID()]; | 271 FaceCache* face_cache = &face_caches[skia_face->uniqueID()]; |
| 270 if (face_cache->first.get() == NULL) | 272 if (face_cache->first.get() == NULL) |
| 271 face_cache->first.Init(skia_face.get()); | 273 face_cache->first.Init(skia_face.get()); |
| 272 | 274 |
| 273 hb_font_t* harfbuzz_font = hb_font_create(face_cache->first.get()); | 275 hb_font_t* harfbuzz_font = hb_font_create(face_cache->first.get()); |
| 274 const int scale = SkiaScalarToHarfBuzzUnits(text_size); | 276 const int scale = SkiaScalarToHarfBuzzUnits(text_size); |
| 275 hb_font_set_scale(harfbuzz_font, scale, scale); | 277 hb_font_set_scale(harfbuzz_font, scale, scale); |
| 276 FontData* hb_font_data = new FontData(&face_cache->second); | 278 FontData* hb_font_data = new FontData(&face_cache->second); |
| 277 hb_font_data->paint_.setTypeface(std::move(skia_face)); | 279 hb_font_data->flags_.setTypeface(std::move(skia_face)); |
| 278 hb_font_data->paint_.setTextSize(text_size); | 280 hb_font_data->flags_.setTextSize(text_size); |
| 279 // TODO(ckocagil): Do we need to update these params later? | 281 // TODO(ckocagil): Do we need to update these params later? |
| 280 internal::ApplyRenderParams(params, subpixel_rendering_suppressed, | 282 internal::ApplyRenderParams(params, subpixel_rendering_suppressed, |
| 281 &hb_font_data->paint_); | 283 &hb_font_data->flags_); |
| 282 hb_font_set_funcs(harfbuzz_font, g_font_funcs.Get().get(), hb_font_data, | 284 hb_font_set_funcs(harfbuzz_font, g_font_funcs.Get().get(), hb_font_data, |
| 283 DeleteByType<FontData>); | 285 DeleteByType<FontData>); |
| 284 hb_font_make_immutable(harfbuzz_font); | 286 hb_font_make_immutable(harfbuzz_font); |
| 285 return harfbuzz_font; | 287 return harfbuzz_font; |
| 286 } | 288 } |
| 287 | 289 |
| 288 } // namespace gfx | 290 } // namespace gfx |
| OLD | NEW |