1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "ScaledFontWin.h"
8 #include "UnscaledFontGDI.h"
9 
10 #include "AutoHelpersWin.h"
11 #include "Logging.h"
12 #include "nsString.h"
13 
14 #ifdef USE_SKIA
15 #  include "skia/include/ports/SkTypeface_win.h"
16 #endif
17 
18 #ifdef USE_CAIRO_SCALED_FONT
19 #  include "cairo-win32.h"
20 #endif
21 
22 #include "HelpersWinFonts.h"
23 
24 namespace mozilla {
25 namespace gfx {
26 
ScaledFontWin(const LOGFONT * aFont,const RefPtr<UnscaledFont> & aUnscaledFont,Float aSize)27 ScaledFontWin::ScaledFontWin(const LOGFONT* aFont,
28                              const RefPtr<UnscaledFont>& aUnscaledFont,
29                              Float aSize)
30     : ScaledFontBase(aUnscaledFont, aSize), mLogFont(*aFont) {}
31 
GetFontFileData(FontFileDataOutput aDataCallback,void * aBaton)32 bool UnscaledFontGDI::GetFontFileData(FontFileDataOutput aDataCallback,
33                                       void* aBaton) {
34   AutoDC dc;
35   AutoSelectFont font(dc.GetDC(), &mLogFont);
36 
37   // Check for a font collection first.
38   uint32_t table = 0x66637474;  // 'ttcf'
39   uint32_t tableSize = ::GetFontData(dc.GetDC(), table, 0, nullptr, 0);
40   if (tableSize == GDI_ERROR) {
41     // Try as if just a single font.
42     table = 0;
43     tableSize = ::GetFontData(dc.GetDC(), table, 0, nullptr, 0);
44     if (tableSize == GDI_ERROR) {
45       return false;
46     }
47   }
48 
49   UniquePtr<uint8_t[]> fontData(new uint8_t[tableSize]);
50 
51   uint32_t sizeGot =
52       ::GetFontData(dc.GetDC(), table, 0, fontData.get(), tableSize);
53   if (sizeGot != tableSize) {
54     return false;
55   }
56 
57   aDataCallback(fontData.get(), tableSize, 0, aBaton);
58   return true;
59 }
60 
GetFontInstanceData(FontInstanceDataOutput aCb,void * aBaton)61 bool ScaledFontWin::GetFontInstanceData(FontInstanceDataOutput aCb,
62                                         void* aBaton) {
63   aCb(reinterpret_cast<uint8_t*>(&mLogFont), sizeof(mLogFont), nullptr, 0,
64       aBaton);
65   return true;
66 }
67 
GetFontInstanceData(FontInstanceDataOutput aCb,void * aBaton)68 bool UnscaledFontGDI::GetFontInstanceData(FontInstanceDataOutput aCb,
69                                           void* aBaton) {
70   aCb(reinterpret_cast<uint8_t*>(&mLogFont), sizeof(mLogFont), aBaton);
71   return true;
72 }
73 
GetFontDescriptor(FontDescriptorOutput aCb,void * aBaton)74 bool UnscaledFontGDI::GetFontDescriptor(FontDescriptorOutput aCb,
75                                         void* aBaton) {
76   // Because all the callers of this function are preparing a recorded
77   // event to be played back in another process, it's not helpful to ever
78   // return a font descriptor, since it isn't meaningful in another
79   // process. Those callers will always need to send full font data, and
80   // returning false here will ensure that that happens.
81   return false;
82 }
83 
CreateFromFontDescriptor(const uint8_t * aData,uint32_t aDataLength,uint32_t aIndex)84 already_AddRefed<UnscaledFont> UnscaledFontGDI::CreateFromFontDescriptor(
85     const uint8_t* aData, uint32_t aDataLength, uint32_t aIndex) {
86   if (aDataLength < sizeof(LOGFONT)) {
87     gfxWarning() << "GDI font descriptor is truncated.";
88     return nullptr;
89   }
90 
91   const LOGFONT* logFont = reinterpret_cast<const LOGFONT*>(aData);
92   RefPtr<UnscaledFont> unscaledFont = new UnscaledFontGDI(*logFont);
93   return unscaledFont.forget();
94 }
95 
CreateScaledFont(Float aGlyphSize,const uint8_t * aInstanceData,uint32_t aInstanceDataLength,const FontVariation * aVariations,uint32_t aNumVariations)96 already_AddRefed<ScaledFont> UnscaledFontGDI::CreateScaledFont(
97     Float aGlyphSize, const uint8_t* aInstanceData,
98     uint32_t aInstanceDataLength, const FontVariation* aVariations,
99     uint32_t aNumVariations) {
100   if (aInstanceDataLength < sizeof(LOGFONT)) {
101     gfxWarning() << "GDI unscaled font instance data is truncated.";
102     return nullptr;
103   }
104   return MakeAndAddRef<ScaledFontWin>(
105       reinterpret_cast<const LOGFONT*>(aInstanceData), this, aGlyphSize);
106 }
107 
GetDefaultAAMode()108 AntialiasMode ScaledFontWin::GetDefaultAAMode() {
109   return GetSystemDefaultAAMode();
110 }
111 
112 #ifdef USE_SKIA
CreateSkTypeface()113 SkTypeface* ScaledFontWin::CreateSkTypeface() {
114   return SkCreateTypefaceFromLOGFONT(mLogFont);
115 }
116 #endif
117 
118 #ifdef USE_CAIRO_SCALED_FONT
CreateCairoFontFace(cairo_font_options_t * aFontOptions)119 cairo_font_face_t* ScaledFontWin::CreateCairoFontFace(
120     cairo_font_options_t* aFontOptions) {
121   if (mLogFont.lfFaceName[0] == 0) {
122     return nullptr;
123   }
124   return cairo_win32_font_face_create_for_logfontw(&mLogFont);
125 }
126 #endif
127 
128 }  // namespace gfx
129 }  // namespace mozilla
130