📄 cairo-win32-font.c
字号:
/* cairo - a vector graphics library with display and print output * * Copyright © 2005 Red Hat, Inc * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public * License version 2.1 as published by the Free Software Foundation * (the "LGPL") or, at your option, under the terms of the Mozilla * Public License Version 1.1 (the "MPL"). If you do not alter this * notice, a recipient may use your version of this file under either * the MPL or the LGPL. * * You should have received a copy of the LGPL along with this library * in the file COPYING-LGPL-2.1; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * You should have received a copy of the MPL along with this library * in the file COPYING-MPL-1.1 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY * OF ANY KIND, either express or implied. See the LGPL or the MPL for * the specific language governing rights and limitations. * * The Original Code is the cairo graphics library. * * The Initial Developer of the Original Code is Red Hat, Inc. * * Contributor(s): */#include <string.h>#include <stdio.h>#include "cairoint.h"#include "cairo-win32-private.h"#ifndef SPI_GETFONTSMOOTHINGTYPE#define SPI_GETFONTSMOOTHINGTYPE 0x200a#endif#ifndef FE_FONTSMOOTHINGCLEARTYPE#define FE_FONTSMOOTHINGCLEARTYPE 2#endif#ifndef CLEARTYPE_QUALITY#define CLEARTYPE_QUALITY 5#endif#ifndef TT_PRIM_CSPLINE#define TT_PRIM_CSPLINE 3#endifconst cairo_scaled_font_backend_t cairo_win32_scaled_font_backend;typedef struct { cairo_scaled_font_t base; LOGFONTW logfont; BYTE quality; /* We do drawing and metrics computation in a "logical space" which * is similar to font space, except that it is scaled by a factor * of the (desired font size) * (WIN32_FONT_LOGICAL_SCALE). The multiplication * by WIN32_FONT_LOGICAL_SCALE allows for sub-pixel precision. */ double logical_scale; /* The size we should actually request the font at from Windows; differs * from the logical_scale because it is quantized for orthogonal * transformations */ double logical_size; /* Transformations from device <=> logical space */ cairo_matrix_t logical_to_device; cairo_matrix_t device_to_logical; /* We special case combinations of 90-degree-rotations, scales and * flips ... that is transformations that take the axes to the * axes. If preserve_axes is true, then swap_axes/swap_x/swap_y * encode the 8 possibilities for orientation (4 rotation angles with * and without a flip), and scale_x, scale_y the scale components. */ cairo_bool_t preserve_axes; cairo_bool_t swap_axes; cairo_bool_t swap_x; cairo_bool_t swap_y; double x_scale; double y_scale; /* The size of the design unit of the font */ int em_square; HFONT scaled_hfont; HFONT unscaled_hfont; cairo_bool_t delete_scaled_hfont;} cairo_win32_scaled_font_t;static cairo_status_t_cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font);static cairo_status_t_cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph);static cairo_status_t_cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph);#define NEARLY_ZERO(d) (fabs(d) < (1. / 65536.))static void_compute_transform (cairo_win32_scaled_font_t *scaled_font, cairo_matrix_t *sc){ cairo_status_t status; if (NEARLY_ZERO (sc->yx) && NEARLY_ZERO (sc->xy)) { scaled_font->preserve_axes = TRUE; scaled_font->x_scale = sc->xx; scaled_font->swap_x = (sc->xx < 0); scaled_font->y_scale = sc->yy; scaled_font->swap_y = (sc->yy < 0); scaled_font->swap_axes = FALSE; } else if (NEARLY_ZERO (sc->xx) && NEARLY_ZERO (sc->yy)) { scaled_font->preserve_axes = TRUE; scaled_font->x_scale = sc->yx; scaled_font->swap_x = (sc->yx < 0); scaled_font->y_scale = sc->xy; scaled_font->swap_y = (sc->xy < 0); scaled_font->swap_axes = TRUE; } else { scaled_font->preserve_axes = FALSE; scaled_font->swap_x = scaled_font->swap_y = scaled_font->swap_axes = FALSE; } if (scaled_font->preserve_axes) { if (scaled_font->swap_x) scaled_font->x_scale = - scaled_font->x_scale; if (scaled_font->swap_y) scaled_font->y_scale = - scaled_font->y_scale; scaled_font->logical_scale = WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale; scaled_font->logical_size = WIN32_FONT_LOGICAL_SCALE * floor (scaled_font->y_scale + 0.5); } /* The font matrix has x and y "scale" components which we extract and * use as character scale values. */ cairo_matrix_init (&scaled_font->logical_to_device, sc->xx, sc->yx, sc->xy, sc->yy, 0, 0); if (!scaled_font->preserve_axes) { _cairo_matrix_compute_scale_factors (&scaled_font->logical_to_device, &scaled_font->x_scale, &scaled_font->y_scale, TRUE); /* XXX: Handle vertical text */ scaled_font->logical_size = floor (WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale + 0.5); scaled_font->logical_scale = WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale; } cairo_matrix_scale (&scaled_font->logical_to_device, 1.0 / scaled_font->logical_scale, 1.0 / scaled_font->logical_scale); scaled_font->device_to_logical = scaled_font->logical_to_device; status = cairo_matrix_invert (&scaled_font->device_to_logical); if (status) cairo_matrix_init_identity (&scaled_font->device_to_logical);}static cairo_bool_t_have_cleartype_quality (void){ OSVERSIONINFO version_info; version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); if (!GetVersionEx (&version_info)) { _cairo_win32_print_gdi_error ("_have_cleartype_quality"); return FALSE; } return (version_info.dwMajorVersion > 5 || (version_info.dwMajorVersion == 5 && version_info.dwMinorVersion >= 1)); /* XP or newer */}static BYTE_get_system_quality (void){ BOOL font_smoothing; UINT smoothing_type; if (!SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0)) { _cairo_win32_print_gdi_error ("_get_system_quality"); return DEFAULT_QUALITY; } if (font_smoothing) { if (_have_cleartype_quality ()) { if (!SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE, 0, &smoothing_type, 0)) { _cairo_win32_print_gdi_error ("_get_system_quality"); return DEFAULT_QUALITY; } if (smoothing_type == FE_FONTSMOOTHINGCLEARTYPE) return CLEARTYPE_QUALITY; } return ANTIALIASED_QUALITY; } else { return DEFAULT_QUALITY; }}static cairo_scaled_font_t *_win32_scaled_font_create (LOGFONTW *logfont, HFONT hfont, cairo_font_face_t *font_face, const cairo_matrix_t *font_matrix, const cairo_matrix_t *ctm, const cairo_font_options_t *options){ cairo_win32_scaled_font_t *f; cairo_matrix_t scale; cairo_status_t status; f = malloc (sizeof(cairo_win32_scaled_font_t)); if (f == NULL) return NULL; f->logfont = *logfont; /* We don't have any control over the hinting style or subpixel * order in the Win32 font API, so we ignore those parts of * cairo_font_options_t. We use the 'antialias' field to set * the 'quality'. * * XXX: The other option we could pay attention to, but don't * here is the hint_metrics options. */ if (options->antialias == CAIRO_ANTIALIAS_DEFAULT) f->quality = _get_system_quality (); else { switch (options->antialias) { case CAIRO_ANTIALIAS_NONE: f->quality = NONANTIALIASED_QUALITY; break; case CAIRO_ANTIALIAS_GRAY: f->quality = ANTIALIASED_QUALITY; break; case CAIRO_ANTIALIAS_SUBPIXEL: if (_have_cleartype_quality ()) f->quality = CLEARTYPE_QUALITY; else f->quality = ANTIALIASED_QUALITY; break; case CAIRO_ANTIALIAS_DEFAULT: ASSERT_NOT_REACHED; } } f->em_square = 0; f->scaled_hfont = hfont; f->unscaled_hfont = NULL; /* don't delete the hfont if it was passed in to us */ f->delete_scaled_hfont = !hfont; cairo_matrix_multiply (&scale, font_matrix, ctm); _compute_transform (f, &scale); _cairo_scaled_font_init (&f->base, font_face, font_matrix, ctm, options, &cairo_win32_scaled_font_backend); status = _cairo_win32_scaled_font_set_metrics (f); if (status) { cairo_scaled_font_destroy (&f->base); return NULL; } return &f->base;}static cairo_status_t_win32_scaled_font_set_world_transform (cairo_win32_scaled_font_t *scaled_font, HDC hdc){ XFORM xform; xform.eM11 = scaled_font->logical_to_device.xx; xform.eM21 = scaled_font->logical_to_device.xy; xform.eM12 = scaled_font->logical_to_device.yx; xform.eM22 = scaled_font->logical_to_device.yy; xform.eDx = scaled_font->logical_to_device.x0; xform.eDy = scaled_font->logical_to_device.y0; if (!SetWorldTransform (hdc, &xform)) return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform"); return CAIRO_STATUS_SUCCESS;}static cairo_status_t_win32_scaled_font_set_identity_transform (HDC hdc){ if (!ModifyWorldTransform (hdc, NULL, MWT_IDENTITY)) return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_identity_transform"); return CAIRO_STATUS_SUCCESS;}static HDC_get_global_font_dc (void){ static HDC hdc; if (!hdc) { hdc = CreateCompatibleDC (NULL); if (!hdc) { _cairo_win32_print_gdi_error ("_get_global_font_dc"); return NULL; } if (!SetGraphicsMode (hdc, GM_ADVANCED)) { _cairo_win32_print_gdi_error ("_get_global_font_dc"); DeleteDC (hdc); return NULL; } } return hdc;}static HFONT_win32_scaled_font_get_scaled_hfont (cairo_win32_scaled_font_t *scaled_font){ if (!scaled_font->scaled_hfont) { LOGFONTW logfont = scaled_font->logfont; logfont.lfHeight = -scaled_font->logical_size; logfont.lfWidth = 0; logfont.lfEscapement = 0; logfont.lfOrientation = 0; logfont.lfQuality = scaled_font->quality; scaled_font->scaled_hfont = CreateFontIndirectW (&logfont); if (!scaled_font->scaled_hfont) { _cairo_win32_print_gdi_error ("_win32_scaled_font_get_scaled_hfont"); return NULL; } } return scaled_font->scaled_hfont;}static HFONT_win32_scaled_font_get_unscaled_hfont (cairo_win32_scaled_font_t *scaled_font, HDC hdc){ if (!scaled_font->unscaled_hfont) { OUTLINETEXTMETRIC *otm; unsigned int otm_size; HFONT scaled_hfont; LOGFONTW logfont; scaled_hfont = _win32_scaled_font_get_scaled_hfont (scaled_font); if (!scaled_hfont) return NULL; if (!SelectObject (hdc, scaled_hfont)) { _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:SelectObject"); return NULL; } otm_size = GetOutlineTextMetrics (hdc, 0, NULL); if (!otm_size) { _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics"); return NULL; } otm = malloc (otm_size); if (!otm) return NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -