michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "ScaledFontBase.h" michael@0: michael@0: #ifdef USE_SKIA michael@0: #include "PathSkia.h" michael@0: #include "skia/SkEmptyShader.h" michael@0: #include "skia/SkPaint.h" michael@0: #endif michael@0: michael@0: #ifdef USE_CAIRO michael@0: #include "PathCairo.h" michael@0: #include "DrawTargetCairo.h" michael@0: #include "HelpersCairo.h" michael@0: #endif michael@0: michael@0: #include michael@0: #include michael@0: michael@0: using namespace std; michael@0: michael@0: namespace mozilla { michael@0: namespace gfx { michael@0: michael@0: ScaledFontBase::~ScaledFontBase() michael@0: { michael@0: #ifdef USE_SKIA michael@0: SkSafeUnref(mTypeface); michael@0: #endif michael@0: #ifdef USE_CAIRO_SCALED_FONT michael@0: cairo_scaled_font_destroy(mScaledFont); michael@0: #endif michael@0: } michael@0: michael@0: ScaledFontBase::ScaledFontBase(Float aSize) michael@0: : mSize(aSize) michael@0: { michael@0: #ifdef USE_SKIA michael@0: mTypeface = nullptr; michael@0: #endif michael@0: #ifdef USE_CAIRO_SCALED_FONT michael@0: mScaledFont = nullptr; michael@0: #endif michael@0: } michael@0: michael@0: #ifdef USE_SKIA michael@0: SkPath michael@0: ScaledFontBase::GetSkiaPathForGlyphs(const GlyphBuffer &aBuffer) michael@0: { michael@0: SkTypeface *typeFace = GetSkTypeface(); michael@0: MOZ_ASSERT(typeFace); michael@0: michael@0: SkPaint paint; michael@0: paint.setTypeface(typeFace); michael@0: paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); michael@0: paint.setTextSize(SkFloatToScalar(mSize)); michael@0: michael@0: std::vector indices; michael@0: std::vector offsets; michael@0: indices.resize(aBuffer.mNumGlyphs); michael@0: offsets.resize(aBuffer.mNumGlyphs); michael@0: michael@0: for (unsigned int i = 0; i < aBuffer.mNumGlyphs; i++) { michael@0: indices[i] = aBuffer.mGlyphs[i].mIndex; michael@0: offsets[i].fX = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.x); michael@0: offsets[i].fY = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.y); michael@0: } michael@0: michael@0: SkPath path; michael@0: paint.getPosTextPath(&indices.front(), aBuffer.mNumGlyphs*2, &offsets.front(), &path); michael@0: return path; michael@0: } michael@0: #endif michael@0: michael@0: TemporaryRef michael@0: ScaledFontBase::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget) michael@0: { michael@0: #ifdef USE_SKIA michael@0: if (aTarget->GetType() == BackendType::SKIA) { michael@0: SkPath path = GetSkiaPathForGlyphs(aBuffer); michael@0: return new PathSkia(path, FillRule::FILL_WINDING); michael@0: } michael@0: #endif michael@0: #ifdef USE_CAIRO michael@0: if (aTarget->GetType() == BackendType::CAIRO) { michael@0: MOZ_ASSERT(mScaledFont); michael@0: michael@0: DrawTarget *dt = const_cast(aTarget); michael@0: cairo_t *ctx = static_cast(dt->GetNativeSurface(NativeSurfaceType::CAIRO_CONTEXT)); michael@0: michael@0: bool isNewContext = !ctx; michael@0: if (!ctx) { michael@0: ctx = cairo_create(DrawTargetCairo::GetDummySurface()); michael@0: cairo_matrix_t mat; michael@0: GfxMatrixToCairoMatrix(aTarget->GetTransform(), mat); michael@0: cairo_set_matrix(ctx, &mat); michael@0: } michael@0: michael@0: cairo_set_scaled_font(ctx, mScaledFont); michael@0: michael@0: // Convert our GlyphBuffer into an array of Cairo glyphs. michael@0: std::vector glyphs(aBuffer.mNumGlyphs); michael@0: for (uint32_t i = 0; i < aBuffer.mNumGlyphs; ++i) { michael@0: glyphs[i].index = aBuffer.mGlyphs[i].mIndex; michael@0: glyphs[i].x = aBuffer.mGlyphs[i].mPosition.x; michael@0: glyphs[i].y = aBuffer.mGlyphs[i].mPosition.y; michael@0: } michael@0: michael@0: cairo_new_path(ctx); michael@0: michael@0: cairo_glyph_path(ctx, &glyphs[0], aBuffer.mNumGlyphs); michael@0: michael@0: RefPtr newPath = new PathCairo(ctx); michael@0: if (isNewContext) { michael@0: cairo_destroy(ctx); michael@0: } michael@0: michael@0: return newPath; michael@0: } michael@0: #endif michael@0: return nullptr; michael@0: } michael@0: michael@0: void michael@0: ScaledFontBase::CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, BackendType aBackendType, const Matrix *aTransformHint) michael@0: { michael@0: #ifdef USE_SKIA michael@0: if (aBackendType == BackendType::SKIA) { michael@0: PathBuilderSkia *builder = static_cast(aBuilder); michael@0: builder->AppendPath(GetSkiaPathForGlyphs(aBuffer)); michael@0: return; michael@0: } michael@0: #endif michael@0: #ifdef USE_CAIRO michael@0: if (aBackendType == BackendType::CAIRO) { michael@0: MOZ_ASSERT(mScaledFont); michael@0: michael@0: PathBuilderCairo* builder = static_cast(aBuilder); michael@0: cairo_t *ctx = cairo_create(DrawTargetCairo::GetDummySurface()); michael@0: michael@0: if (aTransformHint) { michael@0: cairo_matrix_t mat; michael@0: GfxMatrixToCairoMatrix(*aTransformHint, mat); michael@0: cairo_set_matrix(ctx, &mat); michael@0: } michael@0: michael@0: // Convert our GlyphBuffer into an array of Cairo glyphs. michael@0: std::vector glyphs(aBuffer.mNumGlyphs); michael@0: for (uint32_t i = 0; i < aBuffer.mNumGlyphs; ++i) { michael@0: glyphs[i].index = aBuffer.mGlyphs[i].mIndex; michael@0: glyphs[i].x = aBuffer.mGlyphs[i].mPosition.x; michael@0: glyphs[i].y = aBuffer.mGlyphs[i].mPosition.y; michael@0: } michael@0: michael@0: cairo_set_scaled_font(ctx, mScaledFont); michael@0: cairo_glyph_path(ctx, &glyphs[0], aBuffer.mNumGlyphs); michael@0: michael@0: RefPtr cairoPath = new PathCairo(ctx); michael@0: cairo_destroy(ctx); michael@0: michael@0: cairoPath->AppendPathToBuilder(builder); michael@0: return; michael@0: } michael@0: #endif michael@0: michael@0: MOZ_CRASH("The specified backend type is not supported by CopyGlyphsToBuilder"); michael@0: } michael@0: michael@0: #ifdef USE_CAIRO_SCALED_FONT michael@0: void michael@0: ScaledFontBase::SetCairoScaledFont(cairo_scaled_font_t* font) michael@0: { michael@0: MOZ_ASSERT(!mScaledFont); michael@0: michael@0: if (font == mScaledFont) michael@0: return; michael@0: michael@0: if (mScaledFont) michael@0: cairo_scaled_font_destroy(mScaledFont); michael@0: michael@0: mScaledFont = font; michael@0: cairo_scaled_font_reference(mScaledFont); michael@0: } michael@0: #endif michael@0: michael@0: } michael@0: }