1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ 2 /* Cairo - a vector graphics library with display and print output 3 * 4 * Copyright � 2010 Mozilla Foundation 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it either under the terms of the GNU Lesser General Public 8 * License version 2.1 as published by the Free Software Foundation 9 * (the "LGPL") or, at your option, under the terms of the Mozilla 10 * Public License Version 1.1 (the "MPL"). If you do not alter this 11 * notice, a recipient may use your version of this file under either 12 * the MPL or the LGPL. 13 * 14 * You should have received a copy of the LGPL along with this library 15 * in the file COPYING-LGPL-2.1; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * You should have received a copy of the MPL along with this library 18 * in the file COPYING-MPL-1.1 19 * 20 * The contents of this file are subject to the Mozilla Public License 21 * Version 1.1 (the "License"); you may not use this file except in 22 * compliance with the License. You may obtain a copy of the License at 23 * http://www.mozilla.org/MPL/ 24 * 25 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY 26 * OF ANY KIND, either express or implied. See the LGPL or the MPL for 27 * the specific language governing rights and limitations. 28 * 29 * The Original Code is the cairo graphics library. 30 * 31 * The Initial Developer of the Original Code is the Mozilla Foundation 32 * 33 * Contributor(s): 34 * Bas Schouten <bschouten@mozilla.com> 35 */ 36 #include <dwrite_1.h> 37 #include <d2d1.h> 38 39 // DirectWrite is not available on all platforms. 40 typedef HRESULT (WINAPI*DWriteCreateFactoryFunc)( 41 DWRITE_FACTORY_TYPE factoryType, 42 REFIID iid, 43 IUnknown **factory 44 ); 45 46 /* cairo_scaled_font_t implementation */ 47 struct _cairo_dwrite_scaled_font { 48 cairo_scaled_font_t base; 49 cairo_matrix_t mat; 50 cairo_matrix_t mat_inverse; 51 cairo_antialias_t antialias_mode; 52 DWRITE_MEASURING_MODE measuring_mode; 53 cairo_bool_t manual_show_glyphs_allowed; 54 enum TextRenderingState { 55 TEXT_RENDERING_UNINITIALIZED, 56 TEXT_RENDERING_NO_CLEARTYPE, 57 TEXT_RENDERING_NORMAL, 58 TEXT_RENDERING_GDI_CLASSIC 59 }; 60 TextRenderingState rendering_mode; 61 }; 62 typedef struct _cairo_dwrite_scaled_font cairo_dwrite_scaled_font_t; 63 64 class DWriteFactory 65 { 66 public: Instance()67 static IDWriteFactory *Instance() 68 { 69 if (!mFactoryInstance) { 70 DWriteCreateFactoryFunc createDWriteFactory = (DWriteCreateFactoryFunc) 71 GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory"); 72 if (createDWriteFactory) { 73 HRESULT hr = createDWriteFactory( 74 DWRITE_FACTORY_TYPE_SHARED, 75 __uuidof(IDWriteFactory), 76 reinterpret_cast<IUnknown**>(&mFactoryInstance)); 77 assert(SUCCEEDED(hr)); 78 } 79 } 80 return mFactoryInstance; 81 } 82 SystemCollection()83 static IDWriteFontCollection *SystemCollection() 84 { 85 if (!mSystemCollection) { 86 if (Instance()) { 87 HRESULT hr = Instance()->GetSystemFontCollection(&mSystemCollection); 88 assert(SUCCEEDED(hr)); 89 } 90 } 91 return mSystemCollection; 92 } 93 FindSystemFontFamily(const WCHAR * aFamilyName)94 static IDWriteFontFamily *FindSystemFontFamily(const WCHAR *aFamilyName) 95 { 96 UINT32 idx; 97 BOOL found; 98 if (!SystemCollection()) { 99 return NULL; 100 } 101 SystemCollection()->FindFamilyName(aFamilyName, &idx, &found); 102 if (!found) { 103 return NULL; 104 } 105 106 IDWriteFontFamily *family; 107 SystemCollection()->GetFontFamily(idx, &family); 108 return family; 109 } 110 RenderingParams(cairo_dwrite_scaled_font_t::TextRenderingState mode)111 static IDWriteRenderingParams *RenderingParams(cairo_dwrite_scaled_font_t::TextRenderingState mode) 112 { 113 if (!mDefaultRenderingParams || 114 !mForceGDIClassicRenderingParams || 115 !mCustomClearTypeRenderingParams) 116 { 117 CreateRenderingParams(); 118 } 119 IDWriteRenderingParams *params; 120 if (mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_NO_CLEARTYPE) { 121 params = mDefaultRenderingParams; 122 } else if (mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC && mRenderingMode < 0) { 123 params = mForceGDIClassicRenderingParams; 124 } else { 125 params = mCustomClearTypeRenderingParams; 126 } 127 if (params) { 128 params->AddRef(); 129 } 130 return params; 131 } 132 SetRenderingParams(FLOAT aGamma,FLOAT aEnhancedContrast,FLOAT aClearTypeLevel,int aPixelGeometry,int aRenderingMode)133 static void SetRenderingParams(FLOAT aGamma, 134 FLOAT aEnhancedContrast, 135 FLOAT aClearTypeLevel, 136 int aPixelGeometry, 137 int aRenderingMode) 138 { 139 mGamma = aGamma; 140 mEnhancedContrast = aEnhancedContrast; 141 mClearTypeLevel = aClearTypeLevel; 142 mPixelGeometry = aPixelGeometry; 143 mRenderingMode = aRenderingMode; 144 // discard any current RenderingParams objects 145 if (mCustomClearTypeRenderingParams) { 146 mCustomClearTypeRenderingParams->Release(); 147 mCustomClearTypeRenderingParams = NULL; 148 } 149 if (mForceGDIClassicRenderingParams) { 150 mForceGDIClassicRenderingParams->Release(); 151 mForceGDIClassicRenderingParams = NULL; 152 } 153 if (mDefaultRenderingParams) { 154 mDefaultRenderingParams->Release(); 155 mDefaultRenderingParams = NULL; 156 } 157 } 158 GetClearTypeRenderingMode()159 static int GetClearTypeRenderingMode() { 160 return mRenderingMode; 161 } 162 163 private: 164 static void CreateRenderingParams(); 165 166 static IDWriteFactory *mFactoryInstance; 167 static IDWriteFontCollection *mSystemCollection; 168 static IDWriteRenderingParams *mDefaultRenderingParams; 169 static IDWriteRenderingParams *mCustomClearTypeRenderingParams; 170 static IDWriteRenderingParams *mForceGDIClassicRenderingParams; 171 static FLOAT mGamma; 172 static FLOAT mEnhancedContrast; 173 static FLOAT mClearTypeLevel; 174 static int mPixelGeometry; 175 static int mRenderingMode; 176 }; 177 178 class AutoDWriteGlyphRun : public DWRITE_GLYPH_RUN 179 { 180 static const int kNumAutoGlyphs = 256; 181 182 public: AutoDWriteGlyphRun()183 AutoDWriteGlyphRun() { 184 glyphCount = 0; 185 } 186 ~AutoDWriteGlyphRun()187 ~AutoDWriteGlyphRun() { 188 if (glyphCount > kNumAutoGlyphs) { 189 delete[] glyphIndices; 190 delete[] glyphAdvances; 191 delete[] glyphOffsets; 192 } 193 } 194 allocate(int aNumGlyphs)195 void allocate(int aNumGlyphs) { 196 glyphCount = aNumGlyphs; 197 if (aNumGlyphs <= kNumAutoGlyphs) { 198 glyphIndices = &mAutoIndices[0]; 199 glyphAdvances = &mAutoAdvances[0]; 200 glyphOffsets = &mAutoOffsets[0]; 201 } else { 202 glyphIndices = new UINT16[aNumGlyphs]; 203 glyphAdvances = new FLOAT[aNumGlyphs]; 204 glyphOffsets = new DWRITE_GLYPH_OFFSET[aNumGlyphs]; 205 } 206 } 207 208 private: 209 DWRITE_GLYPH_OFFSET mAutoOffsets[kNumAutoGlyphs]; 210 FLOAT mAutoAdvances[kNumAutoGlyphs]; 211 UINT16 mAutoIndices[kNumAutoGlyphs]; 212 }; 213 214 /* cairo_font_face_t implementation */ 215 struct _cairo_dwrite_font_face { 216 cairo_font_face_t base; 217 IDWriteFont *font; 218 IDWriteFontFace *dwriteface; 219 }; 220 typedef struct _cairo_dwrite_font_face cairo_dwrite_font_face_t; 221 222 DWRITE_MATRIX _cairo_dwrite_matrix_from_matrix(const cairo_matrix_t *matrix); 223 224 // This will initialize a DWrite glyph run from cairo glyphs and a scaled_font. 225 void 226 _cairo_dwrite_glyph_run_from_glyphs(cairo_glyph_t *glyphs, 227 int num_glyphs, 228 cairo_dwrite_scaled_font_t *scaled_font, 229 AutoDWriteGlyphRun *run, 230 cairo_bool_t *transformed); 231