Convert from Unicode to ANSI in GetTextMetricsA()
authorGé van Geldorp <ge@gse.nl>
Fri, 16 May 2003 18:55:27 +0000 (18:55 +0000)
committerGé van Geldorp <ge@gse.nl>
Fri, 16 May 2003 18:55:27 +0000 (18:55 +0000)
svn path=/trunk/; revision=4692

reactos/lib/gdi32/objects/text.c

index 3a9977e..4ad23c9 100644 (file)
@@ -51,6 +51,40 @@ SetTextColor(HDC hDC, COLORREF color)
   return(W32kSetTextColor(hDC, color));
 }
 
+static BOOL
+MetricsCharConvert(WCHAR w, BCHAR *b)
+  {
+  UNICODE_STRING WString;
+  WCHAR WBuf[2];
+  ANSI_STRING AString;
+  CHAR ABuf[2];
+  NTSTATUS Status;
+
+  if (L'\0' == w)
+    {
+      *b = '\0';
+    }
+  else
+    {
+      WBuf[0] = w;
+      WBuf[1] = L'\0';
+      RtlInitUnicodeString(&WString, WBuf);
+      ABuf[0] = '*';
+      ABuf[1] = L'\0';
+      RtlInitAnsiString(&AString, ABuf);
+
+      Status = RtlUnicodeStringToAnsiString(&AString, &WString, FALSE);
+      if (! NT_SUCCESS(Status))
+       {
+         SetLastError(RtlNtStatusToDosError(Status));
+         return FALSE;
+       }
+      *b = ABuf[0];
+    }
+
+  return TRUE;
+  }
+
 BOOL 
 STDCALL 
 GetTextMetricsA(
@@ -58,7 +92,107 @@ GetTextMetricsA(
        LPTEXTMETRICA   tm
        )
 {
-       return W32kGetTextMetrics(hdc, (LPTEXTMETRICW) tm);
+  TEXTMETRICW tmw;
+  UNICODE_STRING WString;
+  WCHAR WBuf[256];
+  ANSI_STRING AString;
+  CHAR ABuf[256];
+  UINT Letter;
+  NTSTATUS Status;
+
+  if (! W32kGetTextMetrics(hdc, &tmw))
+    {
+      return FALSE;
+    }
+
+  tm->tmHeight = tmw.tmHeight;
+  tm->tmAscent = tmw.tmAscent;
+  tm->tmDescent = tmw.tmDescent;
+  tm->tmInternalLeading = tmw.tmInternalLeading;
+  tm->tmExternalLeading = tmw.tmExternalLeading;
+  tm->tmAveCharWidth = tmw.tmAveCharWidth;
+  tm->tmMaxCharWidth = tmw.tmMaxCharWidth;
+  tm->tmWeight = tmw.tmWeight;
+  tm->tmOverhang = tmw.tmOverhang;
+  tm->tmDigitizedAspectX = tmw.tmDigitizedAspectX;
+  tm->tmDigitizedAspectY = tmw.tmDigitizedAspectY;
+
+  /* The Unicode FirstChar/LastChar need not correspond to the ANSI
+     FirstChar/LastChar. For example, if the font contains glyphs for
+     letters A-Z and an accented version of the letter e, the Unicode
+     FirstChar would be A and the Unicode LastChar would be the accented
+     e. If you just translate those to ANSI, the range would become
+     letters A-E instead of A-Z.
+     We translate all possible ANSI chars to Unicode and find the first
+     and last translated character which fall into the Unicode FirstChar/
+     LastChar range and return the corresponding ANSI char. */
+
+  /* Setup an Ansi string containing all possible letters (note: skip '\0' at
+     the beginning since that would be interpreted as end-of-string, handle
+     '\0' special later */
+  for (Letter = 1; Letter < 256; Letter++)
+    {
+    ABuf[Letter - 1] = (CHAR) Letter;
+    WBuf[Letter - 1] = L' ';
+    }
+  ABuf[255] = '\0';
+  WBuf[255] = L'\0';
+  RtlInitAnsiString(&AString, ABuf);
+  RtlInitUnicodeString(&WString, WBuf);
+
+  /* Find the corresponding Unicode characters */
+  Status = RtlAnsiStringToUnicodeString(&WString, &AString, FALSE);
+  if (! NT_SUCCESS(Status))
+    {
+      SetLastError(RtlNtStatusToDosError(Status));
+      return FALSE;
+    }
+
+  /* Scan for the first ANSI character which maps to an Unicode character
+     in the range */
+  tm->tmFirstChar = '\0';
+  if (L'\0' != tmw.tmFirstChar)
+    {
+      for (Letter = 1; Letter < 256; Letter++)
+       {
+         if (tmw.tmFirstChar <= WBuf[Letter - 1] &&
+             WBuf[Letter - 1] <= tmw.tmLastChar)
+           {
+             tm->tmFirstChar = (CHAR) Letter;
+             break;
+           }
+       }
+    }
+
+  /* Scan for the last ANSI character which maps to an Unicode character
+     in the range */
+  tm->tmLastChar = '\0';
+  if (L'\0' != tmw.tmLastChar)
+    {
+      for (Letter = 255; 0 < Letter; Letter--)
+       {
+         if (tmw.tmFirstChar <= WBuf[Letter - 1] &&
+             WBuf[Letter - 1] <= tmw.tmLastChar)
+           {
+             tm->tmLastChar = (CHAR) Letter;
+             break;
+           }
+       }
+    }
+
+  if (! MetricsCharConvert(tmw.tmDefaultChar, &tm->tmDefaultChar) ||
+      ! MetricsCharConvert(tmw.tmBreakChar, &tm->tmBreakChar))
+    {
+      return FALSE;
+    }
+
+  tm->tmItalic = tmw.tmItalic;
+  tm->tmUnderlined = tmw.tmUnderlined;
+  tm->tmStruckOut = tmw.tmStruckOut;
+  tm->tmPitchAndFamily = tmw.tmPitchAndFamily;
+  tm->tmCharSet = tmw.tmCharSet;
+
+  return TRUE;
 }
 
 BOOL