Bug 715513 - Implement text in the new 2D API's Cairo backend. r=jrmuizel
authorJoe Drew <joe@drew.ca>
Tue, 10 Jan 2012 13:26:59 -0500
changeset 85463 603df6854a5296c095df575bafd5f4353770d1ee
parent 85462 7349c6b4ac7f856f12b606894872c526e8ffae28
child 85464 b6f547939cfbb675b01ace20fc6482e3a8e348f9
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs715513
milestone12.0a1
Bug 715513 - Implement text in the new 2D API's Cairo backend. r=jrmuizel
gfx/2d/DrawTargetCairo.cpp
gfx/2d/Factory.cpp
gfx/2d/Makefile.in
gfx/2d/ScaledFontCairo.cpp
gfx/2d/ScaledFontCairo.h
gfx/2d/Types.h
gfx/thebes/gfxFont.h
gfx/thebes/gfxPlatform.cpp
--- a/gfx/2d/DrawTargetCairo.cpp
+++ b/gfx/2d/DrawTargetCairo.cpp
@@ -34,16 +34,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "DrawTargetCairo.h"
 
 #include "SourceSurfaceCairo.h"
 #include "PathCairo.h"
 #include "HelpersCairo.h"
+#include "ScaledFontCairo.h"
 
 #include "cairo.h"
 
 #include "Blur.h"
 
 #ifdef CAIRO_HAS_QUARTZ_SURFACE
 #include "cairo-quartz.h"
 #include <ApplicationServices/ApplicationServices.h>
@@ -584,16 +585,36 @@ DrawTargetCairo::Fill(const Path *aPath,
 
 void
 DrawTargetCairo::FillGlyphs(ScaledFont *aFont,
                             const GlyphBuffer &aBuffer,
                             const Pattern &aPattern,
                             const DrawOptions &aOptions)
 {
   AutoPrepareForDrawing prep(this, mContext);
+
+  if (aFont->GetType() != FONT_CAIRO)
+    return;
+
+  ScaledFontCairo* scaledFont = static_cast<ScaledFontCairo*>(aFont);
+  cairo_set_scaled_font(mContext, scaledFont->GetCairoScaledFont());
+
+  cairo_pattern_t* pat = GfxPatternToCairoPattern(aPattern, aOptions.mAlpha);
+  cairo_set_source(mContext, pat);
+  cairo_pattern_destroy(pat);
+
+  // Convert our GlyphBuffer into an array of Cairo glyphs.
+  std::vector<cairo_glyph_t> glyphs(aBuffer.mNumGlyphs);
+  for (uint32_t i = 0; i < aBuffer.mNumGlyphs; ++i) {
+    glyphs[i].index = aBuffer.mGlyphs[i].mIndex;
+    glyphs[i].x = aBuffer.mGlyphs[i].mPosition.x;
+    glyphs[i].y = aBuffer.mGlyphs[i].mPosition.y;
+  }
+
+  cairo_show_glyphs(mContext, &glyphs[0], aBuffer.mNumGlyphs);
 }
 
 void
 DrawTargetCairo::Mask(const Pattern &aSource,
                       const Pattern &aMask,
                       const DrawOptions &aOptions /* = DrawOptions() */)
 {
   AutoPrepareForDrawing prep(this, mContext);
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -34,16 +34,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "2D.h"
 
 #ifdef USE_CAIRO
 #include "DrawTargetCairo.h"
+#include "ScaledFontCairo.h"
 #endif
 
 #ifdef USE_SKIA
 #include "DrawTargetSkia.h"
 #ifdef XP_MACOSX
 #include "ScaledFontMac.h"
 #endif
 #ifdef WIN32
@@ -134,16 +135,20 @@ Factory::CreateScaledFontForNativeFont(c
       return new ScaledFontWin(static_cast<gfxGDIFont*>(aNativeFont.mFont), aSize);
     }
 #endif
   case NATIVE_FONT_SKIA_FONT_FACE:
     {
       return new ScaledFontSkia(static_cast<gfxFont*>(aNativeFont.mFont), aSize);
     }
 #endif
+  case NATIVE_FONT_CAIRO_FONT_FACE:
+    {
+      return new ScaledFontCairo(static_cast<gfxFont*>(aNativeFont.mFont));
+    }
   default:
     gfxWarning() << "Invalid native font type specified.";
     return NULL;
   }
 }
 
 #ifdef WIN32
 TemporaryRef<DrawTarget>
--- a/gfx/2d/Makefile.in
+++ b/gfx/2d/Makefile.in
@@ -63,16 +63,17 @@ EXPORTS_mozilla/gfx	= \
         Rect.h \
         Types.h \
 	$(NULL)
 
 CPPSRCS	= \
 	Factory.cpp \
         Matrix.cpp \
         DrawTargetCairo.cpp \
+        ScaledFontCairo.cpp \
         SourceSurfaceCairo.cpp \
         PathCairo.cpp \
         Blur.cpp \
         $(NULL)
 
 
 DEFINES += -DMOZ_GFX -DUSE_CAIRO
 
new file mode 100644
--- /dev/null
+++ b/gfx/2d/ScaledFontCairo.cpp
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "ScaledFontCairo.h"
+
+#include "cairo.h"
+
+#include "PathCairo.h"
+#include "gfxFont.h"
+
+#include <vector>
+
+using namespace std;
+
+namespace mozilla {
+namespace gfx {
+
+ScaledFontCairo::ScaledFontCairo(gfxFont* aFont)
+{
+  mScaledFont = aFont->GetCairoScaledFont();
+  cairo_scaled_font_reference(mScaledFont);
+}
+
+ScaledFontCairo::~ScaledFontCairo()
+{
+  cairo_scaled_font_destroy(mScaledFont);
+}
+
+TemporaryRef<Path>
+ScaledFontCairo::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget)
+{
+  if (aTarget->GetType() != BACKEND_CAIRO) {
+    return NULL;
+  }
+
+  RefPtr<PathBuilder> builder_iface = aTarget->CreatePathBuilder();
+  PathBuilderCairo* builder = static_cast<PathBuilderCairo*>(builder_iface.get());
+
+  // Manually build the path for the PathBuilder.
+  RefPtr<CairoPathContext> context = builder->GetPathContext();
+
+  cairo_set_scaled_font(*context, mScaledFont);
+
+  // Convert our GlyphBuffer into an array of Cairo glyphs.
+  std::vector<cairo_glyph_t> glyphs(aBuffer.mNumGlyphs);
+  for (uint32_t i = 0; i < aBuffer.mNumGlyphs; ++i) {
+    glyphs[i].index = aBuffer.mGlyphs[i].mIndex;
+    glyphs[i].x = aBuffer.mGlyphs[i].mPosition.x;
+    glyphs[i].y = aBuffer.mGlyphs[i].mPosition.y;
+  }
+
+  cairo_glyph_path(*context, &glyphs[0], aBuffer.mNumGlyphs);
+
+  return builder->Finish();
+}
+
+cairo_scaled_font_t*
+ScaledFontCairo::GetCairoScaledFont()
+{
+  return mScaledFont;
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/gfx/2d/ScaledFontCairo.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef MOZILLA_GFX_SCALEDFONTCAIRO_H_
+#define MOZILLA_GFX_SCALEDFONTCAIRO_H_
+
+#include "2D.h"
+
+class gfxFont;
+typedef struct _cairo_scaled_font cairo_scaled_font_t;
+
+namespace mozilla {
+namespace gfx {
+
+class ScaledFontCairo : public ScaledFont
+{
+public:
+  ScaledFontCairo(gfxFont* aFont);
+  virtual ~ScaledFontCairo();
+
+  virtual FontType GetType() const { return FONT_CAIRO; }
+
+  virtual TemporaryRef<Path> GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget);
+
+  cairo_scaled_font_t* GetCairoScaledFont();
+
+private:
+  cairo_scaled_font_t* mScaledFont;
+};
+
+}
+}
+
+#endif /* MOZILLA_GFX_SCALEDFONTCAIRO_H_ */
--- a/gfx/2d/Types.h
+++ b/gfx/2d/Types.h
@@ -74,31 +74,33 @@ enum BackendType
   BACKEND_SKIA
 };
 
 enum FontType
 {
   FONT_DWRITE,
   FONT_GDI,
   FONT_MAC,
-  FONT_SKIA
+  FONT_SKIA,
+  FONT_CAIRO
 };
 
 enum NativeSurfaceType
 {
   NATIVE_SURFACE_D3D10_TEXTURE,
   NATIVE_SURFACE_CAIRO_SURFACE
 };
 
 enum NativeFontType
 {
   NATIVE_FONT_DWRITE_FONT_FACE,
   NATIVE_FONT_GDI_FONT_FACE,
   NATIVE_FONT_MAC_FONT_FACE,
-  NATIVE_FONT_SKIA_FONT_FACE
+  NATIVE_FONT_SKIA_FONT_FACE,
+  NATIVE_FONT_CAIRO_FONT_FACE
 };
 
 enum CompositionOp { OP_OVER, OP_ADD, OP_ATOP, OP_OUT, OP_IN, OP_SOURCE, OP_DEST_IN, OP_DEST_OUT, OP_DEST_OVER, OP_DEST_ATOP, OP_XOR, OP_COUNT };
 enum ExtendMode { EXTEND_CLAMP, EXTEND_REPEAT, EXTEND_REFLECT };
 enum FillRule { FILL_WINDING, FILL_EVEN_ODD };
 enum AntialiasMode { AA_NONE, AA_GRAY, AA_SUBPIXEL };
 enum Snapping { SNAP_NONE, SNAP_ALIGNED };
 enum Filter { FILTER_LINEAR, FILTER_POINT };
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -1123,16 +1123,18 @@ public:
             // outside the hinted outline.
             // Also NOTE: it is relatively expensive to request this,
             // as it does not use cached glyph extents in the font.
     } BoundingBoxType;
 
     const nsString& GetName() const { return mFontEntry->Name(); }
     const gfxFontStyle *GetStyle() const { return &mStyle; }
 
+    cairo_scaled_font_t* GetCairoScaledFont() { return mScaledFont; }
+
     virtual gfxFont* CopyWithAntialiasOption(AntialiasOption anAAOption) {
         // platforms where this actually matters should override
         return nsnull;
     }
 
     virtual gfxFloat GetAdjustedSize() {
         return mAdjustedSize > 0.0 ? mAdjustedSize : mStyle.size;
     }
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -511,17 +511,23 @@ gfxPlatform::GetSourceSurfaceForSurface(
   aSurface->SetData(&kSourceSurface, srcBuffer, SourceBufferDestroy);
 
   return srcBuffer;
 }
 
 RefPtr<ScaledFont>
 gfxPlatform::GetScaledFontForFont(gfxFont *aFont)
 {
-  return NULL;
+  NativeFont nativeFont;
+  nativeFont.mType = NATIVE_FONT_CAIRO_FONT_FACE;
+  nativeFont.mFont = aFont;
+  RefPtr<ScaledFont> scaledFont =
+    Factory::CreateScaledFontForNativeFont(nativeFont,
+                                           aFont->GetAdjustedSize());
+  return scaledFont;
 }
 
 cairo_user_data_key_t kDrawSourceSurface;
 static void
 DataSourceSurfaceDestroy(void *dataSourceSurface)
 {
       static_cast<DataSourceSurface*>(dataSourceSurface)->Release();
 }