|
Packit |
0ec9dd |
/* Pango
|
|
Packit |
0ec9dd |
* pangowin32.c: Routines for handling Windows fonts
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Copyright (C) 1999 Red Hat Software
|
|
Packit |
0ec9dd |
* Copyright (C) 2000 Tor Lillqvist
|
|
Packit |
0ec9dd |
* Copyright (C) 2001 Alexander Larsson
|
|
Packit |
0ec9dd |
* Copyright (C) 2007 Novell, Inc.
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* This library is free software; you can redistribute it and/or
|
|
Packit |
0ec9dd |
* modify it under the terms of the GNU Library General Public
|
|
Packit |
0ec9dd |
* License as published by the Free Software Foundation; either
|
|
Packit |
0ec9dd |
* version 2 of the License, or (at your option) any later version.
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
0ec9dd |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
0ec9dd |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
0ec9dd |
* Library General Public License for more details.
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* You should have received a copy of the GNU Library General Public
|
|
Packit |
0ec9dd |
* License along with this library; if not, write to the
|
|
Packit |
0ec9dd |
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
Packit |
0ec9dd |
* Boston, MA 02111-1307, USA.
|
|
Packit |
0ec9dd |
*/
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/**
|
|
Packit |
0ec9dd |
* SECTION:win32-fonts
|
|
Packit |
0ec9dd |
* @short_description:Functions for shape engines to manipulate Win32 fonts
|
|
Packit |
0ec9dd |
* @title:Win32 Fonts and Rendering
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* The macros and functions in this section are used to access fonts natively on
|
|
Packit |
0ec9dd |
* Win32 systems and to render text in conjunction with Win32 APIs.
|
|
Packit |
0ec9dd |
*/
|
|
Packit |
0ec9dd |
#include "config.h"
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
#include <string.h>
|
|
Packit |
0ec9dd |
#include <stdlib.h>
|
|
Packit |
0ec9dd |
#include <glib.h>
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
#include "pango-impl-utils.h"
|
|
Packit |
0ec9dd |
#include "pangowin32.h"
|
|
Packit |
0ec9dd |
#include "pangowin32-private.h"
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
#define MAX_FREED_FONTS 256
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
#define CH_IS_UNIHAN_BMP(ch) ((ch) >= 0x3400 && (ch) <= 0x9FFF)
|
|
Packit |
0ec9dd |
#define CH_IS_UNIHAN(ch) (CH_IS_UNIHAN_BMP (ch) || \
|
|
Packit |
0ec9dd |
((ch) >= 0x20000 && (ch) <= 0x2A6DF) || \
|
|
Packit |
0ec9dd |
((ch) >= 0x2F800 && (ch) <= 0x2FA1F))
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
HDC _pango_win32_hdc;
|
|
Packit |
0ec9dd |
OSVERSIONINFO _pango_win32_os_version_info;
|
|
Packit |
0ec9dd |
gboolean _pango_win32_debug = FALSE;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static void pango_win32_font_dispose (GObject *object);
|
|
Packit |
0ec9dd |
static void pango_win32_font_finalize (GObject *object);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static PangoFontDescription *pango_win32_font_describe (PangoFont *font);
|
|
Packit |
0ec9dd |
static PangoFontDescription *pango_win32_font_describe_absolute (PangoFont *font);
|
|
Packit |
0ec9dd |
static PangoCoverage *pango_win32_font_get_coverage (PangoFont *font,
|
|
Packit |
0ec9dd |
PangoLanguage *lang);
|
|
Packit |
0ec9dd |
static void pango_win32_font_calc_coverage (PangoFont *font,
|
|
Packit |
0ec9dd |
PangoCoverage *coverage,
|
|
Packit |
0ec9dd |
PangoLanguage *lang);
|
|
Packit |
0ec9dd |
static PangoEngineShape *pango_win32_font_find_shaper (PangoFont *font,
|
|
Packit |
0ec9dd |
PangoLanguage *lang,
|
|
Packit |
0ec9dd |
guint32 ch);
|
|
Packit |
0ec9dd |
static void pango_win32_font_get_glyph_extents (PangoFont *font,
|
|
Packit |
0ec9dd |
PangoGlyph glyph,
|
|
Packit |
0ec9dd |
PangoRectangle *ink_rect,
|
|
Packit |
0ec9dd |
PangoRectangle *logical_rect);
|
|
Packit |
0ec9dd |
static PangoFontMetrics * pango_win32_font_get_metrics (PangoFont *font,
|
|
Packit |
0ec9dd |
PangoLanguage *lang);
|
|
Packit |
0ec9dd |
static PangoFontMap * pango_win32_font_get_font_map (PangoFont *font);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static gboolean pango_win32_font_real_select_font (PangoFont *font,
|
|
Packit |
0ec9dd |
HDC hdc);
|
|
Packit |
0ec9dd |
static void pango_win32_font_real_done_font (PangoFont *font);
|
|
Packit |
0ec9dd |
static double pango_win32_font_real_get_metrics_factor (PangoFont *font);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static void pango_win32_get_item_properties (PangoItem *item,
|
|
Packit |
0ec9dd |
PangoUnderline *uline,
|
|
Packit |
0ec9dd |
PangoAttrColor *uline_color,
|
|
Packit |
0ec9dd |
gboolean *uline_set,
|
|
Packit |
0ec9dd |
PangoAttrColor *fg_color,
|
|
Packit |
0ec9dd |
gboolean *fg_set,
|
|
Packit |
0ec9dd |
PangoAttrColor *bg_color,
|
|
Packit |
0ec9dd |
gboolean *bg_set);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
HFONT
|
|
Packit |
0ec9dd |
_pango_win32_font_get_hfont (PangoFont *font)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoWin32Font *win32font = (PangoWin32Font *)font;
|
|
Packit |
0ec9dd |
PangoWin32FontCache *cache;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (!win32font)
|
|
Packit |
0ec9dd |
return NULL;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (!win32font->hfont)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
cache = pango_win32_font_map_get_font_cache (win32font->fontmap);
|
|
Packit |
0ec9dd |
if (G_UNLIKELY (!cache))
|
|
Packit |
0ec9dd |
return NULL;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
win32font->hfont = pango_win32_font_cache_loadw (cache, &win32font->logfontw);
|
|
Packit |
0ec9dd |
if (!win32font->hfont)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
gchar *face_utf8 = g_utf16_to_utf8 (win32font->logfontw.lfFaceName,
|
|
Packit |
0ec9dd |
-1, NULL, NULL, NULL);
|
|
Packit |
0ec9dd |
g_warning ("Cannot load font '%s\n", face_utf8);
|
|
Packit |
0ec9dd |
g_free (face_utf8);
|
|
Packit |
0ec9dd |
return NULL;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return win32font->hfont;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/**
|
|
Packit |
0ec9dd |
* pango_win32_get_context:
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Retrieves a #PangoContext appropriate for rendering with Windows fonts.
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Return value: the new #PangoContext
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Deprecated: 1.22: Use pango_win32_font_map_for_display() followed by
|
|
Packit |
0ec9dd |
* pango_font_map_create_context() instead.
|
|
Packit |
0ec9dd |
**/
|
|
Packit |
0ec9dd |
PangoContext *
|
|
Packit |
0ec9dd |
pango_win32_get_context (void)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
return pango_font_map_create_context (pango_win32_font_map_for_display ());
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
G_DEFINE_TYPE (PangoWin32Font, _pango_win32_font, PANGO_TYPE_FONT)
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
_pango_win32_font_init (PangoWin32Font *win32font)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
win32font->size = -1;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
win32font->metrics_by_lang = NULL;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
win32font->glyph_info = g_hash_table_new_full (NULL, NULL, NULL, g_free);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/**
|
|
Packit |
0ec9dd |
* pango_win32_get_dc:
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Obtains a handle to the Windows device context that is used by Pango.
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Return value: A handle to the Windows device context that is used by Pango.
|
|
Packit |
0ec9dd |
**/
|
|
Packit |
0ec9dd |
HDC
|
|
Packit |
0ec9dd |
pango_win32_get_dc (void)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
if (g_once_init_enter (&_pango_win32_hdc))
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
HDC hdc = CreateDC ("DISPLAY", NULL, NULL, NULL);
|
|
Packit |
0ec9dd |
memset (&_pango_win32_os_version_info, 0,
|
|
Packit |
0ec9dd |
sizeof (_pango_win32_os_version_info));
|
|
Packit |
0ec9dd |
_pango_win32_os_version_info.dwOSVersionInfoSize =
|
|
Packit |
0ec9dd |
sizeof (OSVERSIONINFO);
|
|
Packit |
0ec9dd |
GetVersionEx (&_pango_win32_os_version_info);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* Also do some generic pangowin32 initialisations... this function
|
|
Packit |
0ec9dd |
* is a suitable place for those as it is called from a couple
|
|
Packit |
0ec9dd |
* of class_init functions.
|
|
Packit |
0ec9dd |
*/
|
|
Packit |
0ec9dd |
#ifdef PANGO_WIN32_DEBUGGING
|
|
Packit |
0ec9dd |
if (getenv ("PANGO_WIN32_DEBUG") != NULL)
|
|
Packit |
0ec9dd |
_pango_win32_debug = TRUE;
|
|
Packit |
0ec9dd |
#endif
|
|
Packit |
0ec9dd |
g_once_init_leave (&_pango_win32_hdc, hdc);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return _pango_win32_hdc;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/**
|
|
Packit |
0ec9dd |
* pango_win32_get_debug_flag:
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Returns whether debugging is turned on.
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Return value: %TRUE if debugging is turned on.
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Since: 1.2
|
|
Packit |
0ec9dd |
*/
|
|
Packit |
0ec9dd |
gboolean
|
|
Packit |
0ec9dd |
pango_win32_get_debug_flag (void)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
return _pango_win32_debug;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
_pango_win32_font_class_init (PangoWin32FontClass *class)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
|
Packit |
0ec9dd |
PangoFontClass *font_class = PANGO_FONT_CLASS (class);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
object_class->finalize = pango_win32_font_finalize;
|
|
Packit |
0ec9dd |
object_class->dispose = pango_win32_font_dispose;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
font_class->describe = pango_win32_font_describe;
|
|
Packit |
0ec9dd |
font_class->describe_absolute = pango_win32_font_describe_absolute;
|
|
Packit |
0ec9dd |
font_class->get_coverage = pango_win32_font_get_coverage;
|
|
Packit |
0ec9dd |
font_class->find_shaper = pango_win32_font_find_shaper;
|
|
Packit |
0ec9dd |
font_class->get_glyph_extents = pango_win32_font_get_glyph_extents;
|
|
Packit |
0ec9dd |
font_class->get_metrics = pango_win32_font_get_metrics;
|
|
Packit |
0ec9dd |
font_class->get_font_map = pango_win32_font_get_font_map;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
class->select_font = pango_win32_font_real_select_font;
|
|
Packit |
0ec9dd |
class->done_font = pango_win32_font_real_done_font;
|
|
Packit |
0ec9dd |
class->get_metrics_factor = pango_win32_font_real_get_metrics_factor;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
pango_win32_get_dc ();
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/**
|
|
Packit |
0ec9dd |
* pango_win32_render:
|
|
Packit |
0ec9dd |
* @hdc: the device context
|
|
Packit |
0ec9dd |
* @font: the font in which to draw the string
|
|
Packit |
0ec9dd |
* @glyphs: the glyph string to draw
|
|
Packit |
0ec9dd |
* @x: the x position of start of string (in pixels)
|
|
Packit |
0ec9dd |
* @y: the y position of baseline (in pixels)
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Render a #PangoGlyphString onto a Windows DC
|
|
Packit |
0ec9dd |
*/
|
|
Packit |
0ec9dd |
void
|
|
Packit |
0ec9dd |
pango_win32_render (HDC hdc,
|
|
Packit |
0ec9dd |
PangoFont *font,
|
|
Packit |
0ec9dd |
PangoGlyphString *glyphs,
|
|
Packit |
0ec9dd |
int x,
|
|
Packit |
0ec9dd |
int y)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
HFONT hfont, old_hfont = NULL;
|
|
Packit |
0ec9dd |
int i, j, num_valid_glyphs;
|
|
Packit |
0ec9dd |
guint16 *glyph_indexes;
|
|
Packit |
0ec9dd |
gint *dX;
|
|
Packit |
0ec9dd |
gint this_x;
|
|
Packit |
0ec9dd |
gint start_x_offset, x_offset, next_x_offset, cur_y_offset; /* in Pango units */
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
g_return_if_fail (glyphs != NULL);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
#ifdef PANGO_WIN32_DEBUGGING
|
|
Packit |
0ec9dd |
if (_pango_win32_debug)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PING (("num_glyphs:%d", glyphs->num_glyphs));
|
|
Packit |
0ec9dd |
for (i = 0; i < glyphs->num_glyphs; i++)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
g_print (" %d:%d", glyphs->glyphs[i].glyph, glyphs->glyphs[i].geometry.width);
|
|
Packit |
0ec9dd |
if (glyphs->glyphs[i].geometry.x_offset != 0 ||
|
|
Packit |
0ec9dd |
glyphs->glyphs[i].geometry.y_offset != 0)
|
|
Packit |
0ec9dd |
g_print (":%d,%d", glyphs->glyphs[i].geometry.x_offset,
|
|
Packit |
0ec9dd |
glyphs->glyphs[i].geometry.y_offset);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
g_print ("\n");
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
#endif
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (glyphs->num_glyphs == 0)
|
|
Packit |
0ec9dd |
return;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
hfont = _pango_win32_font_get_hfont (font);
|
|
Packit |
0ec9dd |
if (!hfont)
|
|
Packit |
0ec9dd |
return;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
old_hfont = SelectObject (hdc, hfont);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
glyph_indexes = g_new (guint16, glyphs->num_glyphs);
|
|
Packit |
0ec9dd |
dX = g_new (INT, glyphs->num_glyphs);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* Render glyphs using one ExtTextOutW() call for each run of glyphs
|
|
Packit |
0ec9dd |
* that have the same y offset. The big majoroty of glyphs will have
|
|
Packit |
0ec9dd |
* y offset of zero, so in general, the whole glyph string will be
|
|
Packit |
0ec9dd |
* rendered by one call to ExtTextOutW().
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* In order to minimize buildup of rounding errors, we keep track of
|
|
Packit |
0ec9dd |
* where the glyphs should be rendered in Pango units, and round
|
|
Packit |
0ec9dd |
* to pixels separately for each glyph,
|
|
Packit |
0ec9dd |
*/
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
i = 0;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* Outer loop through all glyphs in string */
|
|
Packit |
0ec9dd |
while (i < glyphs->num_glyphs)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
cur_y_offset = glyphs->glyphs[i].geometry.y_offset;
|
|
Packit |
0ec9dd |
num_valid_glyphs = 0;
|
|
Packit |
0ec9dd |
x_offset = 0;
|
|
Packit |
0ec9dd |
start_x_offset = glyphs->glyphs[i].geometry.x_offset;
|
|
Packit |
0ec9dd |
this_x = PANGO_PIXELS (start_x_offset);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* Inner loop through glyphs with the same y offset, or code
|
|
Packit |
0ec9dd |
* point zero (just spacing).
|
|
Packit |
0ec9dd |
*/
|
|
Packit |
0ec9dd |
while (i < glyphs->num_glyphs &&
|
|
Packit |
0ec9dd |
(glyphs->glyphs[i].glyph == PANGO_GLYPH_EMPTY ||
|
|
Packit |
0ec9dd |
cur_y_offset == glyphs->glyphs[i].geometry.y_offset))
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
if (glyphs->glyphs[i].glyph == PANGO_GLYPH_EMPTY)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
/* PANGO_GLYPH_EMPTY glyphs should not be rendered, but their
|
|
Packit |
0ec9dd |
* indicated width (set up by PangoLayout) should be taken
|
|
Packit |
0ec9dd |
* into account.
|
|
Packit |
0ec9dd |
*/
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* If the string starts with spacing, must shift the
|
|
Packit |
0ec9dd |
* starting point for the glyphs actually rendered. For
|
|
Packit |
0ec9dd |
* spacing in the middle of the glyph string, add to the dX
|
|
Packit |
0ec9dd |
* of the previous glyph to be rendered.
|
|
Packit |
0ec9dd |
*/
|
|
Packit |
0ec9dd |
if (num_valid_glyphs == 0)
|
|
Packit |
0ec9dd |
start_x_offset += glyphs->glyphs[i].geometry.width;
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
x_offset += glyphs->glyphs[i].geometry.width;
|
|
Packit |
0ec9dd |
dX[num_valid_glyphs-1] = PANGO_PIXELS (x_offset) - this_x;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
if (glyphs->glyphs[i].glyph & PANGO_GLYPH_UNKNOWN_FLAG)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
/* Glyph index is actually the char value that doesn't
|
|
Packit |
0ec9dd |
* have any glyph (ORed with the flag). We should really
|
|
Packit |
0ec9dd |
* do the same that pango_xft_real_render() does: render
|
|
Packit |
0ec9dd |
* a box with the char value in hex inside it in a tiny
|
|
Packit |
0ec9dd |
* font. Later. For now, use the TrueType invalid glyph
|
|
Packit |
0ec9dd |
* at 0.
|
|
Packit |
0ec9dd |
*/
|
|
Packit |
0ec9dd |
glyph_indexes[num_valid_glyphs] = 0;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
glyph_indexes[num_valid_glyphs] = glyphs->glyphs[i].glyph;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
x_offset += glyphs->glyphs[i].geometry.width;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* If the next glyph has an X offset, take that into consideration now */
|
|
Packit |
0ec9dd |
if (i < glyphs->num_glyphs - 1)
|
|
Packit |
0ec9dd |
next_x_offset = glyphs->glyphs[i+1].geometry.x_offset;
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
next_x_offset = 0;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
dX[num_valid_glyphs] = PANGO_PIXELS (x_offset + next_x_offset) - this_x;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* Prepare for next glyph */
|
|
Packit |
0ec9dd |
this_x += dX[num_valid_glyphs];
|
|
Packit |
0ec9dd |
num_valid_glyphs++;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
i++;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
#ifdef PANGO_WIN32_DEBUGGING
|
|
Packit |
0ec9dd |
if (_pango_win32_debug)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
g_print ("ExtTextOutW at %d,%d deltas:",
|
|
Packit |
0ec9dd |
x + PANGO_PIXELS (start_x_offset),
|
|
Packit |
0ec9dd |
y + PANGO_PIXELS (cur_y_offset));
|
|
Packit |
0ec9dd |
for (j = 0; j < num_valid_glyphs; j++)
|
|
Packit |
0ec9dd |
g_print (" %d", dX[j]);
|
|
Packit |
0ec9dd |
g_print ("\n");
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
#endif
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
ExtTextOutW (hdc,
|
|
Packit |
0ec9dd |
x + PANGO_PIXELS (start_x_offset),
|
|
Packit |
0ec9dd |
y + PANGO_PIXELS (cur_y_offset),
|
|
Packit |
0ec9dd |
ETO_GLYPH_INDEX,
|
|
Packit |
0ec9dd |
NULL,
|
|
Packit |
0ec9dd |
glyph_indexes, num_valid_glyphs,
|
|
Packit |
0ec9dd |
dX);
|
|
Packit |
0ec9dd |
x += this_x;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
SelectObject (hdc, old_hfont); /* restore */
|
|
Packit |
0ec9dd |
g_free (glyph_indexes);
|
|
Packit |
0ec9dd |
g_free (dX);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/**
|
|
Packit |
0ec9dd |
* pango_win32_render_transformed:
|
|
Packit |
0ec9dd |
* @hdc: a windows device context
|
|
Packit |
0ec9dd |
* @matrix: (nullable): a #PangoMatrix, or %NULL to use an identity
|
|
Packit |
0ec9dd |
* transformation
|
|
Packit |
0ec9dd |
* @font: the font in which to draw the string
|
|
Packit |
0ec9dd |
* @glyphs: the glyph string to draw
|
|
Packit |
0ec9dd |
* @x: the x position of the start of the string (in Pango
|
|
Packit |
0ec9dd |
* units in user space coordinates)
|
|
Packit |
0ec9dd |
* @y: the y position of the baseline (in Pango units
|
|
Packit |
0ec9dd |
* in user space coordinates)
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Renders a #PangoGlyphString onto a windows DC, possibly
|
|
Packit |
0ec9dd |
* transforming the layed-out coordinates through a transformation
|
|
Packit |
0ec9dd |
* matrix. Note that the transformation matrix for @font is not
|
|
Packit |
0ec9dd |
* changed, so to produce correct rendering results, the @font
|
|
Packit |
0ec9dd |
* must have been loaded using a #PangoContext with an identical
|
|
Packit |
0ec9dd |
* transformation matrix to that passed in to this function.
|
|
Packit |
0ec9dd |
**/
|
|
Packit |
0ec9dd |
void
|
|
Packit |
0ec9dd |
pango_win32_render_transformed (HDC hdc,
|
|
Packit |
0ec9dd |
const PangoMatrix *matrix,
|
|
Packit |
0ec9dd |
PangoFont *font,
|
|
Packit |
0ec9dd |
PangoGlyphString *glyphs,
|
|
Packit |
0ec9dd |
int x,
|
|
Packit |
0ec9dd |
int y)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
XFORM xForm;
|
|
Packit |
0ec9dd |
XFORM xFormPrev = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
|
|
Packit |
0ec9dd |
int mode = GetGraphicsMode (hdc);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (!SetGraphicsMode (hdc, GM_ADVANCED))
|
|
Packit |
0ec9dd |
g_warning ("SetGraphicsMode() failed");
|
|
Packit |
0ec9dd |
else if (!GetWorldTransform (hdc, &xFormPrev))
|
|
Packit |
0ec9dd |
g_warning ("GetWorldTransform() failed");
|
|
Packit |
0ec9dd |
else if (matrix)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
xForm.eM11 = matrix->xx;
|
|
Packit |
0ec9dd |
xForm.eM12 = matrix->yx;
|
|
Packit |
0ec9dd |
xForm.eM21 = matrix->xy;
|
|
Packit |
0ec9dd |
xForm.eM22 = matrix->yy;
|
|
Packit |
0ec9dd |
xForm.eDx = matrix->x0;
|
|
Packit |
0ec9dd |
xForm.eDy = matrix->y0;
|
|
Packit |
0ec9dd |
if (!SetWorldTransform (hdc, &xForm))
|
|
Packit |
0ec9dd |
g_warning ("GetWorldTransform() failed");
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
pango_win32_render (hdc, font, glyphs, x/PANGO_SCALE, y/PANGO_SCALE);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* restore */
|
|
Packit |
0ec9dd |
SetWorldTransform (hdc, &xFormPrev);
|
|
Packit |
0ec9dd |
SetGraphicsMode (hdc, mode);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
pango_win32_font_get_glyph_extents (PangoFont *font,
|
|
Packit |
0ec9dd |
PangoGlyph glyph,
|
|
Packit |
0ec9dd |
PangoRectangle *ink_rect,
|
|
Packit |
0ec9dd |
PangoRectangle *logical_rect)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoWin32Font *win32font = (PangoWin32Font *)font;
|
|
Packit |
0ec9dd |
guint16 glyph_index = glyph;
|
|
Packit |
0ec9dd |
GLYPHMETRICS gm;
|
|
Packit |
0ec9dd |
TEXTMETRIC tm;
|
|
Packit |
0ec9dd |
guint32 res;
|
|
Packit |
0ec9dd |
HFONT hfont;
|
|
Packit |
0ec9dd |
MAT2 m = {{0,1}, {0,0}, {0,0}, {0,1}};
|
|
Packit |
0ec9dd |
PangoWin32GlyphInfo *info;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (glyph == PANGO_GLYPH_EMPTY)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
if (ink_rect)
|
|
Packit |
0ec9dd |
ink_rect->x = ink_rect->width = ink_rect->y = ink_rect->height = 0;
|
|
Packit |
0ec9dd |
if (logical_rect)
|
|
Packit |
0ec9dd |
logical_rect->x = logical_rect->width = logical_rect->y = logical_rect->height = 0;
|
|
Packit |
0ec9dd |
return;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
|
|
Packit |
0ec9dd |
glyph_index = glyph = 0;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
info = g_hash_table_lookup (win32font->glyph_info, GUINT_TO_POINTER (glyph));
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (!info)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
info = g_new0 (PangoWin32GlyphInfo, 1);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
memset (&gm, 0, sizeof (gm));
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
hfont = _pango_win32_font_get_hfont (font);
|
|
Packit |
0ec9dd |
SelectObject (_pango_win32_hdc, hfont);
|
|
Packit |
0ec9dd |
/* FIXME: (Alex) This constant reuse of _pango_win32_hdc is
|
|
Packit |
0ec9dd |
not thread-safe */
|
|
Packit |
0ec9dd |
res = GetGlyphOutlineA (_pango_win32_hdc,
|
|
Packit |
0ec9dd |
glyph_index,
|
|
Packit |
0ec9dd |
GGO_METRICS | GGO_GLYPH_INDEX,
|
|
Packit |
0ec9dd |
&gm,
|
|
Packit |
0ec9dd |
0, NULL,
|
|
Packit |
0ec9dd |
&m);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (res == GDI_ERROR)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
gchar *error = g_win32_error_message (GetLastError ());
|
|
Packit |
0ec9dd |
g_warning ("GetGlyphOutline(%04X) failed: %s\n",
|
|
Packit |
0ec9dd |
glyph_index, error);
|
|
Packit |
0ec9dd |
g_free (error);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* Don't just return now, use the still zeroed out gm */
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
info->ink_rect.x = PANGO_SCALE * gm.gmptGlyphOrigin.x;
|
|
Packit |
0ec9dd |
info->ink_rect.width = PANGO_SCALE * gm.gmBlackBoxX;
|
|
Packit |
0ec9dd |
info->ink_rect.y = - PANGO_SCALE * gm.gmptGlyphOrigin.y;
|
|
Packit |
0ec9dd |
info->ink_rect.height = PANGO_SCALE * gm.gmBlackBoxY;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
GetTextMetrics (_pango_win32_hdc, &tm;;
|
|
Packit |
0ec9dd |
info->logical_rect.x = 0;
|
|
Packit |
0ec9dd |
info->logical_rect.width = PANGO_SCALE * gm.gmCellIncX;
|
|
Packit |
0ec9dd |
info->logical_rect.y = - PANGO_SCALE * tm.tmAscent;
|
|
Packit |
0ec9dd |
info->logical_rect.height = PANGO_SCALE * (tm.tmAscent + tm.tmDescent);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
g_hash_table_insert (win32font->glyph_info, GUINT_TO_POINTER(glyph), info);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (ink_rect)
|
|
Packit |
0ec9dd |
*ink_rect = info->ink_rect;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (logical_rect)
|
|
Packit |
0ec9dd |
*logical_rect = info->logical_rect;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static int
|
|
Packit |
0ec9dd |
max_glyph_width (PangoLayout *layout)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
int max_width = 0;
|
|
Packit |
0ec9dd |
GSList *l, *r;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
for (l = pango_layout_get_lines_readonly (layout); l; l = l->next)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoLayoutLine *line = l->data;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
for (r = line->runs; r; r = r->next)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs;
|
|
Packit |
0ec9dd |
int i;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
for (i = 0; i < glyphs->num_glyphs; i++)
|
|
Packit |
0ec9dd |
if (glyphs->glyphs[i].geometry.width > max_width)
|
|
Packit |
0ec9dd |
max_width = glyphs->glyphs[i].geometry.width;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return max_width;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static PangoFontMetrics *
|
|
Packit |
0ec9dd |
pango_win32_font_get_metrics (PangoFont *font,
|
|
Packit |
0ec9dd |
PangoLanguage *language)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoWin32MetricsInfo *info = NULL; /* Quiet gcc */
|
|
Packit |
0ec9dd |
PangoWin32Font *win32font = (PangoWin32Font *)font;
|
|
Packit |
0ec9dd |
GSList *tmp_list;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
const char *sample_str = pango_language_get_sample_string (language);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
tmp_list = win32font->metrics_by_lang;
|
|
Packit |
0ec9dd |
while (tmp_list)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
info = tmp_list->data;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (info->sample_str == sample_str) /* We _don't_ need strcmp */
|
|
Packit |
0ec9dd |
break;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
tmp_list = tmp_list->next;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (!tmp_list)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
HFONT hfont;
|
|
Packit |
0ec9dd |
PangoFontMetrics *metrics;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
info = g_new (PangoWin32MetricsInfo, 1);
|
|
Packit |
0ec9dd |
win32font->metrics_by_lang = g_slist_prepend (win32font->metrics_by_lang, info);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
info->sample_str = sample_str;
|
|
Packit |
0ec9dd |
info->metrics = metrics = pango_font_metrics_new ();
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
hfont = _pango_win32_font_get_hfont (font);
|
|
Packit |
0ec9dd |
if (hfont != NULL)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoCoverage *coverage;
|
|
Packit |
0ec9dd |
TEXTMETRIC tm;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
SelectObject (_pango_win32_hdc, hfont);
|
|
Packit |
0ec9dd |
GetTextMetrics (_pango_win32_hdc, &tm;;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
metrics->ascent = tm.tmAscent * PANGO_SCALE;
|
|
Packit |
0ec9dd |
metrics->descent = tm.tmDescent * PANGO_SCALE;
|
|
Packit |
0ec9dd |
metrics->approximate_char_width = tm.tmAveCharWidth * PANGO_SCALE;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
coverage = pango_win32_font_get_coverage (font, language);
|
|
Packit |
0ec9dd |
if (pango_coverage_get (coverage, '0') != PANGO_COVERAGE_NONE &&
|
|
Packit |
0ec9dd |
pango_coverage_get (coverage, '9') != PANGO_COVERAGE_NONE)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoContext *context;
|
|
Packit |
0ec9dd |
PangoFontDescription *font_desc;
|
|
Packit |
0ec9dd |
PangoLayout *layout;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* Get the average width of the chars in "0123456789" */
|
|
Packit |
0ec9dd |
context = pango_font_map_create_context (pango_win32_font_map_for_display ());
|
|
Packit |
0ec9dd |
pango_context_set_language (context, language);
|
|
Packit |
0ec9dd |
font_desc = pango_font_describe_with_absolute_size (font);
|
|
Packit |
0ec9dd |
pango_context_set_font_description (context, font_desc);
|
|
Packit |
0ec9dd |
layout = pango_layout_new (context);
|
|
Packit |
0ec9dd |
pango_layout_set_text (layout, "0123456789", -1);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
metrics->approximate_digit_width = max_glyph_width (layout);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
pango_font_description_free (font_desc);
|
|
Packit |
0ec9dd |
g_object_unref (layout);
|
|
Packit |
0ec9dd |
g_object_unref (context);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
metrics->approximate_digit_width = metrics->approximate_char_width;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
pango_coverage_unref (coverage);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* FIXME: Should get the real values from the TrueType font file */
|
|
Packit |
0ec9dd |
metrics->underline_position = -2 * PANGO_SCALE;
|
|
Packit |
0ec9dd |
metrics->underline_thickness = 1 * PANGO_SCALE;
|
|
Packit |
0ec9dd |
metrics->strikethrough_thickness = metrics->underline_thickness;
|
|
Packit |
0ec9dd |
/* Really really wild guess */
|
|
Packit |
0ec9dd |
metrics->strikethrough_position = metrics->ascent / 3;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return pango_font_metrics_ref (info->metrics);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static PangoFontMap *
|
|
Packit |
0ec9dd |
pango_win32_font_get_font_map (PangoFont *font)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoWin32Font *win32font = (PangoWin32Font *)font;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return win32font->fontmap;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static gboolean
|
|
Packit |
0ec9dd |
pango_win32_font_real_select_font (PangoFont *font,
|
|
Packit |
0ec9dd |
HDC hdc)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
HFONT hfont = _pango_win32_font_get_hfont (font);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (!hfont)
|
|
Packit |
0ec9dd |
return FALSE;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (!SelectObject (hdc, hfont))
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
g_warning ("pango_win32_font_real_select_font: Cannot select font\n");
|
|
Packit |
0ec9dd |
return FALSE;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return TRUE;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
pango_win32_font_real_done_font (PangoFont *font)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static double
|
|
Packit |
0ec9dd |
pango_win32_font_real_get_metrics_factor (PangoFont *font)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
return PANGO_SCALE;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/**
|
|
Packit |
0ec9dd |
* pango_win32_font_logfont:
|
|
Packit |
0ec9dd |
* @font: a #PangoFont which must be from the Win32 backend
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Determine the LOGFONTA struct for the specified font. Note that
|
|
Packit |
0ec9dd |
* Pango internally uses LOGFONTW structs, so if converting the UTF-16
|
|
Packit |
0ec9dd |
* face name in the LOGFONTW struct to system codepage fails, the
|
|
Packit |
0ec9dd |
* returned LOGFONTA will have an emppty face name. To get the
|
|
Packit |
0ec9dd |
* LOGFONTW of a PangoFont, use pango_win32_font_logfontw(). It
|
|
Packit |
0ec9dd |
* is recommended to do that always even if you don't expect
|
|
Packit |
0ec9dd |
* to come across fonts with odd names.
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Return value: A newly allocated LOGFONTA struct. It must be
|
|
Packit |
0ec9dd |
* freed with g_free().
|
|
Packit |
0ec9dd |
**/
|
|
Packit |
0ec9dd |
LOGFONTA *
|
|
Packit |
0ec9dd |
pango_win32_font_logfont (PangoFont *font)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoWin32Font *win32font = (PangoWin32Font *)font;
|
|
Packit |
0ec9dd |
LOGFONTA *lfp;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
g_return_val_if_fail (font != NULL, NULL);
|
|
Packit |
0ec9dd |
g_return_val_if_fail (PANGO_WIN32_IS_FONT (font), NULL);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
lfp = g_new (LOGFONTA, 1);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
*lfp = *(LOGFONTA*) &win32font->logfontw;
|
|
Packit |
0ec9dd |
if (!WideCharToMultiByte (CP_ACP, 0,
|
|
Packit |
0ec9dd |
win32font->logfontw.lfFaceName, -1,
|
|
Packit |
0ec9dd |
lfp->lfFaceName, G_N_ELEMENTS (lfp->lfFaceName),
|
|
Packit |
0ec9dd |
NULL, NULL))
|
|
Packit |
0ec9dd |
lfp->lfFaceName[0] = '\0';
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return lfp;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/**
|
|
Packit |
0ec9dd |
* pango_win32_font_logfontw:
|
|
Packit |
0ec9dd |
* @font: a #PangoFont which must be from the Win32 backend
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Determine the LOGFONTW struct for the specified font.
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Return value: A newly allocated LOGFONTW struct. It must be
|
|
Packit |
0ec9dd |
* freed with g_free().
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Since: 1.16
|
|
Packit |
0ec9dd |
**/
|
|
Packit |
0ec9dd |
LOGFONTW *
|
|
Packit |
0ec9dd |
pango_win32_font_logfontw (PangoFont *font)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoWin32Font *win32font = (PangoWin32Font *)font;
|
|
Packit |
0ec9dd |
LOGFONTW *lfp;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
g_return_val_if_fail (font != NULL, NULL);
|
|
Packit |
0ec9dd |
g_return_val_if_fail (PANGO_WIN32_IS_FONT (font), NULL);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
lfp = g_new (LOGFONTW, 1);
|
|
Packit |
0ec9dd |
*lfp = win32font->logfontw;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return lfp;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/**
|
|
Packit |
0ec9dd |
* pango_win32_font_select_font:
|
|
Packit |
0ec9dd |
* @font: a #PangoFont from the Win32 backend
|
|
Packit |
0ec9dd |
* @hdc: a windows device context
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Selects the font into the specified DC and changes the mapping mode
|
|
Packit |
0ec9dd |
* and world transformation of the DC appropriately for the font.
|
|
Packit |
0ec9dd |
* You may want to surround the use of this function with calls
|
|
Packit |
0ec9dd |
* to SaveDC() and RestoreDC(). Call pango_win32_font_done_font() when
|
|
Packit |
0ec9dd |
* you are done using the DC to release allocated resources.
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* See pango_win32_font_get_metrics_factor() for information about
|
|
Packit |
0ec9dd |
* converting from the coordinate space used by this function
|
|
Packit |
0ec9dd |
* into Pango units.
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Return value: %TRUE if the operation succeeded.
|
|
Packit |
0ec9dd |
**/
|
|
Packit |
0ec9dd |
gboolean
|
|
Packit |
0ec9dd |
pango_win32_font_select_font (PangoFont *font,
|
|
Packit |
0ec9dd |
HDC hdc)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
g_return_val_if_fail (PANGO_WIN32_IS_FONT (font), FALSE);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return PANGO_WIN32_FONT_GET_CLASS (font)->select_font (font, hdc);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/**
|
|
Packit |
0ec9dd |
* pango_win32_font_done_font:
|
|
Packit |
0ec9dd |
* @font: a #PangoFont from the win32 backend
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Releases any resources allocated by pango_win32_font_done_font()
|
|
Packit |
0ec9dd |
**/
|
|
Packit |
0ec9dd |
void
|
|
Packit |
0ec9dd |
pango_win32_font_done_font (PangoFont *font)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
g_return_if_fail (PANGO_WIN32_IS_FONT (font));
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
PANGO_WIN32_FONT_GET_CLASS (font)->done_font (font);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/**
|
|
Packit |
0ec9dd |
* pango_win32_font_get_metrics_factor:
|
|
Packit |
0ec9dd |
* @font: a #PangoFont from the win32 backend
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Returns the scale factor from logical units in the coordinate
|
|
Packit |
0ec9dd |
* space used by pango_win32_font_select_font() to Pango units
|
|
Packit |
0ec9dd |
* in user space.
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Return value: factor to multiply logical units by to get Pango
|
|
Packit |
0ec9dd |
* units.
|
|
Packit |
0ec9dd |
**/
|
|
Packit |
0ec9dd |
double
|
|
Packit |
0ec9dd |
pango_win32_font_get_metrics_factor (PangoFont *font)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
g_return_val_if_fail (PANGO_WIN32_IS_FONT (font), 1.);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return PANGO_WIN32_FONT_GET_CLASS (font)->get_metrics_factor (font);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
pango_win32_fontmap_cache_add (PangoFontMap *fontmap,
|
|
Packit |
0ec9dd |
PangoWin32Font *win32font)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoWin32FontMap *win32fontmap = PANGO_WIN32_FONT_MAP (fontmap);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (win32fontmap->freed_fonts->length == MAX_FREED_FONTS)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoWin32Font *old_font = g_queue_pop_tail (win32fontmap->freed_fonts);
|
|
Packit |
0ec9dd |
g_object_unref (old_font);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
g_object_ref (win32font);
|
|
Packit |
0ec9dd |
g_queue_push_head (win32fontmap->freed_fonts, win32font);
|
|
Packit |
0ec9dd |
win32font->in_cache = TRUE;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
pango_win32_font_dispose (GObject *object)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoWin32Font *win32font = PANGO_WIN32_FONT (object);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* If the font is not already in the freed-fonts cache, add it,
|
|
Packit |
0ec9dd |
* if it is already there, do nothing and the font will be
|
|
Packit |
0ec9dd |
* freed.
|
|
Packit |
0ec9dd |
*/
|
|
Packit |
0ec9dd |
if (!win32font->in_cache && win32font->fontmap)
|
|
Packit |
0ec9dd |
pango_win32_fontmap_cache_add (win32font->fontmap, win32font);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
G_OBJECT_CLASS (_pango_win32_font_parent_class)->dispose (object);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
free_metrics_info (PangoWin32MetricsInfo *info)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
pango_font_metrics_unref (info->metrics);
|
|
Packit |
0ec9dd |
g_free (info);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
pango_win32_font_entry_remove (PangoWin32Face *face,
|
|
Packit |
0ec9dd |
PangoFont *font)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
face->cached_fonts = g_slist_remove (face->cached_fonts, font);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
pango_win32_font_finalize (GObject *object)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoWin32Font *win32font = (PangoWin32Font *)object;
|
|
Packit |
0ec9dd |
PangoWin32FontCache *cache = pango_win32_font_map_get_font_cache (win32font->fontmap);
|
|
Packit |
0ec9dd |
PangoWin32Font *fontmap;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (G_UNLIKELY (!cache))
|
|
Packit |
0ec9dd |
return;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (win32font->hfont != NULL)
|
|
Packit |
0ec9dd |
pango_win32_font_cache_unload (cache, win32font->hfont);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
g_slist_foreach (win32font->metrics_by_lang, (GFunc)free_metrics_info, NULL);
|
|
Packit |
0ec9dd |
g_slist_free (win32font->metrics_by_lang);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (win32font->win32face)
|
|
Packit |
0ec9dd |
pango_win32_font_entry_remove (win32font->win32face, PANGO_FONT (win32font));
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
g_hash_table_destroy (win32font->glyph_info);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
fontmap = g_weak_ref_get ((GWeakRef *) &win32font->fontmap);
|
|
Packit |
0ec9dd |
if (fontmap)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
g_object_remove_weak_pointer (G_OBJECT (win32font->fontmap), (gpointer *) (gpointer) &win32font->fontmap);
|
|
Packit |
0ec9dd |
g_object_unref (fontmap);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
G_OBJECT_CLASS (_pango_win32_font_parent_class)->finalize (object);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static PangoFontDescription *
|
|
Packit |
0ec9dd |
pango_win32_font_describe (PangoFont *font)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoFontDescription *desc;
|
|
Packit |
0ec9dd |
PangoWin32Font *win32font = PANGO_WIN32_FONT (font);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
desc = pango_font_description_copy (win32font->win32face->description);
|
|
Packit |
0ec9dd |
pango_font_description_set_size (desc, win32font->size / (PANGO_SCALE / PANGO_WIN32_FONT_MAP (win32font->fontmap)->resolution));
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return desc;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static PangoFontDescription *
|
|
Packit |
0ec9dd |
pango_win32_font_describe_absolute (PangoFont *font)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoFontDescription *desc;
|
|
Packit |
0ec9dd |
PangoWin32Font *win32font = PANGO_WIN32_FONT (font);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
desc = pango_font_description_copy (win32font->win32face->description);
|
|
Packit |
0ec9dd |
pango_font_description_set_absolute_size (desc, win32font->size);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return desc;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static gint
|
|
Packit |
0ec9dd |
pango_win32_coverage_language_classify (PangoLanguage *lang)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
if (pango_language_matches (lang, "zh-tw"))
|
|
Packit |
0ec9dd |
return PANGO_WIN32_COVERAGE_ZH_TW;
|
|
Packit |
0ec9dd |
else if (pango_language_matches (lang, "zh-cn"))
|
|
Packit |
0ec9dd |
return PANGO_WIN32_COVERAGE_ZH_CN;
|
|
Packit |
0ec9dd |
else if (pango_language_matches (lang, "ja"))
|
|
Packit |
0ec9dd |
return PANGO_WIN32_COVERAGE_JA;
|
|
Packit |
0ec9dd |
else if (pango_language_matches (lang, "ko"))
|
|
Packit |
0ec9dd |
return PANGO_WIN32_COVERAGE_KO;
|
|
Packit |
0ec9dd |
else if (pango_language_matches (lang, "vi"))
|
|
Packit |
0ec9dd |
return PANGO_WIN32_COVERAGE_VI;
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
return PANGO_WIN32_COVERAGE_UNSPEC;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static PangoCoverage *
|
|
Packit |
0ec9dd |
pango_win32_font_entry_get_coverage (PangoWin32Face *face,
|
|
Packit |
0ec9dd |
PangoLanguage *lang)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
gint i = pango_win32_coverage_language_classify (lang);
|
|
Packit |
0ec9dd |
if (face->coverages[i])
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
pango_coverage_ref (face->coverages[i]);
|
|
Packit |
0ec9dd |
return face->coverages[i];
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return NULL;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
pango_win32_font_entry_set_coverage (PangoWin32Face *face,
|
|
Packit |
0ec9dd |
PangoCoverage *coverage,
|
|
Packit |
0ec9dd |
PangoLanguage *lang)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
face->coverages[pango_win32_coverage_language_classify (lang)] = pango_coverage_ref (coverage);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static PangoCoverage *
|
|
Packit |
0ec9dd |
pango_win32_font_get_coverage (PangoFont *font,
|
|
Packit |
0ec9dd |
PangoLanguage *lang)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoCoverage *coverage;
|
|
Packit |
0ec9dd |
PangoWin32Font *win32font = (PangoWin32Font *)font;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
coverage = pango_win32_font_entry_get_coverage (win32font->win32face, lang);
|
|
Packit |
0ec9dd |
if (!coverage)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
coverage = pango_coverage_new ();
|
|
Packit |
0ec9dd |
pango_win32_font_calc_coverage (font, coverage, lang);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
pango_win32_font_entry_set_coverage (win32font->win32face, coverage, lang);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return coverage;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* Wrap shaper in PangoEngineShape to pass it through old API,
|
|
Packit |
0ec9dd |
* from times when there were modules and engines. */
|
|
Packit |
0ec9dd |
typedef PangoEngineShape PangoWin32ShapeEngine;
|
|
Packit |
0ec9dd |
typedef PangoEngineShapeClass PangoWin32ShapeEngineClass;
|
|
Packit |
0ec9dd |
static GType pango_win32_shape_engine_get_type (void) G_GNUC_CONST;
|
|
Packit |
0ec9dd |
G_DEFINE_TYPE (PangoWin32ShapeEngine, pango_win32_shape_engine, PANGO_TYPE_ENGINE_SHAPE);
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
_pango_win32_shape_engine_shape (PangoEngineShape *engine G_GNUC_UNUSED,
|
|
Packit |
0ec9dd |
PangoFont *font,
|
|
Packit |
0ec9dd |
const char *item_text,
|
|
Packit |
0ec9dd |
unsigned int item_length,
|
|
Packit |
0ec9dd |
const PangoAnalysis *analysis,
|
|
Packit |
0ec9dd |
PangoGlyphString *glyphs,
|
|
Packit |
0ec9dd |
const char *paragraph_text,
|
|
Packit |
0ec9dd |
unsigned int paragraph_length)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
_pango_win32_shape (font, item_text, item_length, analysis, glyphs,
|
|
Packit |
0ec9dd |
paragraph_text, paragraph_length);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
pango_win32_shape_engine_class_init (PangoEngineShapeClass *class)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
class->script_shape = _pango_win32_shape_engine_shape;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
pango_win32_shape_engine_init (PangoEngineShape *object)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static PangoEngineShape *
|
|
Packit |
0ec9dd |
pango_win32_font_find_shaper (PangoFont *font,
|
|
Packit |
0ec9dd |
PangoLanguage *lang,
|
|
Packit |
0ec9dd |
guint32 ch)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
static PangoEngineShape *shaper;
|
|
Packit |
0ec9dd |
if (g_once_init_enter (&shaper))
|
|
Packit |
0ec9dd |
g_once_init_leave (&shaper, g_object_new (pango_win32_shape_engine_get_type(), NULL));
|
|
Packit |
0ec9dd |
return shaper;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* Utility functions */
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/**
|
|
Packit |
0ec9dd |
* pango_win32_get_unknown_glyph:
|
|
Packit |
0ec9dd |
* @font: a #PangoFont
|
|
Packit |
0ec9dd |
* @wc: the Unicode character for which a glyph is needed.
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Returns the index of a glyph suitable for drawing @wc as an
|
|
Packit |
0ec9dd |
* unknown character.
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Use PANGO_GET_UNKNOWN_GLYPH() instead.
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Return value: a glyph index into @font
|
|
Packit |
0ec9dd |
**/
|
|
Packit |
0ec9dd |
PangoGlyph
|
|
Packit |
0ec9dd |
pango_win32_get_unknown_glyph (PangoFont *font,
|
|
Packit |
0ec9dd |
gunichar wc)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
return PANGO_GET_UNKNOWN_GLYPH (wc);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/**
|
|
Packit |
0ec9dd |
* pango_win32_render_layout_line:
|
|
Packit |
0ec9dd |
* @hdc: DC to use for drawing
|
|
Packit |
0ec9dd |
* @line: a #PangoLayoutLine
|
|
Packit |
0ec9dd |
* @x: the x position of start of string (in pixels)
|
|
Packit |
0ec9dd |
* @y: the y position of baseline (in pixels)
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Render a #PangoLayoutLine onto a device context. For underlining to
|
|
Packit |
0ec9dd |
* work property the text alignment of the DC should have TA_BASELINE
|
|
Packit |
0ec9dd |
* and TA_LEFT.
|
|
Packit |
0ec9dd |
*/
|
|
Packit |
0ec9dd |
void
|
|
Packit |
0ec9dd |
pango_win32_render_layout_line (HDC hdc,
|
|
Packit |
0ec9dd |
PangoLayoutLine *line,
|
|
Packit |
0ec9dd |
int x,
|
|
Packit |
0ec9dd |
int y)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
GSList *tmp_list = line->runs;
|
|
Packit |
0ec9dd |
PangoRectangle overall_rect;
|
|
Packit |
0ec9dd |
PangoRectangle logical_rect;
|
|
Packit |
0ec9dd |
PangoRectangle ink_rect;
|
|
Packit |
0ec9dd |
int oldbkmode = SetBkMode (hdc, TRANSPARENT);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
int x_off = 0;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
pango_layout_line_get_extents (line,NULL, &overall_rect);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
while (tmp_list)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
COLORREF oldfg = 0;
|
|
Packit |
0ec9dd |
HPEN uline_pen, old_pen;
|
|
Packit |
0ec9dd |
POINT points[2];
|
|
Packit |
0ec9dd |
PangoUnderline uline = PANGO_UNDERLINE_NONE;
|
|
Packit |
0ec9dd |
PangoLayoutRun *run = tmp_list->data;
|
|
Packit |
0ec9dd |
PangoAttrColor fg_color, bg_color, uline_color;
|
|
Packit |
0ec9dd |
gboolean fg_set, bg_set, uline_set;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
tmp_list = tmp_list->next;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
pango_win32_get_item_properties (run->item, &uline, &uline_color, &uline_set, &fg_color, &fg_set, &bg_color, &bg_set);
|
|
Packit |
0ec9dd |
if (!uline_set)
|
|
Packit |
0ec9dd |
uline_color = fg_color;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (uline == PANGO_UNDERLINE_NONE)
|
|
Packit |
0ec9dd |
pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
|
|
Packit |
0ec9dd |
NULL, &logical_rect);
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
|
|
Packit |
0ec9dd |
&ink_rect, &logical_rect);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (bg_set)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
COLORREF bg_col = RGB ((bg_color.color.red) >> 8,
|
|
Packit |
0ec9dd |
(bg_color.color.green) >> 8,
|
|
Packit |
0ec9dd |
(bg_color.color.blue) >> 8);
|
|
Packit |
0ec9dd |
HBRUSH bg_brush = CreateSolidBrush (bg_col);
|
|
Packit |
0ec9dd |
HBRUSH old_brush = SelectObject (hdc, bg_brush);
|
|
Packit |
0ec9dd |
old_pen = SelectObject (hdc, GetStockObject (NULL_PEN));
|
|
Packit |
0ec9dd |
Rectangle (hdc, x + PANGO_PIXELS (x_off + logical_rect.x),
|
|
Packit |
0ec9dd |
y + PANGO_PIXELS (overall_rect.y),
|
|
Packit |
0ec9dd |
1 + x + PANGO_PIXELS (x_off + logical_rect.x + logical_rect.width),
|
|
Packit |
0ec9dd |
1 + y + PANGO_PIXELS (overall_rect.y + overall_rect.height));
|
|
Packit |
0ec9dd |
SelectObject (hdc, old_brush);
|
|
Packit |
0ec9dd |
DeleteObject (bg_brush);
|
|
Packit |
0ec9dd |
SelectObject (hdc, old_pen);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (fg_set)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
COLORREF fg_col = RGB ((fg_color.color.red) >> 8,
|
|
Packit |
0ec9dd |
(fg_color.color.green) >> 8,
|
|
Packit |
0ec9dd |
(fg_color.color.blue) >> 8);
|
|
Packit |
0ec9dd |
oldfg = SetTextColor (hdc, fg_col);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
pango_win32_render (hdc, run->item->analysis.font, run->glyphs,
|
|
Packit |
0ec9dd |
x + PANGO_PIXELS (x_off), y);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (fg_set)
|
|
Packit |
0ec9dd |
SetTextColor (hdc, oldfg);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (uline != PANGO_UNDERLINE_NONE)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
COLORREF uline_col = RGB ((uline_color.color.red) >> 8,
|
|
Packit |
0ec9dd |
(uline_color.color.green) >> 8,
|
|
Packit |
0ec9dd |
(uline_color.color.blue) >> 8);
|
|
Packit |
0ec9dd |
uline_pen = CreatePen (PS_SOLID, 1, uline_col);
|
|
Packit |
0ec9dd |
old_pen = SelectObject (hdc, uline_pen);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
switch (uline)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
case PANGO_UNDERLINE_NONE:
|
|
Packit |
0ec9dd |
break;
|
|
Packit |
0ec9dd |
case PANGO_UNDERLINE_DOUBLE:
|
|
Packit |
0ec9dd |
points[0].x = x + PANGO_PIXELS (x_off + ink_rect.x) - 1;
|
|
Packit |
0ec9dd |
points[0].y = points[1].y = y + 4;
|
|
Packit |
0ec9dd |
points[1].x = x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width);
|
|
Packit |
0ec9dd |
Polyline (hdc, points, 2);
|
|
Packit |
0ec9dd |
points[0].y = points[1].y = y + 2;
|
|
Packit |
0ec9dd |
Polyline (hdc, points, 2);
|
|
Packit |
0ec9dd |
break;
|
|
Packit |
0ec9dd |
case PANGO_UNDERLINE_SINGLE:
|
|
Packit |
0ec9dd |
points[0].x = x + PANGO_PIXELS (x_off + ink_rect.x) - 1;
|
|
Packit |
0ec9dd |
points[0].y = points[1].y = y + 2;
|
|
Packit |
0ec9dd |
points[1].x = x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width);
|
|
Packit |
0ec9dd |
Polyline (hdc, points, 2);
|
|
Packit |
0ec9dd |
break;
|
|
Packit |
0ec9dd |
case PANGO_UNDERLINE_ERROR:
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
int point_x;
|
|
Packit |
0ec9dd |
int counter = 0;
|
|
Packit |
0ec9dd |
int end_x = x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
for (point_x = x + PANGO_PIXELS (x_off + ink_rect.x) - 1;
|
|
Packit |
0ec9dd |
point_x <= end_x;
|
|
Packit |
0ec9dd |
point_x += 2)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
points[0].x = point_x;
|
|
Packit |
0ec9dd |
points[1].x = MAX (point_x + 1, end_x);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (counter)
|
|
Packit |
0ec9dd |
points[0].y = points[1].y = y + 2;
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
points[0].y = points[1].y = y + 3;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
Polyline (hdc, points, 2);
|
|
Packit |
0ec9dd |
counter = (counter + 1) % 2;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
break;
|
|
Packit |
0ec9dd |
case PANGO_UNDERLINE_LOW:
|
|
Packit |
0ec9dd |
points[0].x = x + PANGO_PIXELS (x_off + ink_rect.x) - 1;
|
|
Packit |
0ec9dd |
points[0].y = points[1].y = y + PANGO_PIXELS (ink_rect.y + ink_rect.height) + 2;
|
|
Packit |
0ec9dd |
points[1].x = x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width);
|
|
Packit |
0ec9dd |
Polyline (hdc, points, 2);
|
|
Packit |
0ec9dd |
break;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (uline != PANGO_UNDERLINE_NONE)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
SelectObject (hdc, old_pen);
|
|
Packit |
0ec9dd |
DeleteObject (uline_pen);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
x_off += logical_rect.width;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
SetBkMode (hdc, oldbkmode);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/**
|
|
Packit |
0ec9dd |
* pango_win32_render_layout:
|
|
Packit |
0ec9dd |
* @hdc: HDC to use for drawing
|
|
Packit |
0ec9dd |
* @layout: a #PangoLayout
|
|
Packit |
0ec9dd |
* @x: the X position of the left of the layout (in pixels)
|
|
Packit |
0ec9dd |
* @y: the Y position of the top of the layout (in pixels)
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Render a #PangoLayoutLine onto an X drawable
|
|
Packit |
0ec9dd |
*/
|
|
Packit |
0ec9dd |
void
|
|
Packit |
0ec9dd |
pango_win32_render_layout (HDC hdc,
|
|
Packit |
0ec9dd |
PangoLayout *layout,
|
|
Packit |
0ec9dd |
int x,
|
|
Packit |
0ec9dd |
int y)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoLayoutIter *iter;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
g_return_if_fail (hdc != NULL);
|
|
Packit |
0ec9dd |
g_return_if_fail (PANGO_IS_LAYOUT (layout));
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
iter = pango_layout_get_iter (layout);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
do
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoRectangle logical_rect;
|
|
Packit |
0ec9dd |
PangoLayoutLine *line;
|
|
Packit |
0ec9dd |
int baseline;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
line = pango_layout_iter_get_line_readonly (iter);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
|
|
Packit |
0ec9dd |
baseline = pango_layout_iter_get_baseline (iter);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
pango_win32_render_layout_line (hdc,
|
|
Packit |
0ec9dd |
line,
|
|
Packit |
0ec9dd |
x + PANGO_PIXELS (logical_rect.x),
|
|
Packit |
0ec9dd |
y + PANGO_PIXELS (baseline));
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
while (pango_layout_iter_next_line (iter));
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
pango_layout_iter_free (iter);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* This utility function is duplicated here and in pango-layout.c; should it be
|
|
Packit |
0ec9dd |
* public? Trouble is - what is the appropriate set of properties?
|
|
Packit |
0ec9dd |
*/
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
pango_win32_get_item_properties (PangoItem *item,
|
|
Packit |
0ec9dd |
PangoUnderline *uline,
|
|
Packit |
0ec9dd |
PangoAttrColor *uline_color,
|
|
Packit |
0ec9dd |
gboolean *uline_set,
|
|
Packit |
0ec9dd |
PangoAttrColor *fg_color,
|
|
Packit |
0ec9dd |
gboolean *fg_set,
|
|
Packit |
0ec9dd |
PangoAttrColor *bg_color,
|
|
Packit |
0ec9dd |
gboolean *bg_set)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
GSList *tmp_list = item->analysis.extra_attrs;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (fg_set)
|
|
Packit |
0ec9dd |
*fg_set = FALSE;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (bg_set)
|
|
Packit |
0ec9dd |
*bg_set = FALSE;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
while (tmp_list)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoAttribute *attr = tmp_list->data;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
switch (attr->klass->type)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
case PANGO_ATTR_UNDERLINE:
|
|
Packit |
0ec9dd |
if (uline)
|
|
Packit |
0ec9dd |
*uline = ((PangoAttrInt *)attr)->value;
|
|
Packit |
0ec9dd |
break;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
case PANGO_ATTR_UNDERLINE_COLOR:
|
|
Packit |
0ec9dd |
if (uline_color)
|
|
Packit |
0ec9dd |
*uline_color = *((PangoAttrColor *)attr);
|
|
Packit |
0ec9dd |
if (uline_set)
|
|
Packit |
0ec9dd |
*uline_set = TRUE;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
break;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
case PANGO_ATTR_FOREGROUND:
|
|
Packit |
0ec9dd |
if (fg_color)
|
|
Packit |
0ec9dd |
*fg_color = *((PangoAttrColor *)attr);
|
|
Packit |
0ec9dd |
if (fg_set)
|
|
Packit |
0ec9dd |
*fg_set = TRUE;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
break;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
case PANGO_ATTR_BACKGROUND:
|
|
Packit |
0ec9dd |
if (bg_color)
|
|
Packit |
0ec9dd |
*bg_color = *((PangoAttrColor *)attr);
|
|
Packit |
0ec9dd |
if (bg_set)
|
|
Packit |
0ec9dd |
*bg_set = TRUE;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
break;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
default:
|
|
Packit |
0ec9dd |
break;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
tmp_list = tmp_list->next;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static guint
|
|
Packit |
0ec9dd |
get_cmap_offset (HDC hdc,
|
|
Packit |
0ec9dd |
guint16 encoding_id)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
guint16 n_tables;
|
|
Packit |
0ec9dd |
struct cmap_encoding_subtable *table;
|
|
Packit |
0ec9dd |
gint32 res;
|
|
Packit |
0ec9dd |
int i;
|
|
Packit |
0ec9dd |
guint32 offset;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* Get The number of encoding tables, at offset 2 */
|
|
Packit |
0ec9dd |
res = GetFontData (hdc, CMAP, 2, &n_tables, 2);
|
|
Packit |
0ec9dd |
if (res != 2)
|
|
Packit |
0ec9dd |
return 0;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
n_tables = GUINT16_FROM_BE (n_tables);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
table = g_malloc (ENCODING_TABLE_SIZE*n_tables);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
res = GetFontData (hdc, CMAP, CMAP_HEADER_SIZE, table, ENCODING_TABLE_SIZE*n_tables);
|
|
Packit |
0ec9dd |
if (res != ENCODING_TABLE_SIZE*n_tables)
|
|
Packit |
0ec9dd |
return 0;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
for (i = 0; i < n_tables; i++)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
if (table[i].platform_id == GUINT16_TO_BE (MICROSOFT_PLATFORM_ID) &&
|
|
Packit |
0ec9dd |
table[i].encoding_id == GUINT16_TO_BE (encoding_id))
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
offset = GUINT32_FROM_BE (table[i].offset);
|
|
Packit |
0ec9dd |
g_free (table);
|
|
Packit |
0ec9dd |
return offset;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
g_free (table);
|
|
Packit |
0ec9dd |
return 0;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static gpointer
|
|
Packit |
0ec9dd |
get_format_4_cmap (HDC hdc)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
guint32 offset;
|
|
Packit |
0ec9dd |
guint32 res;
|
|
Packit |
0ec9dd |
guint16 length;
|
|
Packit |
0ec9dd |
guint16 *tbl, *tbl_end;
|
|
Packit |
0ec9dd |
struct format_4_cmap *table;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* FIXME: Could look here at the CRC for the font in the DC
|
|
Packit |
0ec9dd |
and return a cached copy if the same */
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
offset = get_cmap_offset (hdc, UNICODE_ENCODING_ID);
|
|
Packit |
0ec9dd |
if (offset == 0)
|
|
Packit |
0ec9dd |
return NULL;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
res = GetFontData (hdc, CMAP, offset + 2, &length, 2);
|
|
Packit |
0ec9dd |
if (res != 2)
|
|
Packit |
0ec9dd |
return NULL;
|
|
Packit |
0ec9dd |
length = GUINT16_FROM_BE (length);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
table = g_malloc (length);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
res = GetFontData (hdc, CMAP, offset, table, length);
|
|
Packit |
0ec9dd |
if (res != length ||
|
|
Packit |
0ec9dd |
GUINT16_FROM_BE (table->format) != 4 ||
|
|
Packit |
0ec9dd |
(GUINT16_FROM_BE (table->length) % 2) != 0)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
g_free (table);
|
|
Packit |
0ec9dd |
return NULL;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
table->format = GUINT16_FROM_BE (table->format);
|
|
Packit |
0ec9dd |
table->length = GUINT16_FROM_BE (table->length);
|
|
Packit |
0ec9dd |
table->language = GUINT16_FROM_BE (table->language);
|
|
Packit |
0ec9dd |
table->seg_count_x_2 = GUINT16_FROM_BE (table->seg_count_x_2);
|
|
Packit |
0ec9dd |
table->search_range = GUINT16_FROM_BE (table->search_range);
|
|
Packit |
0ec9dd |
table->entry_selector = GUINT16_FROM_BE (table->entry_selector);
|
|
Packit |
0ec9dd |
table->range_shift = GUINT16_FROM_BE (table->range_shift);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
tbl_end = (guint16 *)((char *)table + length);
|
|
Packit |
0ec9dd |
tbl = &table->reserved;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
while (tbl < tbl_end)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
*tbl = GUINT16_FROM_BE (*tbl);
|
|
Packit |
0ec9dd |
tbl++;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return table;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static guint16 *
|
|
Packit |
0ec9dd |
get_id_range_offset (struct format_4_cmap *table)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
gint32 seg_count = table->seg_count_x_2/2;
|
|
Packit |
0ec9dd |
return &table->arrays[seg_count*3];
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static guint16 *
|
|
Packit |
0ec9dd |
get_id_delta (struct format_4_cmap *table)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
gint32 seg_count = table->seg_count_x_2/2;
|
|
Packit |
0ec9dd |
return &table->arrays[seg_count*2];
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static guint16 *
|
|
Packit |
0ec9dd |
get_start_count (struct format_4_cmap *table)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
gint32 seg_count = table->seg_count_x_2/2;
|
|
Packit |
0ec9dd |
return &table->arrays[seg_count*1];
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static guint16 *
|
|
Packit |
0ec9dd |
get_end_count (struct format_4_cmap *table)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
gint32 seg_count = table->seg_count_x_2/2;
|
|
Packit |
0ec9dd |
/* Apparently the reseved spot is not reserved for
|
|
Packit |
0ec9dd |
the end_count array!? */
|
|
Packit |
0ec9dd |
return (&table->arrays[seg_count*0])-1;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static gboolean
|
|
Packit |
0ec9dd |
find_segment (struct format_4_cmap *table,
|
|
Packit |
0ec9dd |
guint16 wc,
|
|
Packit |
0ec9dd |
guint16 *segment)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
guint16 start, end, i;
|
|
Packit |
0ec9dd |
guint16 seg_count = table->seg_count_x_2/2;
|
|
Packit |
0ec9dd |
guint16 *end_count = get_end_count (table);
|
|
Packit |
0ec9dd |
guint16 *start_count = get_start_count (table);
|
|
Packit |
0ec9dd |
static guint last = 0; /* Cache of one */ /* MT-safe */
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (last < seg_count &&
|
|
Packit |
0ec9dd |
wc >= start_count[last] &&
|
|
Packit |
0ec9dd |
wc <= end_count[last])
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
*segment = last;
|
|
Packit |
0ec9dd |
return TRUE;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* Binary search for the segment */
|
|
Packit |
0ec9dd |
start = 0; /* inclusive */
|
|
Packit |
0ec9dd |
end = seg_count; /* not inclusive */
|
|
Packit |
0ec9dd |
while (start < end)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
/* Look at middle pos */
|
|
Packit |
0ec9dd |
i = (start + end)/2;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (i == start)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
/* We made no progress. Look if this is the one. */
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (wc >= start_count[i] &&
|
|
Packit |
0ec9dd |
wc <= end_count[i])
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
*segment = i;
|
|
Packit |
0ec9dd |
last = i;
|
|
Packit |
0ec9dd |
return TRUE;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
return FALSE;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
else if (wc < start_count[i])
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
end = i;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
else if (wc > end_count[i])
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
start = i;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
/* Found it! */
|
|
Packit |
0ec9dd |
*segment = i;
|
|
Packit |
0ec9dd |
last = i;
|
|
Packit |
0ec9dd |
return TRUE;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
return FALSE;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static gpointer
|
|
Packit |
0ec9dd |
get_format_12_cmap (HDC hdc)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
guint32 offset;
|
|
Packit |
0ec9dd |
guint32 res;
|
|
Packit |
0ec9dd |
guint32 length;
|
|
Packit |
0ec9dd |
guint32 *tbl, *tbl_end;
|
|
Packit |
0ec9dd |
struct format_12_cmap *table;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
offset = get_cmap_offset (hdc, UCS4_ENCODING_ID);
|
|
Packit |
0ec9dd |
if (offset == 0)
|
|
Packit |
0ec9dd |
return NULL;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
res = GetFontData (hdc, CMAP, offset + 4, &length, 4);
|
|
Packit |
0ec9dd |
if (res != 4)
|
|
Packit |
0ec9dd |
return NULL;
|
|
Packit |
0ec9dd |
length = GUINT32_FROM_BE (length);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
table = g_malloc (length);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
res = GetFontData (hdc, CMAP, offset, table, length);
|
|
Packit |
0ec9dd |
if (res != length)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
g_free (table);
|
|
Packit |
0ec9dd |
return NULL;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
table->format = GUINT16_FROM_BE (table->format);
|
|
Packit |
0ec9dd |
table->length = GUINT32_FROM_BE (table->length);
|
|
Packit |
0ec9dd |
table->language = GUINT32_FROM_BE (table->language);
|
|
Packit |
0ec9dd |
table->count = GUINT32_FROM_BE (table->count);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (table->format != 12 ||
|
|
Packit |
0ec9dd |
(table->length % 4) != 0 ||
|
|
Packit |
0ec9dd |
table->length > length ||
|
|
Packit |
0ec9dd |
table->length < 16 + table->count * 12)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
g_free (table);
|
|
Packit |
0ec9dd |
return NULL;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
tbl_end = (guint32 *) ((char *) table + length);
|
|
Packit |
0ec9dd |
tbl = table->groups;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
while (tbl < tbl_end)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
*tbl = GUINT32_FROM_BE (*tbl);
|
|
Packit |
0ec9dd |
tbl++;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return table;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static gpointer
|
|
Packit |
0ec9dd |
font_get_cmap (PangoFont *font)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoWin32Font *win32font = (PangoWin32Font *)font;
|
|
Packit |
0ec9dd |
gpointer cmap;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (win32font->win32face->cmap)
|
|
Packit |
0ec9dd |
return win32font->win32face->cmap;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
pango_win32_font_select_font (font, _pango_win32_hdc);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* Prefer the format 12 cmap */
|
|
Packit |
0ec9dd |
if ((cmap = get_format_12_cmap (_pango_win32_hdc)) != NULL)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
win32font->win32face->cmap_format = 12;
|
|
Packit |
0ec9dd |
win32font->win32face->cmap = cmap;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
else if ((cmap = get_format_4_cmap (_pango_win32_hdc)) != NULL)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
win32font->win32face->cmap_format = 4;
|
|
Packit |
0ec9dd |
win32font->win32face->cmap = cmap;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
pango_win32_font_done_font (font);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return cmap;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static gint
|
|
Packit |
0ec9dd |
pango_win32_font_get_type1_glyph_index (PangoFont *font,
|
|
Packit |
0ec9dd |
gunichar wc)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
wchar_t unicode[2];
|
|
Packit |
0ec9dd |
WORD glyph_index;
|
|
Packit |
0ec9dd |
gint32 res;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
unicode[0] = wc;
|
|
Packit |
0ec9dd |
unicode[1] = 0;
|
|
Packit |
0ec9dd |
pango_win32_font_select_font (font, _pango_win32_hdc);
|
|
Packit |
0ec9dd |
res = GetGlyphIndicesW (_pango_win32_hdc, unicode, 1, &glyph_index, 0);
|
|
Packit |
0ec9dd |
pango_win32_font_done_font (font);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (res == 1)
|
|
Packit |
0ec9dd |
return glyph_index;
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
return 0;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/**
|
|
Packit |
0ec9dd |
* pango_win32_font_get_glyph_index:
|
|
Packit |
0ec9dd |
* @font: a #PangoFont.
|
|
Packit |
0ec9dd |
* @wc: a Unicode character.
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Obtains the index of the glyph for @wc in @font, or 0, if not
|
|
Packit |
0ec9dd |
* covered.
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Return value: the glyph index for @wc.
|
|
Packit |
0ec9dd |
**/
|
|
Packit |
0ec9dd |
gint
|
|
Packit |
0ec9dd |
pango_win32_font_get_glyph_index (PangoFont *font,
|
|
Packit |
0ec9dd |
gunichar wc)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoWin32Font *win32font = (PangoWin32Font *)font;
|
|
Packit |
0ec9dd |
gpointer cmap;
|
|
Packit |
0ec9dd |
guint16 glyph;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (win32font->win32face->has_cmap)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
/* Do GetFontData magic on font->hfont here. */
|
|
Packit |
0ec9dd |
cmap = font_get_cmap (font);
|
|
Packit |
0ec9dd |
if (cmap == NULL)
|
|
Packit |
0ec9dd |
win32font->win32face->has_cmap = FALSE;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (!win32font->win32face->has_cmap)
|
|
Packit |
0ec9dd |
return pango_win32_font_get_type1_glyph_index (font, wc);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (win32font->win32face->cmap_format == 4)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
struct format_4_cmap *cmap4 = cmap;
|
|
Packit |
0ec9dd |
guint16 *id_range_offset;
|
|
Packit |
0ec9dd |
guint16 *id_delta;
|
|
Packit |
0ec9dd |
guint16 *start_count;
|
|
Packit |
0ec9dd |
guint16 segment;
|
|
Packit |
0ec9dd |
guint16 id;
|
|
Packit |
0ec9dd |
guint16 ch = wc;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (wc > 0xFFFF)
|
|
Packit |
0ec9dd |
return 0;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (!find_segment (cmap4, ch, &segment))
|
|
Packit |
0ec9dd |
return 0;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
id_range_offset = get_id_range_offset (cmap4);
|
|
Packit |
0ec9dd |
id_delta = get_id_delta (cmap4);
|
|
Packit |
0ec9dd |
start_count = get_start_count (cmap4);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (id_range_offset[segment] == 0)
|
|
Packit |
0ec9dd |
glyph = (id_delta[segment] + ch) % 65536;
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
id = *(id_range_offset[segment]/2 +
|
|
Packit |
0ec9dd |
(ch - start_count[segment]) +
|
|
Packit |
0ec9dd |
&id_range_offset[segment]);
|
|
Packit |
0ec9dd |
if (id)
|
|
Packit |
0ec9dd |
glyph = (id_delta[segment] + id) %65536;
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
glyph = 0;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
else if (win32font->win32face->cmap_format == 12)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
struct format_12_cmap *cmap12 = cmap;
|
|
Packit |
0ec9dd |
guint32 i;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
glyph = 0;
|
|
Packit |
0ec9dd |
for (i = 0; i < cmap12->count; i++)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
if (cmap12->groups[i*3+0] <= wc && wc <= cmap12->groups[i*3+1])
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
glyph = cmap12->groups[i*3+2] + (wc - cmap12->groups[i*3+0]);
|
|
Packit |
0ec9dd |
break;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
g_assert_not_reached ();
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return glyph;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
gboolean
|
|
Packit |
0ec9dd |
_pango_win32_get_name_header (HDC hdc,
|
|
Packit |
0ec9dd |
struct name_header *header)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
if (GetFontData (hdc, NAME, 0, header, sizeof (*header)) != sizeof (*header))
|
|
Packit |
0ec9dd |
return FALSE;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
header->num_records = GUINT16_FROM_BE (header->num_records);
|
|
Packit |
0ec9dd |
header->string_storage_offset = GUINT16_FROM_BE (header->string_storage_offset);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return TRUE;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
gboolean
|
|
Packit |
0ec9dd |
_pango_win32_get_name_record (HDC hdc,
|
|
Packit |
0ec9dd |
gint i,
|
|
Packit |
0ec9dd |
struct name_record *record)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
if (GetFontData (hdc, NAME, 6 + i * sizeof (*record),
|
|
Packit |
0ec9dd |
record, sizeof (*record)) != sizeof (*record))
|
|
Packit |
0ec9dd |
return FALSE;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
record->platform_id = GUINT16_FROM_BE (record->platform_id);
|
|
Packit |
0ec9dd |
record->encoding_id = GUINT16_FROM_BE (record->encoding_id);
|
|
Packit |
0ec9dd |
record->language_id = GUINT16_FROM_BE (record->language_id);
|
|
Packit |
0ec9dd |
record->name_id = GUINT16_FROM_BE (record->name_id);
|
|
Packit |
0ec9dd |
record->string_length = GUINT16_FROM_BE (record->string_length);
|
|
Packit |
0ec9dd |
record->string_offset = GUINT16_FROM_BE (record->string_offset);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return TRUE;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static gboolean
|
|
Packit |
0ec9dd |
font_has_name_in (PangoFont *font,
|
|
Packit |
0ec9dd |
PangoWin32CoverageLanguageClass cjkv)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
HFONT hfont, oldhfont;
|
|
Packit |
0ec9dd |
struct name_header header;
|
|
Packit |
0ec9dd |
struct name_record record;
|
|
Packit |
0ec9dd |
gint i;
|
|
Packit |
0ec9dd |
gboolean retval = FALSE;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (cjkv == PANGO_WIN32_COVERAGE_UNSPEC)
|
|
Packit |
0ec9dd |
return TRUE;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
hfont = _pango_win32_font_get_hfont (font);
|
|
Packit |
0ec9dd |
oldhfont = SelectObject (_pango_win32_hdc, hfont);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (!_pango_win32_get_name_header (_pango_win32_hdc, &header))
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
SelectObject (_pango_win32_hdc, oldhfont);
|
|
Packit |
0ec9dd |
return FALSE;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
for (i = 0; i < header.num_records; i++)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
if (!_pango_win32_get_name_record (_pango_win32_hdc, i, &record))
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
SelectObject (_pango_win32_hdc, oldhfont);
|
|
Packit |
0ec9dd |
return FALSE;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if ((record.name_id != 1 && record.name_id != 16) || record.string_length <= 0)
|
|
Packit |
0ec9dd |
continue;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
PING (("platform:%d encoding:%d language:%04x name_id:%d",
|
|
Packit |
0ec9dd |
record.platform_id, record.encoding_id, record.language_id, record.name_id));
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (record.platform_id == MICROSOFT_PLATFORM_ID)
|
|
Packit |
0ec9dd |
if ((cjkv == PANGO_WIN32_COVERAGE_ZH_TW &&
|
|
Packit |
0ec9dd |
record.language_id == MAKELANGID (LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL))
|
|
Packit |
0ec9dd |
||
|
|
Packit |
0ec9dd |
(cjkv == PANGO_WIN32_COVERAGE_ZH_CN &&
|
|
Packit |
0ec9dd |
record.language_id == MAKELANGID (LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED))
|
|
Packit |
0ec9dd |
||
|
|
Packit |
0ec9dd |
(cjkv == PANGO_WIN32_COVERAGE_JA &&
|
|
Packit |
0ec9dd |
PRIMARYLANGID (record.language_id) == LANG_JAPANESE)
|
|
Packit |
0ec9dd |
||
|
|
Packit |
0ec9dd |
(cjkv == PANGO_WIN32_COVERAGE_KO &&
|
|
Packit |
0ec9dd |
PRIMARYLANGID (record.language_id) == LANG_KOREAN)
|
|
Packit |
0ec9dd |
||
|
|
Packit |
0ec9dd |
(cjkv == PANGO_WIN32_COVERAGE_VI &&
|
|
Packit |
0ec9dd |
PRIMARYLANGID (record.language_id) == LANG_VIETNAMESE))
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PING (("yep:%d:%04x", cjkv, record.language_id));
|
|
Packit |
0ec9dd |
retval = TRUE;
|
|
Packit |
0ec9dd |
break;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
SelectObject (_pango_win32_hdc, oldhfont);
|
|
Packit |
0ec9dd |
return retval;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
pango_win32_font_calc_type1_coverage (PangoFont *font,
|
|
Packit |
0ec9dd |
PangoCoverage *coverage,
|
|
Packit |
0ec9dd |
PangoLanguage *lang)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
GLYPHSET *glyph_set;
|
|
Packit |
0ec9dd |
gint32 res;
|
|
Packit |
0ec9dd |
guint32 ch;
|
|
Packit |
0ec9dd |
guint32 i;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
pango_win32_font_select_font (font, _pango_win32_hdc);
|
|
Packit |
0ec9dd |
res = GetFontUnicodeRanges(_pango_win32_hdc, NULL);
|
|
Packit |
0ec9dd |
if (res == 0)
|
|
Packit |
0ec9dd |
goto fail1;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
glyph_set = g_malloc (res);
|
|
Packit |
0ec9dd |
res = GetFontUnicodeRanges(_pango_win32_hdc, glyph_set);
|
|
Packit |
0ec9dd |
if (res == 0)
|
|
Packit |
0ec9dd |
goto fail2;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
for (i = 0; i < glyph_set->cRanges; i++)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
guint32 end = glyph_set->ranges[i].wcLow + glyph_set->ranges[i].cGlyphs;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
for (ch = glyph_set->ranges[i].wcLow; ch < end; ch++)
|
|
Packit |
0ec9dd |
if (CH_IS_UNIHAN_BMP (ch))
|
|
Packit |
0ec9dd |
pango_coverage_set (coverage, ch, PANGO_COVERAGE_APPROXIMATE);
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
pango_coverage_set (coverage, ch, PANGO_COVERAGE_EXACT);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
fail2:
|
|
Packit |
0ec9dd |
g_free (glyph_set);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
fail1:
|
|
Packit |
0ec9dd |
pango_win32_font_done_font (font);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
pango_win32_font_calc_coverage (PangoFont *font,
|
|
Packit |
0ec9dd |
PangoCoverage *coverage,
|
|
Packit |
0ec9dd |
PangoLanguage *lang)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoWin32Font *win32font = (PangoWin32Font *)font;
|
|
Packit |
0ec9dd |
gpointer cmap;
|
|
Packit |
0ec9dd |
guint32 ch;
|
|
Packit |
0ec9dd |
guint32 i;
|
|
Packit |
0ec9dd |
PangoWin32CoverageLanguageClass cjkv;
|
|
Packit |
0ec9dd |
gboolean hide_unihan = FALSE;
|
|
Packit |
0ec9dd |
PangoFontDescription *desc;
|
|
Packit |
0ec9dd |
gchar *name;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
desc = pango_font_describe (font);
|
|
Packit |
0ec9dd |
name = pango_font_description_to_string (desc);
|
|
Packit |
0ec9dd |
PING (("font:%s lang:%s", name,
|
|
Packit |
0ec9dd |
pango_language_to_string (lang)));
|
|
Packit |
0ec9dd |
g_free (name);
|
|
Packit |
0ec9dd |
pango_font_description_free (desc);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (win32font->win32face->has_cmap)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
/* Do GetFontData magic on font->hfont here. */
|
|
Packit |
0ec9dd |
cmap = font_get_cmap (font);
|
|
Packit |
0ec9dd |
if (cmap == NULL)
|
|
Packit |
0ec9dd |
win32font->win32face->has_cmap = FALSE;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (!win32font->win32face->has_cmap)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
pango_win32_font_calc_type1_coverage (font, coverage, lang);
|
|
Packit |
0ec9dd |
return;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
cjkv = pango_win32_coverage_language_classify (lang);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (cjkv != PANGO_WIN32_COVERAGE_UNSPEC && !font_has_name_in (font, cjkv))
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PING (("hiding UniHan chars"));
|
|
Packit |
0ec9dd |
hide_unihan = TRUE;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
PING (("coverage:"));
|
|
Packit |
0ec9dd |
if (win32font->win32face->cmap_format == 4)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
struct format_4_cmap *cmap4 = cmap;
|
|
Packit |
0ec9dd |
guint16 *id_range_offset;
|
|
Packit |
0ec9dd |
guint16 *start_count;
|
|
Packit |
0ec9dd |
guint16 *end_count;
|
|
Packit |
0ec9dd |
guint16 seg_count;
|
|
Packit |
0ec9dd |
guint16 id;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
seg_count = cmap4->seg_count_x_2/2;
|
|
Packit |
0ec9dd |
end_count = get_end_count (cmap4);
|
|
Packit |
0ec9dd |
start_count = get_start_count (cmap4);
|
|
Packit |
0ec9dd |
id_range_offset = get_id_range_offset (cmap4);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
for (i = 0; i < seg_count; i++)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
if (id_range_offset[i] == 0)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
#ifdef PANGO_WIN32_DEBUGGING
|
|
Packit |
0ec9dd |
if (_pango_win32_debug)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
if (end_count[i] == start_count[i])
|
|
Packit |
0ec9dd |
g_print ("%04x ", start_count[i]);
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
g_print ("%04x:%04x ", start_count[i], end_count[i]);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
#endif
|
|
Packit |
0ec9dd |
for (ch = start_count[i]; ch <= end_count[i]; ch++)
|
|
Packit |
0ec9dd |
if (hide_unihan && CH_IS_UNIHAN_BMP (ch))
|
|
Packit |
0ec9dd |
pango_coverage_set (coverage, ch, PANGO_COVERAGE_APPROXIMATE);
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
pango_coverage_set (coverage, ch, PANGO_COVERAGE_EXACT);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
#ifdef PANGO_WIN32_DEBUGGING
|
|
Packit |
0ec9dd |
guint32 ch0 = G_MAXUINT;
|
|
Packit |
0ec9dd |
#endif
|
|
Packit |
0ec9dd |
for (ch = start_count[i]; ch <= end_count[i]; ch++)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
if (ch == 0xFFFF)
|
|
Packit |
0ec9dd |
break;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
id = *(id_range_offset[i]/2 +
|
|
Packit |
0ec9dd |
(ch - start_count[i]) +
|
|
Packit |
0ec9dd |
&id_range_offset[i]);
|
|
Packit |
0ec9dd |
if (id)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
#ifdef PANGO_WIN32_DEBUGGING
|
|
Packit |
0ec9dd |
if (ch0 == G_MAXUINT)
|
|
Packit |
0ec9dd |
ch0 = ch;
|
|
Packit |
0ec9dd |
#endif
|
|
Packit |
0ec9dd |
if (hide_unihan && CH_IS_UNIHAN_BMP (ch))
|
|
Packit |
0ec9dd |
pango_coverage_set (coverage, ch, PANGO_COVERAGE_APPROXIMATE);
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
pango_coverage_set (coverage, ch, PANGO_COVERAGE_EXACT);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
#ifdef PANGO_WIN32_DEBUGGING
|
|
Packit |
0ec9dd |
else if (ch0 < G_MAXUINT)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
if (_pango_win32_debug)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
if (ch > ch0 + 2)
|
|
Packit |
0ec9dd |
g_print ("%04x:%04x ", ch0, ch - 1);
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
g_print ("%04x ", ch0);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
ch0 = G_MAXUINT;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
#endif
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
#ifdef PANGO_WIN32_DEBUGGING
|
|
Packit |
0ec9dd |
if (ch0 < G_MAXUINT)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
if (_pango_win32_debug)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
if (ch > ch0 + 2)
|
|
Packit |
0ec9dd |
g_print ("%04x:%04x ", ch0, ch - 1);
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
g_print ("%04x ", ch0);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
#endif
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
else if (win32font->win32face->cmap_format == 12)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
struct format_12_cmap *cmap12 = cmap;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
for (i = 0; i < cmap12->count; i++)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
#ifdef PANGO_WIN32_DEBUGGING
|
|
Packit |
0ec9dd |
if (_pango_win32_debug)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
if (cmap12->groups[i*3+0] == cmap12->groups[i*3+1])
|
|
Packit |
0ec9dd |
g_print ("%04x ", cmap12->groups[i*3+0]);
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
g_print ("%04x:%04x ", cmap12->groups[i*3+0], cmap12->groups[i*3+1]);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
#endif
|
|
Packit |
0ec9dd |
for (ch = cmap12->groups[i*3+0]; ch <= cmap12->groups[i*3+1]; ch++)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
if (hide_unihan && CH_IS_UNIHAN (ch))
|
|
Packit |
0ec9dd |
pango_coverage_set (coverage, ch, PANGO_COVERAGE_APPROXIMATE);
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
pango_coverage_set (coverage, ch, PANGO_COVERAGE_EXACT);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
else
|
|
Packit |
0ec9dd |
g_assert_not_reached ();
|
|
Packit |
0ec9dd |
#ifdef PANGO_WIN32_DEBUGGING
|
|
Packit |
0ec9dd |
if (_pango_win32_debug)
|
|
Packit |
0ec9dd |
g_print ("\n");
|
|
Packit |
0ec9dd |
#endif
|
|
Packit |
0ec9dd |
}
|