1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/2d/ScaledFontBase.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,190 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "ScaledFontBase.h" 1.10 + 1.11 +#ifdef USE_SKIA 1.12 +#include "PathSkia.h" 1.13 +#include "skia/SkEmptyShader.h" 1.14 +#include "skia/SkPaint.h" 1.15 +#endif 1.16 + 1.17 +#ifdef USE_CAIRO 1.18 +#include "PathCairo.h" 1.19 +#include "DrawTargetCairo.h" 1.20 +#include "HelpersCairo.h" 1.21 +#endif 1.22 + 1.23 +#include <vector> 1.24 +#include <cmath> 1.25 + 1.26 +using namespace std; 1.27 + 1.28 +namespace mozilla { 1.29 +namespace gfx { 1.30 + 1.31 +ScaledFontBase::~ScaledFontBase() 1.32 +{ 1.33 +#ifdef USE_SKIA 1.34 + SkSafeUnref(mTypeface); 1.35 +#endif 1.36 +#ifdef USE_CAIRO_SCALED_FONT 1.37 + cairo_scaled_font_destroy(mScaledFont); 1.38 +#endif 1.39 +} 1.40 + 1.41 +ScaledFontBase::ScaledFontBase(Float aSize) 1.42 + : mSize(aSize) 1.43 +{ 1.44 +#ifdef USE_SKIA 1.45 + mTypeface = nullptr; 1.46 +#endif 1.47 +#ifdef USE_CAIRO_SCALED_FONT 1.48 + mScaledFont = nullptr; 1.49 +#endif 1.50 +} 1.51 + 1.52 +#ifdef USE_SKIA 1.53 +SkPath 1.54 +ScaledFontBase::GetSkiaPathForGlyphs(const GlyphBuffer &aBuffer) 1.55 +{ 1.56 + SkTypeface *typeFace = GetSkTypeface(); 1.57 + MOZ_ASSERT(typeFace); 1.58 + 1.59 + SkPaint paint; 1.60 + paint.setTypeface(typeFace); 1.61 + paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 1.62 + paint.setTextSize(SkFloatToScalar(mSize)); 1.63 + 1.64 + std::vector<uint16_t> indices; 1.65 + std::vector<SkPoint> offsets; 1.66 + indices.resize(aBuffer.mNumGlyphs); 1.67 + offsets.resize(aBuffer.mNumGlyphs); 1.68 + 1.69 + for (unsigned int i = 0; i < aBuffer.mNumGlyphs; i++) { 1.70 + indices[i] = aBuffer.mGlyphs[i].mIndex; 1.71 + offsets[i].fX = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.x); 1.72 + offsets[i].fY = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.y); 1.73 + } 1.74 + 1.75 + SkPath path; 1.76 + paint.getPosTextPath(&indices.front(), aBuffer.mNumGlyphs*2, &offsets.front(), &path); 1.77 + return path; 1.78 +} 1.79 +#endif 1.80 + 1.81 +TemporaryRef<Path> 1.82 +ScaledFontBase::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget) 1.83 +{ 1.84 +#ifdef USE_SKIA 1.85 + if (aTarget->GetType() == BackendType::SKIA) { 1.86 + SkPath path = GetSkiaPathForGlyphs(aBuffer); 1.87 + return new PathSkia(path, FillRule::FILL_WINDING); 1.88 + } 1.89 +#endif 1.90 +#ifdef USE_CAIRO 1.91 + if (aTarget->GetType() == BackendType::CAIRO) { 1.92 + MOZ_ASSERT(mScaledFont); 1.93 + 1.94 + DrawTarget *dt = const_cast<DrawTarget*>(aTarget); 1.95 + cairo_t *ctx = static_cast<cairo_t*>(dt->GetNativeSurface(NativeSurfaceType::CAIRO_CONTEXT)); 1.96 + 1.97 + bool isNewContext = !ctx; 1.98 + if (!ctx) { 1.99 + ctx = cairo_create(DrawTargetCairo::GetDummySurface()); 1.100 + cairo_matrix_t mat; 1.101 + GfxMatrixToCairoMatrix(aTarget->GetTransform(), mat); 1.102 + cairo_set_matrix(ctx, &mat); 1.103 + } 1.104 + 1.105 + cairo_set_scaled_font(ctx, mScaledFont); 1.106 + 1.107 + // Convert our GlyphBuffer into an array of Cairo glyphs. 1.108 + std::vector<cairo_glyph_t> glyphs(aBuffer.mNumGlyphs); 1.109 + for (uint32_t i = 0; i < aBuffer.mNumGlyphs; ++i) { 1.110 + glyphs[i].index = aBuffer.mGlyphs[i].mIndex; 1.111 + glyphs[i].x = aBuffer.mGlyphs[i].mPosition.x; 1.112 + glyphs[i].y = aBuffer.mGlyphs[i].mPosition.y; 1.113 + } 1.114 + 1.115 + cairo_new_path(ctx); 1.116 + 1.117 + cairo_glyph_path(ctx, &glyphs[0], aBuffer.mNumGlyphs); 1.118 + 1.119 + RefPtr<PathCairo> newPath = new PathCairo(ctx); 1.120 + if (isNewContext) { 1.121 + cairo_destroy(ctx); 1.122 + } 1.123 + 1.124 + return newPath; 1.125 + } 1.126 +#endif 1.127 + return nullptr; 1.128 +} 1.129 + 1.130 +void 1.131 +ScaledFontBase::CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, BackendType aBackendType, const Matrix *aTransformHint) 1.132 +{ 1.133 +#ifdef USE_SKIA 1.134 + if (aBackendType == BackendType::SKIA) { 1.135 + PathBuilderSkia *builder = static_cast<PathBuilderSkia*>(aBuilder); 1.136 + builder->AppendPath(GetSkiaPathForGlyphs(aBuffer)); 1.137 + return; 1.138 + } 1.139 +#endif 1.140 +#ifdef USE_CAIRO 1.141 + if (aBackendType == BackendType::CAIRO) { 1.142 + MOZ_ASSERT(mScaledFont); 1.143 + 1.144 + PathBuilderCairo* builder = static_cast<PathBuilderCairo*>(aBuilder); 1.145 + cairo_t *ctx = cairo_create(DrawTargetCairo::GetDummySurface()); 1.146 + 1.147 + if (aTransformHint) { 1.148 + cairo_matrix_t mat; 1.149 + GfxMatrixToCairoMatrix(*aTransformHint, mat); 1.150 + cairo_set_matrix(ctx, &mat); 1.151 + } 1.152 + 1.153 + // Convert our GlyphBuffer into an array of Cairo glyphs. 1.154 + std::vector<cairo_glyph_t> glyphs(aBuffer.mNumGlyphs); 1.155 + for (uint32_t i = 0; i < aBuffer.mNumGlyphs; ++i) { 1.156 + glyphs[i].index = aBuffer.mGlyphs[i].mIndex; 1.157 + glyphs[i].x = aBuffer.mGlyphs[i].mPosition.x; 1.158 + glyphs[i].y = aBuffer.mGlyphs[i].mPosition.y; 1.159 + } 1.160 + 1.161 + cairo_set_scaled_font(ctx, mScaledFont); 1.162 + cairo_glyph_path(ctx, &glyphs[0], aBuffer.mNumGlyphs); 1.163 + 1.164 + RefPtr<PathCairo> cairoPath = new PathCairo(ctx); 1.165 + cairo_destroy(ctx); 1.166 + 1.167 + cairoPath->AppendPathToBuilder(builder); 1.168 + return; 1.169 + } 1.170 +#endif 1.171 + 1.172 + MOZ_CRASH("The specified backend type is not supported by CopyGlyphsToBuilder"); 1.173 +} 1.174 + 1.175 +#ifdef USE_CAIRO_SCALED_FONT 1.176 +void 1.177 +ScaledFontBase::SetCairoScaledFont(cairo_scaled_font_t* font) 1.178 +{ 1.179 + MOZ_ASSERT(!mScaledFont); 1.180 + 1.181 + if (font == mScaledFont) 1.182 + return; 1.183 + 1.184 + if (mScaledFont) 1.185 + cairo_scaled_font_destroy(mScaledFont); 1.186 + 1.187 + mScaledFont = font; 1.188 + cairo_scaled_font_reference(mScaledFont); 1.189 +} 1.190 +#endif 1.191 + 1.192 +} 1.193 +}