gfx/skia/trunk/src/ports/SkFontHost_cairo.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1
michael@0 2 /*
michael@0 3 * Copyright 2012 Mozilla Foundation
michael@0 4 *
michael@0 5 * Use of this source code is governed by a BSD-style license that can be
michael@0 6 * found in the LICENSE file.
michael@0 7 */
michael@0 8
michael@0 9 #include "cairo.h"
michael@0 10 #include "cairo-ft.h"
michael@0 11
michael@0 12 #include "SkFontHost_FreeType_common.h"
michael@0 13
michael@0 14 #include "SkAdvancedTypefaceMetrics.h"
michael@0 15 #include "SkFontHost.h"
michael@0 16 #include "SkPath.h"
michael@0 17 #include "SkScalerContext.h"
michael@0 18 #include "SkTypefaceCache.h"
michael@0 19
michael@0 20 #include <ft2build.h>
michael@0 21 #include FT_FREETYPE_H
michael@0 22
michael@0 23 #ifndef SK_FONTHOST_CAIRO_STANDALONE
michael@0 24 #define SK_FONTHOST_CAIRO_STANDALONE 1
michael@0 25 #endif
michael@0 26
michael@0 27 static cairo_user_data_key_t kSkTypefaceKey;
michael@0 28
michael@0 29 class SkScalerContext_CairoFT : public SkScalerContext_FreeType_Base {
michael@0 30 public:
michael@0 31 SkScalerContext_CairoFT(SkTypeface* typeface, const SkDescriptor* desc);
michael@0 32 virtual ~SkScalerContext_CairoFT();
michael@0 33
michael@0 34 protected:
michael@0 35 virtual unsigned generateGlyphCount() SK_OVERRIDE;
michael@0 36 virtual uint16_t generateCharToGlyph(SkUnichar uniChar) SK_OVERRIDE;
michael@0 37 virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
michael@0 38 virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
michael@0 39 virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
michael@0 40 virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
michael@0 41 virtual void generateFontMetrics(SkPaint::FontMetrics* mx,
michael@0 42 SkPaint::FontMetrics* my) SK_OVERRIDE;
michael@0 43 virtual SkUnichar generateGlyphToChar(uint16_t glyph) SK_OVERRIDE;
michael@0 44 private:
michael@0 45 cairo_scaled_font_t* fScaledFont;
michael@0 46 uint32_t fLoadGlyphFlags;
michael@0 47 };
michael@0 48
michael@0 49 class CairoLockedFTFace {
michael@0 50 public:
michael@0 51 CairoLockedFTFace(cairo_scaled_font_t* scaledFont)
michael@0 52 : fScaledFont(scaledFont)
michael@0 53 , fFace(cairo_ft_scaled_font_lock_face(scaledFont))
michael@0 54 {}
michael@0 55
michael@0 56 ~CairoLockedFTFace()
michael@0 57 {
michael@0 58 cairo_ft_scaled_font_unlock_face(fScaledFont);
michael@0 59 }
michael@0 60
michael@0 61 FT_Face getFace()
michael@0 62 {
michael@0 63 return fFace;
michael@0 64 }
michael@0 65
michael@0 66 private:
michael@0 67 cairo_scaled_font_t* fScaledFont;
michael@0 68 FT_Face fFace;
michael@0 69 };
michael@0 70
michael@0 71 class SkCairoFTTypeface : public SkTypeface {
michael@0 72 public:
michael@0 73 static SkTypeface* CreateTypeface(cairo_font_face_t* fontFace, SkTypeface::Style style, bool isFixedWidth) {
michael@0 74 SkASSERT(fontFace != NULL);
michael@0 75 SkASSERT(cairo_font_face_get_type(fontFace) == CAIRO_FONT_TYPE_FT);
michael@0 76
michael@0 77 SkFontID newId = SkTypefaceCache::NewFontID();
michael@0 78
michael@0 79 return SkNEW_ARGS(SkCairoFTTypeface, (fontFace, style, newId, isFixedWidth));
michael@0 80 }
michael@0 81
michael@0 82 cairo_font_face_t* getFontFace() {
michael@0 83 return fFontFace;
michael@0 84 }
michael@0 85
michael@0 86 virtual SkStream* onOpenStream(int*) const SK_OVERRIDE { return NULL; }
michael@0 87
michael@0 88 virtual SkAdvancedTypefaceMetrics*
michael@0 89 onGetAdvancedTypefaceMetrics(SkAdvancedTypefaceMetrics::PerGlyphInfo,
michael@0 90 const uint32_t*, uint32_t) const SK_OVERRIDE
michael@0 91 {
michael@0 92 SkDEBUGCODE(SkDebugf("SkCairoFTTypeface::onGetAdvancedTypefaceMetrics unimplemented\n"));
michael@0 93 return NULL;
michael@0 94 }
michael@0 95
michael@0 96 virtual SkScalerContext* onCreateScalerContext(const SkDescriptor* desc) const SK_OVERRIDE
michael@0 97 {
michael@0 98 return SkNEW_ARGS(SkScalerContext_CairoFT, (const_cast<SkCairoFTTypeface*>(this), desc));
michael@0 99 }
michael@0 100
michael@0 101 virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE
michael@0 102 {
michael@0 103 SkDEBUGCODE(SkDebugf("SkCairoFTTypeface::onFilterRec unimplemented\n"));
michael@0 104 }
michael@0 105
michael@0 106 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE
michael@0 107 {
michael@0 108 SkDEBUGCODE(SkDebugf("SkCairoFTTypeface::onGetFontDescriptor unimplemented\n"));
michael@0 109 }
michael@0 110
michael@0 111 virtual int onCharsToGlyphs(void const*, SkTypeface::Encoding, uint16_t*, int) const SK_OVERRIDE
michael@0 112 {
michael@0 113 return 0;
michael@0 114 }
michael@0 115
michael@0 116 virtual int onCountGlyphs() const SK_OVERRIDE
michael@0 117 {
michael@0 118 return 0;
michael@0 119 }
michael@0 120
michael@0 121 virtual int onGetUPEM() const SK_OVERRIDE
michael@0 122 {
michael@0 123 return 0;
michael@0 124 }
michael@0 125
michael@0 126 virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE
michael@0 127 {
michael@0 128 return NULL;
michael@0 129 }
michael@0 130
michael@0 131 virtual int onGetTableTags(SkFontTableTag*) const SK_OVERRIDE
michael@0 132 {
michael@0 133 return 0;
michael@0 134 }
michael@0 135
michael@0 136 virtual size_t onGetTableData(SkFontTableTag, size_t, size_t, void*) const SK_OVERRIDE
michael@0 137 {
michael@0 138 return 0;
michael@0 139 }
michael@0 140
michael@0 141 private:
michael@0 142
michael@0 143 SkCairoFTTypeface(cairo_font_face_t* fontFace, SkTypeface::Style style, SkFontID id, bool isFixedWidth)
michael@0 144 : SkTypeface(style, id, isFixedWidth)
michael@0 145 , fFontFace(fontFace)
michael@0 146 {
michael@0 147 cairo_font_face_set_user_data(fFontFace, &kSkTypefaceKey, this, NULL);
michael@0 148 cairo_font_face_reference(fFontFace);
michael@0 149 }
michael@0 150
michael@0 151 ~SkCairoFTTypeface()
michael@0 152 {
michael@0 153 cairo_font_face_set_user_data(fFontFace, &kSkTypefaceKey, NULL, NULL);
michael@0 154 cairo_font_face_destroy(fFontFace);
michael@0 155 }
michael@0 156
michael@0 157 cairo_font_face_t* fFontFace;
michael@0 158 };
michael@0 159
michael@0 160 SkTypeface* SkCreateTypefaceFromCairoFont(cairo_font_face_t* fontFace, SkTypeface::Style style, bool isFixedWidth)
michael@0 161 {
michael@0 162 SkTypeface* typeface = reinterpret_cast<SkTypeface*>(cairo_font_face_get_user_data(fontFace, &kSkTypefaceKey));
michael@0 163
michael@0 164 if (typeface) {
michael@0 165 typeface->ref();
michael@0 166 } else {
michael@0 167 typeface = SkCairoFTTypeface::CreateTypeface(fontFace, style, isFixedWidth);
michael@0 168 SkTypefaceCache::Add(typeface, style);
michael@0 169 }
michael@0 170
michael@0 171 return typeface;
michael@0 172 }
michael@0 173
michael@0 174 #if defined(SK_FONTHOST_DOES_NOT_USE_FONTMGR) && SK_FONTHOST_CAIRO_STANDALONE
michael@0 175 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
michael@0 176 const char famillyName[],
michael@0 177 SkTypeface::Style style)
michael@0 178 {
michael@0 179 SkDEBUGFAIL("SkFontHost::FindTypeface unimplemented");
michael@0 180 return NULL;
michael@0 181 }
michael@0 182
michael@0 183 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream*)
michael@0 184 {
michael@0 185 SkDEBUGFAIL("SkFontHost::CreateTypeface unimplemented");
michael@0 186 return NULL;
michael@0 187 }
michael@0 188
michael@0 189 SkTypeface* SkFontHost::CreateTypefaceFromFile(char const*)
michael@0 190 {
michael@0 191 SkDEBUGFAIL("SkFontHost::CreateTypefaceFromFile unimplemented");
michael@0 192 return NULL;
michael@0 193 }
michael@0 194 #endif
michael@0 195
michael@0 196 ///////////////////////////////////////////////////////////////////////////////
michael@0 197
michael@0 198 static bool isLCD(const SkScalerContext::Rec& rec) {
michael@0 199 switch (rec.fMaskFormat) {
michael@0 200 case SkMask::kLCD16_Format:
michael@0 201 case SkMask::kLCD32_Format:
michael@0 202 return true;
michael@0 203 default:
michael@0 204 return false;
michael@0 205 }
michael@0 206 }
michael@0 207
michael@0 208 ///////////////////////////////////////////////////////////////////////////////
michael@0 209 SkScalerContext_CairoFT::SkScalerContext_CairoFT(SkTypeface* typeface, const SkDescriptor* desc)
michael@0 210 : SkScalerContext_FreeType_Base(typeface, desc)
michael@0 211 {
michael@0 212 SkMatrix matrix;
michael@0 213 fRec.getSingleMatrix(&matrix);
michael@0 214
michael@0 215 cairo_font_face_t* fontFace = static_cast<SkCairoFTTypeface*>(typeface)->getFontFace();
michael@0 216
michael@0 217 cairo_matrix_t fontMatrix, ctMatrix;
michael@0 218 cairo_matrix_init(&fontMatrix, matrix.getScaleX(), matrix.getSkewY(), matrix.getSkewX(), matrix.getScaleY(), 0.0, 0.0);
michael@0 219 cairo_matrix_init_scale(&ctMatrix, 1.0, 1.0);
michael@0 220
michael@0 221 // We need to ensure that the font options match for hinting, as generateMetrics()
michael@0 222 // uses the fScaledFont which uses these font options
michael@0 223 cairo_font_options_t *fontOptions = cairo_font_options_create();
michael@0 224
michael@0 225 FT_Int32 loadFlags = FT_LOAD_DEFAULT;
michael@0 226
michael@0 227 if (SkMask::kBW_Format == fRec.fMaskFormat) {
michael@0 228 // See http://code.google.com/p/chromium/issues/detail?id=43252#c24
michael@0 229 loadFlags = FT_LOAD_TARGET_MONO;
michael@0 230 if (fRec.getHinting() == SkPaint::kNo_Hinting) {
michael@0 231 cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_NONE);
michael@0 232 loadFlags = FT_LOAD_NO_HINTING;
michael@0 233 }
michael@0 234 } else {
michael@0 235 switch (fRec.getHinting()) {
michael@0 236 case SkPaint::kNo_Hinting:
michael@0 237 loadFlags = FT_LOAD_NO_HINTING;
michael@0 238 cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_NONE);
michael@0 239 break;
michael@0 240 case SkPaint::kSlight_Hinting:
michael@0 241 loadFlags = FT_LOAD_TARGET_LIGHT; // This implies FORCE_AUTOHINT
michael@0 242 cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_SLIGHT);
michael@0 243 break;
michael@0 244 case SkPaint::kNormal_Hinting:
michael@0 245 cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_MEDIUM);
michael@0 246 if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) {
michael@0 247 loadFlags = FT_LOAD_FORCE_AUTOHINT;
michael@0 248 }
michael@0 249 break;
michael@0 250 case SkPaint::kFull_Hinting:
michael@0 251 cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_FULL);
michael@0 252 if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) {
michael@0 253 loadFlags = FT_LOAD_FORCE_AUTOHINT;
michael@0 254 }
michael@0 255 if (isLCD(fRec)) {
michael@0 256 if (SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag)) {
michael@0 257 loadFlags = FT_LOAD_TARGET_LCD_V;
michael@0 258 } else {
michael@0 259 loadFlags = FT_LOAD_TARGET_LCD;
michael@0 260 }
michael@0 261 }
michael@0 262 break;
michael@0 263 default:
michael@0 264 SkDebugf("---------- UNKNOWN hinting %d\n", fRec.getHinting());
michael@0 265 break;
michael@0 266 }
michael@0 267 }
michael@0 268
michael@0 269 fScaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctMatrix, fontOptions);
michael@0 270
michael@0 271 if ((fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag) == 0) {
michael@0 272 loadFlags |= FT_LOAD_NO_BITMAP;
michael@0 273 }
michael@0 274
michael@0 275 // Always using FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH to get correct
michael@0 276 // advances, as fontconfig and cairo do.
michael@0 277 // See http://code.google.com/p/skia/issues/detail?id=222.
michael@0 278 loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
michael@0 279
michael@0 280 fLoadGlyphFlags = loadFlags;
michael@0 281 }
michael@0 282
michael@0 283 SkScalerContext_CairoFT::~SkScalerContext_CairoFT()
michael@0 284 {
michael@0 285 cairo_scaled_font_destroy(fScaledFont);
michael@0 286 }
michael@0 287
michael@0 288 unsigned SkScalerContext_CairoFT::generateGlyphCount()
michael@0 289 {
michael@0 290 CairoLockedFTFace faceLock(fScaledFont);
michael@0 291 return faceLock.getFace()->num_glyphs;
michael@0 292 }
michael@0 293
michael@0 294 uint16_t SkScalerContext_CairoFT::generateCharToGlyph(SkUnichar uniChar)
michael@0 295 {
michael@0 296 CairoLockedFTFace faceLock(fScaledFont);
michael@0 297 return SkToU16(FT_Get_Char_Index(faceLock.getFace(), uniChar));
michael@0 298 }
michael@0 299
michael@0 300 void SkScalerContext_CairoFT::generateAdvance(SkGlyph* glyph)
michael@0 301 {
michael@0 302 generateMetrics(glyph);
michael@0 303 }
michael@0 304
michael@0 305 void SkScalerContext_CairoFT::generateMetrics(SkGlyph* glyph)
michael@0 306 {
michael@0 307 SkASSERT(fScaledFont != NULL);
michael@0 308 cairo_text_extents_t extents;
michael@0 309 cairo_glyph_t cairoGlyph = { glyph->getGlyphID(fBaseGlyphCount), 0.0, 0.0 };
michael@0 310 cairo_scaled_font_glyph_extents(fScaledFont, &cairoGlyph, 1, &extents);
michael@0 311
michael@0 312 glyph->fAdvanceX = SkDoubleToFixed(extents.x_advance);
michael@0 313 glyph->fAdvanceY = SkDoubleToFixed(extents.y_advance);
michael@0 314 glyph->fWidth = SkToU16(SkScalarCeilToInt(extents.width));
michael@0 315 glyph->fHeight = SkToU16(SkScalarCeilToInt(extents.height));
michael@0 316 glyph->fLeft = SkToS16(SkScalarCeilToInt(extents.x_bearing));
michael@0 317 glyph->fTop = SkToS16(SkScalarCeilToInt(extents.y_bearing));
michael@0 318 glyph->fLsbDelta = 0;
michael@0 319 glyph->fRsbDelta = 0;
michael@0 320 }
michael@0 321
michael@0 322 void SkScalerContext_CairoFT::generateImage(const SkGlyph& glyph)
michael@0 323 {
michael@0 324 SkASSERT(fScaledFont != NULL);
michael@0 325 CairoLockedFTFace faceLock(fScaledFont);
michael@0 326 FT_Face face = faceLock.getFace();
michael@0 327
michael@0 328 FT_Error err = FT_Load_Glyph(face, glyph.getGlyphID(fBaseGlyphCount), fLoadGlyphFlags);
michael@0 329
michael@0 330 if (err != 0) {
michael@0 331 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
michael@0 332 return;
michael@0 333 }
michael@0 334
michael@0 335 generateGlyphImage(face, glyph);
michael@0 336 }
michael@0 337
michael@0 338 void SkScalerContext_CairoFT::generatePath(const SkGlyph& glyph, SkPath* path)
michael@0 339 {
michael@0 340 SkASSERT(fScaledFont != NULL);
michael@0 341 CairoLockedFTFace faceLock(fScaledFont);
michael@0 342 FT_Face face = faceLock.getFace();
michael@0 343
michael@0 344 SkASSERT(&glyph && path);
michael@0 345
michael@0 346 uint32_t flags = fLoadGlyphFlags;
michael@0 347 flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline
michael@0 348 flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline)
michael@0 349
michael@0 350 FT_Error err = FT_Load_Glyph(face, glyph.getGlyphID(fBaseGlyphCount), flags);
michael@0 351
michael@0 352 if (err != 0) {
michael@0 353 path->reset();
michael@0 354 return;
michael@0 355 }
michael@0 356
michael@0 357 generateGlyphPath(face, path);
michael@0 358 }
michael@0 359
michael@0 360 void SkScalerContext_CairoFT::generateFontMetrics(SkPaint::FontMetrics* mx,
michael@0 361 SkPaint::FontMetrics* my)
michael@0 362 {
michael@0 363 SkDEBUGCODE(SkDebugf("SkScalerContext_CairoFT::generateFontMetrics unimplemented\n"));
michael@0 364 }
michael@0 365
michael@0 366 SkUnichar SkScalerContext_CairoFT::generateGlyphToChar(uint16_t glyph)
michael@0 367 {
michael@0 368 SkASSERT(fScaledFont != NULL);
michael@0 369 CairoLockedFTFace faceLock(fScaledFont);
michael@0 370 FT_Face face = faceLock.getFace();
michael@0 371
michael@0 372 FT_UInt glyphIndex;
michael@0 373 SkUnichar charCode = FT_Get_First_Char(face, &glyphIndex);
michael@0 374 while (glyphIndex != 0) {
michael@0 375 if (glyphIndex == glyph) {
michael@0 376 return charCode;
michael@0 377 }
michael@0 378 charCode = FT_Get_Next_Char(face, charCode, &glyphIndex);
michael@0 379 }
michael@0 380
michael@0 381 return 0;
michael@0 382 }
michael@0 383
michael@0 384 ///////////////////////////////////////////////////////////////////////////////
michael@0 385
michael@0 386 #include "SkFontMgr.h"
michael@0 387
michael@0 388 SkFontMgr* SkFontMgr::Factory() {
michael@0 389 // todo
michael@0 390 return NULL;
michael@0 391 }
michael@0 392

mercurial