Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
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/. */
6 #include "ScaledFontBase.h"
8 #ifdef USE_SKIA
9 #include "PathSkia.h"
10 #include "skia/SkEmptyShader.h"
11 #include "skia/SkPaint.h"
12 #endif
14 #ifdef USE_CAIRO
15 #include "PathCairo.h"
16 #include "DrawTargetCairo.h"
17 #include "HelpersCairo.h"
18 #endif
20 #include <vector>
21 #include <cmath>
23 using namespace std;
25 namespace mozilla {
26 namespace gfx {
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 }
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 }
49 #ifdef USE_SKIA
50 SkPath
51 ScaledFontBase::GetSkiaPathForGlyphs(const GlyphBuffer &aBuffer)
52 {
53 SkTypeface *typeFace = GetSkTypeface();
54 MOZ_ASSERT(typeFace);
56 SkPaint paint;
57 paint.setTypeface(typeFace);
58 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
59 paint.setTextSize(SkFloatToScalar(mSize));
61 std::vector<uint16_t> indices;
62 std::vector<SkPoint> offsets;
63 indices.resize(aBuffer.mNumGlyphs);
64 offsets.resize(aBuffer.mNumGlyphs);
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 }
72 SkPath path;
73 paint.getPosTextPath(&indices.front(), aBuffer.mNumGlyphs*2, &offsets.front(), &path);
74 return path;
75 }
76 #endif
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);
91 DrawTarget *dt = const_cast<DrawTarget*>(aTarget);
92 cairo_t *ctx = static_cast<cairo_t*>(dt->GetNativeSurface(NativeSurfaceType::CAIRO_CONTEXT));
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 }
102 cairo_set_scaled_font(ctx, mScaledFont);
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 }
112 cairo_new_path(ctx);
114 cairo_glyph_path(ctx, &glyphs[0], aBuffer.mNumGlyphs);
116 RefPtr<PathCairo> newPath = new PathCairo(ctx);
117 if (isNewContext) {
118 cairo_destroy(ctx);
119 }
121 return newPath;
122 }
123 #endif
124 return nullptr;
125 }
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);
141 PathBuilderCairo* builder = static_cast<PathBuilderCairo*>(aBuilder);
142 cairo_t *ctx = cairo_create(DrawTargetCairo::GetDummySurface());
144 if (aTransformHint) {
145 cairo_matrix_t mat;
146 GfxMatrixToCairoMatrix(*aTransformHint, mat);
147 cairo_set_matrix(ctx, &mat);
148 }
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 }
158 cairo_set_scaled_font(ctx, mScaledFont);
159 cairo_glyph_path(ctx, &glyphs[0], aBuffer.mNumGlyphs);
161 RefPtr<PathCairo> cairoPath = new PathCairo(ctx);
162 cairo_destroy(ctx);
164 cairoPath->AppendPathToBuilder(builder);
165 return;
166 }
167 #endif
169 MOZ_CRASH("The specified backend type is not supported by CopyGlyphsToBuilder");
170 }
172 #ifdef USE_CAIRO_SCALED_FONT
173 void
174 ScaledFontBase::SetCairoScaledFont(cairo_scaled_font_t* font)
175 {
176 MOZ_ASSERT(!mScaledFont);
178 if (font == mScaledFont)
179 return;
181 if (mScaledFont)
182 cairo_scaled_font_destroy(mScaledFont);
184 mScaledFont = font;
185 cairo_scaled_font_reference(mScaledFont);
186 }
187 #endif
189 }
190 }