|
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
2 * This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "ScaledFontBase.h" |
|
7 |
|
8 #ifdef USE_SKIA |
|
9 #include "PathSkia.h" |
|
10 #include "skia/SkEmptyShader.h" |
|
11 #include "skia/SkPaint.h" |
|
12 #endif |
|
13 |
|
14 #ifdef USE_CAIRO |
|
15 #include "PathCairo.h" |
|
16 #include "DrawTargetCairo.h" |
|
17 #include "HelpersCairo.h" |
|
18 #endif |
|
19 |
|
20 #include <vector> |
|
21 #include <cmath> |
|
22 |
|
23 using namespace std; |
|
24 |
|
25 namespace mozilla { |
|
26 namespace gfx { |
|
27 |
|
28 ScaledFontBase::~ScaledFontBase() |
|
29 { |
|
30 #ifdef USE_SKIA |
|
31 SkSafeUnref(mTypeface); |
|
32 #endif |
|
33 #ifdef USE_CAIRO_SCALED_FONT |
|
34 cairo_scaled_font_destroy(mScaledFont); |
|
35 #endif |
|
36 } |
|
37 |
|
38 ScaledFontBase::ScaledFontBase(Float aSize) |
|
39 : mSize(aSize) |
|
40 { |
|
41 #ifdef USE_SKIA |
|
42 mTypeface = nullptr; |
|
43 #endif |
|
44 #ifdef USE_CAIRO_SCALED_FONT |
|
45 mScaledFont = nullptr; |
|
46 #endif |
|
47 } |
|
48 |
|
49 #ifdef USE_SKIA |
|
50 SkPath |
|
51 ScaledFontBase::GetSkiaPathForGlyphs(const GlyphBuffer &aBuffer) |
|
52 { |
|
53 SkTypeface *typeFace = GetSkTypeface(); |
|
54 MOZ_ASSERT(typeFace); |
|
55 |
|
56 SkPaint paint; |
|
57 paint.setTypeface(typeFace); |
|
58 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); |
|
59 paint.setTextSize(SkFloatToScalar(mSize)); |
|
60 |
|
61 std::vector<uint16_t> indices; |
|
62 std::vector<SkPoint> offsets; |
|
63 indices.resize(aBuffer.mNumGlyphs); |
|
64 offsets.resize(aBuffer.mNumGlyphs); |
|
65 |
|
66 for (unsigned int i = 0; i < aBuffer.mNumGlyphs; i++) { |
|
67 indices[i] = aBuffer.mGlyphs[i].mIndex; |
|
68 offsets[i].fX = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.x); |
|
69 offsets[i].fY = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.y); |
|
70 } |
|
71 |
|
72 SkPath path; |
|
73 paint.getPosTextPath(&indices.front(), aBuffer.mNumGlyphs*2, &offsets.front(), &path); |
|
74 return path; |
|
75 } |
|
76 #endif |
|
77 |
|
78 TemporaryRef<Path> |
|
79 ScaledFontBase::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget) |
|
80 { |
|
81 #ifdef USE_SKIA |
|
82 if (aTarget->GetType() == BackendType::SKIA) { |
|
83 SkPath path = GetSkiaPathForGlyphs(aBuffer); |
|
84 return new PathSkia(path, FillRule::FILL_WINDING); |
|
85 } |
|
86 #endif |
|
87 #ifdef USE_CAIRO |
|
88 if (aTarget->GetType() == BackendType::CAIRO) { |
|
89 MOZ_ASSERT(mScaledFont); |
|
90 |
|
91 DrawTarget *dt = const_cast<DrawTarget*>(aTarget); |
|
92 cairo_t *ctx = static_cast<cairo_t*>(dt->GetNativeSurface(NativeSurfaceType::CAIRO_CONTEXT)); |
|
93 |
|
94 bool isNewContext = !ctx; |
|
95 if (!ctx) { |
|
96 ctx = cairo_create(DrawTargetCairo::GetDummySurface()); |
|
97 cairo_matrix_t mat; |
|
98 GfxMatrixToCairoMatrix(aTarget->GetTransform(), mat); |
|
99 cairo_set_matrix(ctx, &mat); |
|
100 } |
|
101 |
|
102 cairo_set_scaled_font(ctx, mScaledFont); |
|
103 |
|
104 // Convert our GlyphBuffer into an array of Cairo glyphs. |
|
105 std::vector<cairo_glyph_t> glyphs(aBuffer.mNumGlyphs); |
|
106 for (uint32_t i = 0; i < aBuffer.mNumGlyphs; ++i) { |
|
107 glyphs[i].index = aBuffer.mGlyphs[i].mIndex; |
|
108 glyphs[i].x = aBuffer.mGlyphs[i].mPosition.x; |
|
109 glyphs[i].y = aBuffer.mGlyphs[i].mPosition.y; |
|
110 } |
|
111 |
|
112 cairo_new_path(ctx); |
|
113 |
|
114 cairo_glyph_path(ctx, &glyphs[0], aBuffer.mNumGlyphs); |
|
115 |
|
116 RefPtr<PathCairo> newPath = new PathCairo(ctx); |
|
117 if (isNewContext) { |
|
118 cairo_destroy(ctx); |
|
119 } |
|
120 |
|
121 return newPath; |
|
122 } |
|
123 #endif |
|
124 return nullptr; |
|
125 } |
|
126 |
|
127 void |
|
128 ScaledFontBase::CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, BackendType aBackendType, const Matrix *aTransformHint) |
|
129 { |
|
130 #ifdef USE_SKIA |
|
131 if (aBackendType == BackendType::SKIA) { |
|
132 PathBuilderSkia *builder = static_cast<PathBuilderSkia*>(aBuilder); |
|
133 builder->AppendPath(GetSkiaPathForGlyphs(aBuffer)); |
|
134 return; |
|
135 } |
|
136 #endif |
|
137 #ifdef USE_CAIRO |
|
138 if (aBackendType == BackendType::CAIRO) { |
|
139 MOZ_ASSERT(mScaledFont); |
|
140 |
|
141 PathBuilderCairo* builder = static_cast<PathBuilderCairo*>(aBuilder); |
|
142 cairo_t *ctx = cairo_create(DrawTargetCairo::GetDummySurface()); |
|
143 |
|
144 if (aTransformHint) { |
|
145 cairo_matrix_t mat; |
|
146 GfxMatrixToCairoMatrix(*aTransformHint, mat); |
|
147 cairo_set_matrix(ctx, &mat); |
|
148 } |
|
149 |
|
150 // Convert our GlyphBuffer into an array of Cairo glyphs. |
|
151 std::vector<cairo_glyph_t> glyphs(aBuffer.mNumGlyphs); |
|
152 for (uint32_t i = 0; i < aBuffer.mNumGlyphs; ++i) { |
|
153 glyphs[i].index = aBuffer.mGlyphs[i].mIndex; |
|
154 glyphs[i].x = aBuffer.mGlyphs[i].mPosition.x; |
|
155 glyphs[i].y = aBuffer.mGlyphs[i].mPosition.y; |
|
156 } |
|
157 |
|
158 cairo_set_scaled_font(ctx, mScaledFont); |
|
159 cairo_glyph_path(ctx, &glyphs[0], aBuffer.mNumGlyphs); |
|
160 |
|
161 RefPtr<PathCairo> cairoPath = new PathCairo(ctx); |
|
162 cairo_destroy(ctx); |
|
163 |
|
164 cairoPath->AppendPathToBuilder(builder); |
|
165 return; |
|
166 } |
|
167 #endif |
|
168 |
|
169 MOZ_CRASH("The specified backend type is not supported by CopyGlyphsToBuilder"); |
|
170 } |
|
171 |
|
172 #ifdef USE_CAIRO_SCALED_FONT |
|
173 void |
|
174 ScaledFontBase::SetCairoScaledFont(cairo_scaled_font_t* font) |
|
175 { |
|
176 MOZ_ASSERT(!mScaledFont); |
|
177 |
|
178 if (font == mScaledFont) |
|
179 return; |
|
180 |
|
181 if (mScaledFont) |
|
182 cairo_scaled_font_destroy(mScaledFont); |
|
183 |
|
184 mScaledFont = font; |
|
185 cairo_scaled_font_reference(mScaledFont); |
|
186 } |
|
187 #endif |
|
188 |
|
189 } |
|
190 } |