1 /* 2 * Copyright (C) 2007 Kevin Ollivier <kevino (at) theolliviers.com> 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 // this needs to be included before fontprops.h for UChar* to be defined. 28 #include <wtf/unicode/Unicode.h> 29 30 #include "fontprops.h" 31 #include "math.h" 32 #include "MathExtras.h" 33 34 #include <wx/defs.h> 35 #include <wx/gdicmn.h> 36 #include <wx/wx.h> 37 #include "wx/msw/private.h" 38 39 #include <mlang.h> 40 #include <usp10.h> 41 42 inline long my_round(double x) 43 { 44 return (long)(x < 0 ? x - 0.5 : x + 0.5); 45 } 46 47 wxFontProperties::wxFontProperties(wxFont* font): 48 m_ascent(0), m_descent(0), m_lineGap(0), m_lineSpacing(0), m_xHeight(0) 49 { 50 HDC dc = GetDC(0); 51 WXHFONT hFont = font->GetHFONT(); 52 ::SelectObject(dc, hFont); 53 if (font){ 54 55 int height = font->GetPointSize(); 56 57 TEXTMETRIC tm; 58 GetTextMetrics(dc, &tm); 59 m_ascent = lroundf(tm.tmAscent); 60 m_descent = lroundf(tm.tmDescent); 61 m_xHeight = m_ascent * 0.56f; // Best guess for xHeight for non-Truetype fonts. 62 m_lineGap = lroundf(tm.tmExternalLeading); 63 m_lineSpacing = m_lineGap + m_ascent + m_descent; 64 } 65 RestoreDC(dc, -1); 66 ReleaseDC(0, dc); 67 } 68 69 bool wxFontContainsCharacters(void* font, const UChar* characters, int length) 70 { 71 // FIXME: Microsoft documentation seems to imply that characters can be output using a given font and DC 72 // merely by testing code page intersection. This seems suspect though. Can't a font only partially 73 // cover a given code page? 74 static IMultiLanguage *multiLanguage; 75 if (!multiLanguage) { 76 if (CoCreateInstance(CLSID_CMultiLanguage, 0, CLSCTX_ALL, IID_IMultiLanguage, (void**)&multiLanguage) != S_OK) 77 return true; 78 } 79 80 static IMLangFontLink2* langFontLink; 81 if (!langFontLink) { 82 if (multiLanguage->QueryInterface(&langFontLink) != S_OK) 83 return true; 84 } 85 86 HDC dc = GetDC(0); 87 88 DWORD acpCodePages; 89 langFontLink->CodePageToCodePages(CP_ACP, &acpCodePages); 90 91 DWORD fontCodePages; 92 langFontLink->GetFontCodePages(dc, (HFONT)font, &fontCodePages); 93 94 DWORD actualCodePages; 95 long numCharactersProcessed; 96 long offset = 0; 97 while (offset < length) { 98 langFontLink->GetStrCodePages(characters, length, acpCodePages, &actualCodePages, &numCharactersProcessed); 99 if ((actualCodePages & fontCodePages)) 100 return false; 101 offset += numCharactersProcessed; 102 } 103 104 ReleaseDC(0, dc); 105 106 return true; 107 } 108 109 void GetTextExtent( const wxFont& font, const wxString& str, wxCoord *width, wxCoord *height, 110 wxCoord *descent, wxCoord *externalLeading ) 111 { 112 HDC dc = GetDC(0); 113 WXHFONT hFont = font.GetHFONT(); 114 ::SelectObject(dc, hFont); 115 116 HFONT hfontOld; 117 if ( font != wxNullFont ) 118 { 119 wxASSERT_MSG( font.Ok(), _T("invalid font in wxDC::GetTextExtent") ); 120 121 hfontOld = (HFONT)::SelectObject(dc, hFont); 122 } 123 else // don't change the font 124 { 125 hfontOld = 0; 126 } 127 128 SIZE sizeRect; 129 const size_t len = str.length(); 130 if ( !::GetTextExtentPoint32(dc, str, len, &sizeRect) ) 131 { 132 wxLogLastError(_T("GetTextExtentPoint32()")); 133 } 134 135 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) 136 // the result computed by GetTextExtentPoint32() may be too small as it 137 // accounts for under/overhang of the first/last character while we want 138 // just the bounding rect for this string so adjust the width as needed 139 // (using API not available in 2002 SDKs of WinCE) 140 if ( len > 1 ) 141 { 142 ABC width; 143 const wxChar chFirst = *str.begin(); 144 if ( ::GetCharABCWidths(dc, chFirst, chFirst, &width) ) 145 { 146 if ( width.abcA < 0 ) 147 sizeRect.cx -= width.abcA; 148 149 if ( len > 1 ) 150 { 151 const wxChar chLast = *str.rbegin(); 152 ::GetCharABCWidths(dc, chLast, chLast, &width); 153 } 154 //else: we already have the width of the last character 155 156 if ( width.abcC < 0 ) 157 sizeRect.cx -= width.abcC; 158 } 159 //else: GetCharABCWidths() failed, not a TrueType font? 160 } 161 #endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) 162 163 TEXTMETRIC tm; 164 ::GetTextMetrics(dc, &tm); 165 166 if (width) 167 *width = sizeRect.cx; 168 if (height) 169 *height = sizeRect.cy; 170 if (descent) 171 *descent = tm.tmDescent; 172 if (externalLeading) 173 *externalLeading = tm.tmExternalLeading; 174 175 if ( hfontOld ) 176 { 177 ::SelectObject(dc, hfontOld); 178 } 179 180 ReleaseDC(0, dc); 181 } 182