gfx/skia/patches/0005-Bug-736276-Add-a-new-SkFontHost-that-takes-a-cairo_s.patch

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:2f7468d26d14
1 From: George Wright <george@mozilla.com>
2 Date: Wed, 1 Aug 2012 16:43:15 -0400
3 Subject: Bug 736276 - Add a new SkFontHost that takes a cairo_scaled_font_t r=karl
4
5
6 diff --git a/gfx/skia/Makefile.in b/gfx/skia/Makefile.in
7 index 5ebbd2e..7c8cdbf 100644
8 --- a/gfx/skia/Makefile.in
9 +++ b/gfx/skia/Makefile.in
10 @@ -60,15 +60,15 @@ VPATH += \
11 $(NULL)
12
13 ifeq (android,$(MOZ_WIDGET_TOOLKIT))
14 -OS_CXXFLAGS += $(CAIRO_FT_CFLAGS)
15 +OS_CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(CAIRO_FT_CFLAGS)
16 endif
17
18 ifeq (gtk2,$(MOZ_WIDGET_TOOLKIT))
19 -OS_CXXFLAGS += $(MOZ_PANGO_CFLAGS)
20 +OS_CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(MOZ_PANGO_CFLAGS) $(CAIRO_FT_CFLAGS)
21 endif
22
23 ifeq (qt,$(MOZ_WIDGET_TOOLKIT))
24 -OS_CXXFLAGS += $(MOZ_PANGO_CFLAGS)
25 +OS_CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(MOZ_PANGO_CFLAGS) $(CAIRO_FT_CFLAGS)
26 ifeq (Linux,$(OS_TARGET))
27 DEFINES += -DSK_USE_POSIX_THREADS=1
28 endif
29 diff --git a/gfx/skia/include/ports/SkTypeface_cairo.h b/gfx/skia/include/ports/SkTypeface_cairo.h
30 new file mode 100644
31 index 0000000..7e44f04
32 --- /dev/null
33 +++ b/gfx/skia/include/ports/SkTypeface_cairo.h
34 @@ -0,0 +1,11 @@
35 +#ifndef SkTypeface_cairo_DEFINED
36 +#define SkTypeface_cairo_DEFINED
37 +
38 +#include <cairo.h>
39 +
40 +#include "SkTypeface.h"
41 +
42 +SK_API extern SkTypeface* SkCreateTypefaceFromCairoFont(cairo_font_face_t* fontFace, SkTypeface::Style style, bool isFixedWidth);
43 +
44 +#endif
45 +
46 diff --git a/gfx/skia/moz.build b/gfx/skia/moz.build
47 index 9ceba59..66efd52 100644
48 --- a/gfx/skia/moz.build
49 +++ b/gfx/skia/moz.build
50 @@ -171,10 +171,12 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
51 'SkTime_win.cpp',
52 ]
53 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk2':
54 + EXPORTS.skia += [
55 + 'include/ports/SkTypeface_cairo.h',
56 + ]
57 CPP_SOURCES += [
58 - 'SkFontHost_FreeType.cpp',
59 + 'SkFontHost_cairo.cpp',
60 'SkFontHost_FreeType_common.cpp',
61 - 'SkFontHost_linux.cpp',
62 'SkThread_pthread.cpp',
63 'SkThreadUtils_pthread.cpp',
64 'SkThreadUtils_pthread_linux.cpp',
65 @@ -183,14 +185,15 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk2':
66 ]
67 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt':
68 CPP_SOURCES += [
69 - 'SkFontHost_FreeType.cpp',
70 + 'SkFontHost_cairo.cpp',
71 'SkFontHost_FreeType_common.cpp',
72 'SkOSFile.cpp',
73 ]
74 if CONFIG['OS_TARGET'] == 'Linux':
75 + EXPORTS.skia += [
76 + 'include/ports/SkTypeface_cairo.h',
77 + ]
78 CPP_SOURCES += [
79 - 'SkFontHost_linux.cpp',
80 - 'SkFontHost_tables.cpp',
81 'SkThread_pthread.cpp',
82 'SkThreadUtils_pthread.cpp',
83 'SkThreadUtils_pthread_linux.cpp',
84 @@ -204,11 +207,13 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
85 # Separate 'if' from above, since the else below applies to all != 'android'
86 # toolkits.
87 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
88 + EXPORTS.skia += [
89 + 'include/ports/SkTypeface_cairo.h',
90 + ]
91 CPP_SOURCES += [
92 'ashmem.cpp',
93 'SkDebug_android.cpp',
94 - 'SkFontHost_android_old.cpp',
95 - 'SkFontHost_FreeType.cpp',
96 + 'SkFontHost_cairo.cpp',
97 'SkFontHost_FreeType_common.cpp',
98 'SkImageRef_ashmem.cpp',
99 'SkTime_Unix.cpp',
100 diff --git a/gfx/skia/src/ports/SkFontHost_cairo.cpp b/gfx/skia/src/ports/SkFontHost_cairo.cpp
101 new file mode 100644
102 index 0000000..bb5b778
103 --- /dev/null
104 +++ b/gfx/skia/src/ports/SkFontHost_cairo.cpp
105 @@ -0,0 +1,364 @@
106 +
107 +/*
108 + * Copyright 2012 Mozilla Foundation
109 + *
110 + * Use of this source code is governed by a BSD-style license that can be
111 + * found in the LICENSE file.
112 + */
113 +
114 +#include "cairo.h"
115 +#include "cairo-ft.h"
116 +
117 +#include "SkFontHost_FreeType_common.h"
118 +
119 +#include "SkAdvancedTypefaceMetrics.h"
120 +#include "SkFontHost.h"
121 +#include "SkPath.h"
122 +#include "SkScalerContext.h"
123 +#include "SkTypefaceCache.h"
124 +
125 +#include <ft2build.h>
126 +#include FT_FREETYPE_H
127 +
128 +static cairo_user_data_key_t kSkTypefaceKey;
129 +
130 +class SkScalerContext_CairoFT : public SkScalerContext_FreeType_Base {
131 +public:
132 + SkScalerContext_CairoFT(SkTypeface* typeface, const SkDescriptor* desc);
133 + virtual ~SkScalerContext_CairoFT();
134 +
135 +protected:
136 + virtual unsigned generateGlyphCount() SK_OVERRIDE;
137 + virtual uint16_t generateCharToGlyph(SkUnichar uniChar) SK_OVERRIDE;
138 + virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
139 + virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
140 + virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
141 + virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
142 + virtual void generateFontMetrics(SkPaint::FontMetrics* mx,
143 + SkPaint::FontMetrics* my) SK_OVERRIDE;
144 + virtual SkUnichar generateGlyphToChar(uint16_t glyph) SK_OVERRIDE;
145 +private:
146 + cairo_scaled_font_t* fScaledFont;
147 + uint32_t fLoadGlyphFlags;
148 +};
149 +
150 +class CairoLockedFTFace {
151 +public:
152 + CairoLockedFTFace(cairo_scaled_font_t* scaledFont)
153 + : fScaledFont(scaledFont)
154 + , fFace(cairo_ft_scaled_font_lock_face(scaledFont))
155 + {}
156 +
157 + ~CairoLockedFTFace()
158 + {
159 + cairo_ft_scaled_font_unlock_face(fScaledFont);
160 + }
161 +
162 + FT_Face getFace()
163 + {
164 + return fFace;
165 + }
166 +
167 +private:
168 + cairo_scaled_font_t* fScaledFont;
169 + FT_Face fFace;
170 +};
171 +
172 +class SkCairoFTTypeface : public SkTypeface {
173 +public:
174 + static SkTypeface* CreateTypeface(cairo_font_face_t* fontFace, SkTypeface::Style style, bool isFixedWidth) {
175 + SkASSERT(fontFace != NULL);
176 + SkASSERT(cairo_font_face_get_type(fontFace) == CAIRO_FONT_TYPE_FT);
177 +
178 + SkFontID newId = SkTypefaceCache::NewFontID();
179 +
180 + return SkNEW_ARGS(SkCairoFTTypeface, (fontFace, style, newId, isFixedWidth));
181 + }
182 +
183 + cairo_font_face_t* getFontFace() {
184 + return fFontFace;
185 + }
186 +
187 + virtual SkStream* onOpenStream(int*) const SK_OVERRIDE { return NULL; }
188 +
189 + virtual SkAdvancedTypefaceMetrics*
190 + onGetAdvancedTypefaceMetrics(SkAdvancedTypefaceMetrics::PerGlyphInfo,
191 + const uint32_t*, uint32_t) const SK_OVERRIDE
192 + {
193 + SkDEBUGCODE(SkDebugf("SkCairoFTTypeface::onGetAdvancedTypefaceMetrics unimplemented\n"));
194 + return NULL;
195 + }
196 +
197 + virtual SkScalerContext* onCreateScalerContext(const SkDescriptor* desc) const SK_OVERRIDE
198 + {
199 + return SkNEW_ARGS(SkScalerContext_CairoFT, (const_cast<SkCairoFTTypeface*>(this), desc));
200 + }
201 +
202 + virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE
203 + {
204 + SkDEBUGCODE(SkDebugf("SkCairoFTTypeface::onFilterRec unimplemented\n"));
205 + }
206 +
207 + virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE
208 + {
209 + SkDEBUGCODE(SkDebugf("SkCairoFTTypeface::onGetFontDescriptor unimplemented\n"));
210 + }
211 +
212 +
213 +private:
214 +
215 + SkCairoFTTypeface(cairo_font_face_t* fontFace, SkTypeface::Style style, SkFontID id, bool isFixedWidth)
216 + : SkTypeface(style, id, isFixedWidth)
217 + , fFontFace(fontFace)
218 + {
219 + cairo_font_face_set_user_data(fFontFace, &kSkTypefaceKey, this, NULL);
220 + cairo_font_face_reference(fFontFace);
221 + }
222 +
223 + ~SkCairoFTTypeface()
224 + {
225 + cairo_font_face_set_user_data(fFontFace, &kSkTypefaceKey, NULL, NULL);
226 + cairo_font_face_destroy(fFontFace);
227 + }
228 +
229 + cairo_font_face_t* fFontFace;
230 +};
231 +
232 +SkTypeface* SkCreateTypefaceFromCairoFont(cairo_font_face_t* fontFace, SkTypeface::Style style, bool isFixedWidth)
233 +{
234 + SkTypeface* typeface = reinterpret_cast<SkTypeface*>(cairo_font_face_get_user_data(fontFace, &kSkTypefaceKey));
235 +
236 + if (typeface) {
237 + typeface->ref();
238 + } else {
239 + typeface = SkCairoFTTypeface::CreateTypeface(fontFace, style, isFixedWidth);
240 + SkTypefaceCache::Add(typeface, style);
241 + }
242 +
243 + return typeface;
244 +}
245 +
246 +SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
247 + const char famillyName[],
248 + SkTypeface::Style style)
249 +{
250 + SkDEBUGFAIL("SkFontHost::FindTypeface unimplemented");
251 + return NULL;
252 +}
253 +
254 +SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream*)
255 +{
256 + SkDEBUGFAIL("SkFontHost::CreateTypeface unimplemented");
257 + return NULL;
258 +}
259 +
260 +SkTypeface* SkFontHost::CreateTypefaceFromFile(char const*)
261 +{
262 + SkDEBUGFAIL("SkFontHost::CreateTypefaceFromFile unimplemented");
263 + return NULL;
264 +}
265 +
266 +///////////////////////////////////////////////////////////////////////////////
267 +
268 +static bool isLCD(const SkScalerContext::Rec& rec) {
269 + switch (rec.fMaskFormat) {
270 + case SkMask::kLCD16_Format:
271 + case SkMask::kLCD32_Format:
272 + return true;
273 + default:
274 + return false;
275 + }
276 +}
277 +
278 +///////////////////////////////////////////////////////////////////////////////
279 +SkScalerContext_CairoFT::SkScalerContext_CairoFT(SkTypeface* typeface, const SkDescriptor* desc)
280 + : SkScalerContext_FreeType_Base(typeface, desc)
281 +{
282 + SkMatrix matrix;
283 + fRec.getSingleMatrix(&matrix);
284 +
285 + cairo_font_face_t* fontFace = static_cast<SkCairoFTTypeface*>(typeface)->getFontFace();
286 +
287 + cairo_matrix_t fontMatrix, ctMatrix;
288 + cairo_matrix_init(&fontMatrix, matrix.getScaleX(), matrix.getSkewY(), matrix.getSkewX(), matrix.getScaleY(), 0.0, 0.0);
289 + cairo_matrix_init_scale(&ctMatrix, 1.0, 1.0);
290 +
291 + // We need to ensure that the font options match for hinting, as generateMetrics()
292 + // uses the fScaledFont which uses these font options
293 + cairo_font_options_t *fontOptions = cairo_font_options_create();
294 +
295 + FT_Int32 loadFlags = FT_LOAD_DEFAULT;
296 +
297 + if (SkMask::kBW_Format == fRec.fMaskFormat) {
298 + // See http://code.google.com/p/chromium/issues/detail?id=43252#c24
299 + loadFlags = FT_LOAD_TARGET_MONO;
300 + if (fRec.getHinting() == SkPaint::kNo_Hinting) {
301 + cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_NONE);
302 + loadFlags = FT_LOAD_NO_HINTING;
303 + }
304 + } else {
305 + switch (fRec.getHinting()) {
306 + case SkPaint::kNo_Hinting:
307 + loadFlags = FT_LOAD_NO_HINTING;
308 + cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_NONE);
309 + break;
310 + case SkPaint::kSlight_Hinting:
311 + loadFlags = FT_LOAD_TARGET_LIGHT; // This implies FORCE_AUTOHINT
312 + cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_SLIGHT);
313 + break;
314 + case SkPaint::kNormal_Hinting:
315 + cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_MEDIUM);
316 + if (fRec.fFlags & SkScalerContext::kAutohinting_Flag) {
317 + loadFlags = FT_LOAD_FORCE_AUTOHINT;
318 + }
319 + break;
320 + case SkPaint::kFull_Hinting:
321 + cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_FULL);
322 + if (fRec.fFlags & SkScalerContext::kAutohinting_Flag) {
323 + loadFlags = FT_LOAD_FORCE_AUTOHINT;
324 + }
325 + if (isLCD(fRec)) {
326 + if (SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag)) {
327 + loadFlags = FT_LOAD_TARGET_LCD_V;
328 + } else {
329 + loadFlags = FT_LOAD_TARGET_LCD;
330 + }
331 + }
332 + break;
333 + default:
334 + SkDebugf("---------- UNKNOWN hinting %d\n", fRec.getHinting());
335 + break;
336 + }
337 + }
338 +
339 + fScaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctMatrix, fontOptions);
340 +
341 + if ((fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag) == 0) {
342 + loadFlags |= FT_LOAD_NO_BITMAP;
343 + }
344 +
345 + // Always using FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH to get correct
346 + // advances, as fontconfig and cairo do.
347 + // See http://code.google.com/p/skia/issues/detail?id=222.
348 + loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
349 +
350 + fLoadGlyphFlags = loadFlags;
351 +}
352 +
353 +SkScalerContext_CairoFT::~SkScalerContext_CairoFT()
354 +{
355 + cairo_scaled_font_destroy(fScaledFont);
356 +}
357 +
358 +unsigned SkScalerContext_CairoFT::generateGlyphCount()
359 +{
360 + CairoLockedFTFace faceLock(fScaledFont);
361 + return faceLock.getFace()->num_glyphs;
362 +}
363 +
364 +uint16_t SkScalerContext_CairoFT::generateCharToGlyph(SkUnichar uniChar)
365 +{
366 + CairoLockedFTFace faceLock(fScaledFont);
367 + return SkToU16(FT_Get_Char_Index(faceLock.getFace(), uniChar));
368 +}
369 +
370 +void SkScalerContext_CairoFT::generateAdvance(SkGlyph* glyph)
371 +{
372 + generateMetrics(glyph);
373 +}
374 +
375 +void SkScalerContext_CairoFT::generateMetrics(SkGlyph* glyph)
376 +{
377 + SkASSERT(fScaledFont != NULL);
378 + cairo_text_extents_t extents;
379 + cairo_glyph_t cairoGlyph = { glyph->getGlyphID(fBaseGlyphCount), 0.0, 0.0 };
380 + cairo_scaled_font_glyph_extents(fScaledFont, &cairoGlyph, 1, &extents);
381 +
382 + glyph->fAdvanceX = SkDoubleToFixed(extents.x_advance);
383 + glyph->fAdvanceY = SkDoubleToFixed(extents.y_advance);
384 + glyph->fWidth = SkToU16(SkScalarCeil(extents.width));
385 + glyph->fHeight = SkToU16(SkScalarCeil(extents.height));
386 + glyph->fLeft = SkToS16(SkScalarCeil(extents.x_bearing));
387 + glyph->fTop = SkToS16(SkScalarCeil(extents.y_bearing));
388 + glyph->fLsbDelta = 0;
389 + glyph->fRsbDelta = 0;
390 +}
391 +
392 +void SkScalerContext_CairoFT::generateImage(const SkGlyph& glyph)
393 +{
394 + SkASSERT(fScaledFont != NULL);
395 + CairoLockedFTFace faceLock(fScaledFont);
396 + FT_Face face = faceLock.getFace();
397 +
398 + FT_Error err = FT_Load_Glyph(face, glyph.getGlyphID(fBaseGlyphCount), fLoadGlyphFlags);
399 +
400 + if (err != 0) {
401 + memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
402 + return;
403 + }
404 +
405 + generateGlyphImage(face, glyph);
406 +}
407 +
408 +void SkScalerContext_CairoFT::generatePath(const SkGlyph& glyph, SkPath* path)
409 +{
410 + SkASSERT(fScaledFont != NULL);
411 + CairoLockedFTFace faceLock(fScaledFont);
412 + FT_Face face = faceLock.getFace();
413 +
414 + SkASSERT(&glyph && path);
415 +
416 + uint32_t flags = fLoadGlyphFlags;
417 + flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline
418 + flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline)
419 +
420 + FT_Error err = FT_Load_Glyph(face, glyph.getGlyphID(fBaseGlyphCount), flags);
421 +
422 + if (err != 0) {
423 + path->reset();
424 + return;
425 + }
426 +
427 + generateGlyphPath(face, path);
428 +}
429 +
430 +void SkScalerContext_CairoFT::generateFontMetrics(SkPaint::FontMetrics* mx,
431 + SkPaint::FontMetrics* my)
432 +{
433 + SkDEBUGCODE(SkDebugf("SkScalerContext_CairoFT::generateFontMetrics unimplemented\n"));
434 +}
435 +
436 +SkUnichar SkScalerContext_CairoFT::generateGlyphToChar(uint16_t glyph)
437 +{
438 + SkASSERT(fScaledFont != NULL);
439 + CairoLockedFTFace faceLock(fScaledFont);
440 + FT_Face face = faceLock.getFace();
441 +
442 + FT_UInt glyphIndex;
443 + SkUnichar charCode = FT_Get_First_Char(face, &glyphIndex);
444 + while (glyphIndex != 0) {
445 + if (glyphIndex == glyph) {
446 + return charCode;
447 + }
448 + charCode = FT_Get_Next_Char(face, charCode, &glyphIndex);
449 + }
450 +
451 + return 0;
452 +}
453 +
454 +#ifdef SK_BUILD_FOR_ANDROID
455 +SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID,
456 + SkFontID origFontID) {
457 + return NULL;
458 +}
459 +#endif
460 +
461 +///////////////////////////////////////////////////////////////////////////////
462 +
463 +#include "SkFontMgr.h"
464 +
465 +SkFontMgr* SkFontMgr::Factory() {
466 + // todo
467 + return NULL;
468 +}
469 +
470 --
471 1.7.11.7
472

mercurial