⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cairo-win32-font.c

📁 按照官方的说法:Cairo is a vector graphics library with cross-device output support. 翻译过来
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (!GetOutlineTextMetrics (hdc, otm_size, otm)) {	    _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics");	    free (otm);	    return NULL;	}	scaled_font->em_square = otm->otmEMSquare;	free (otm);	logfont = scaled_font->logfont;	logfont.lfHeight = -scaled_font->em_square;	logfont.lfWidth = 0;	logfont.lfEscapement = 0;	logfont.lfOrientation = 0;	logfont.lfQuality = scaled_font->quality;	scaled_font->unscaled_hfont = CreateFontIndirectW (&logfont);	if (!scaled_font->unscaled_hfont) {	    _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:CreateIndirect");	    return NULL;	}    }    return scaled_font->unscaled_hfont;}static cairo_status_t_cairo_win32_scaled_font_select_unscaled_font (cairo_scaled_font_t *scaled_font,					       HDC                  hdc){    cairo_status_t status;    HFONT hfont;    HFONT old_hfont = NULL;    hfont = _win32_scaled_font_get_unscaled_hfont ((cairo_win32_scaled_font_t *)scaled_font, hdc);    if (!hfont)	return CAIRO_STATUS_NO_MEMORY;    old_hfont = SelectObject (hdc, hfont);    if (!old_hfont)	return _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_select_unscaled_font");    status = _win32_scaled_font_set_identity_transform (hdc);    if (status) {	SelectObject (hdc, old_hfont);	return status;    }    SetMapMode (hdc, MM_TEXT);    return CAIRO_STATUS_SUCCESS;}static void_cairo_win32_scaled_font_done_unscaled_font (cairo_scaled_font_t *scaled_font){}/* implement the font backend interface */static cairo_status_t_cairo_win32_scaled_font_create_toy (cairo_toy_font_face_t *toy_face,				     const cairo_matrix_t        *font_matrix,				     const cairo_matrix_t        *ctm,				     const cairo_font_options_t  *options,				     cairo_scaled_font_t        **scaled_font_out){    LOGFONTW logfont;    cairo_scaled_font_t *scaled_font;    uint16_t *face_name;    int face_name_len;    cairo_status_t status;    status = _cairo_utf8_to_utf16 (toy_face->family, -1,				   &face_name, &face_name_len);    if (status)	return status;    if (face_name_len > LF_FACESIZE - 1) {	free (face_name);	return CAIRO_STATUS_INVALID_STRING;    }    memcpy (logfont.lfFaceName, face_name, sizeof (uint16_t) * (face_name_len + 1));    free (face_name);    logfont.lfHeight = 0;	/* filled in later */    logfont.lfWidth = 0;	/* filled in later */    logfont.lfEscapement = 0;	/* filled in later */    logfont.lfOrientation = 0;	/* filled in later */    switch (toy_face->weight) {    case CAIRO_FONT_WEIGHT_NORMAL:    default:	logfont.lfWeight = FW_NORMAL;	break;    case CAIRO_FONT_WEIGHT_BOLD:	logfont.lfWeight = FW_BOLD;	break;    }    switch (toy_face->slant) {    case CAIRO_FONT_SLANT_NORMAL:    default:	logfont.lfItalic = FALSE;	break;    case CAIRO_FONT_SLANT_ITALIC:    case CAIRO_FONT_SLANT_OBLIQUE:	logfont.lfItalic = TRUE;	break;    }    logfont.lfUnderline = FALSE;    logfont.lfStrikeOut = FALSE;    /* The docs for LOGFONT discourage using this, since the     * interpretation is locale-specific, but it's not clear what     * would be a better alternative.     */    logfont.lfCharSet = DEFAULT_CHARSET;    logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;    logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;    logfont.lfQuality = DEFAULT_QUALITY; /* filled in later */    logfont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;    if (!logfont.lfFaceName)	return CAIRO_STATUS_NO_MEMORY;    scaled_font = _win32_scaled_font_create (&logfont, NULL, &toy_face->base,					     font_matrix, ctm, options);    if (!scaled_font)	return CAIRO_STATUS_NO_MEMORY;    *scaled_font_out = scaled_font;    return CAIRO_STATUS_SUCCESS;}static void_cairo_win32_scaled_font_fini (void *abstract_font){    cairo_win32_scaled_font_t *scaled_font = abstract_font;    if (scaled_font == NULL)	return;    if (scaled_font->scaled_hfont && scaled_font->delete_scaled_hfont)	DeleteObject (scaled_font->scaled_hfont);    if (scaled_font->unscaled_hfont)	DeleteObject (scaled_font->unscaled_hfont);}static cairo_int_status_t_cairo_win32_scaled_font_text_to_glyphs (void		*abstract_font,					 double		x,					 double		y,					 const char	*utf8,					 cairo_glyph_t **glyphs,					 int		*num_glyphs){    cairo_win32_scaled_font_t *scaled_font = abstract_font;    uint16_t *utf16;    int n16;    GCP_RESULTSW gcp_results;    unsigned int buffer_size, i;    WCHAR *glyph_indices = NULL;    int *dx = NULL;    cairo_status_t status = CAIRO_STATUS_SUCCESS;    double x_pos, y_pos;    double x_incr, y_incr;    HDC hdc = NULL;    /* Compute a vector in user space along the baseline of length one logical space unit */    x_incr = 1;    y_incr = 0;    cairo_matrix_transform_distance (&scaled_font->base.font_matrix, &x_incr, &y_incr);    x_incr /= scaled_font->logical_scale;    y_incr /= scaled_font->logical_scale;    status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16);    if (status)	return status;    gcp_results.lStructSize = sizeof (GCP_RESULTS);    gcp_results.lpOutString = NULL;    gcp_results.lpOrder = NULL;    gcp_results.lpCaretPos = NULL;    gcp_results.lpClass = NULL;    buffer_size = MAX (n16 * 1.2, 16);		/* Initially guess number of chars plus a few */    if (buffer_size > INT_MAX) {	status = CAIRO_STATUS_NO_MEMORY;	goto FAIL1;    }    hdc = _get_global_font_dc ();    if (!hdc) {	status = CAIRO_STATUS_NO_MEMORY;	goto FAIL1;    }    status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);    if (status)	goto FAIL1;    while (TRUE) {	if (glyph_indices) {	    free (glyph_indices);	    glyph_indices = NULL;	}	if (dx) {	    free (dx);	    dx = NULL;	}	glyph_indices = malloc (sizeof (WCHAR) * buffer_size);	dx = malloc (sizeof (int) * buffer_size);	if (!glyph_indices || !dx) {	    status = CAIRO_STATUS_NO_MEMORY;	    goto FAIL2;	}	gcp_results.nGlyphs = buffer_size;	gcp_results.lpDx = dx;	gcp_results.lpGlyphs = glyph_indices;	if (!GetCharacterPlacementW (hdc, utf16, n16,				     0,				     &gcp_results,				     GCP_DIACRITIC | GCP_LIGATE | GCP_GLYPHSHAPE | GCP_REORDER)) {	    status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_text_to_glyphs");	    goto FAIL2;	}	if (gcp_results.lpDx && gcp_results.lpGlyphs)	    break;	/* Too small a buffer, try again */	buffer_size *= 1.5;	if (buffer_size > INT_MAX) {	    status = CAIRO_STATUS_NO_MEMORY;	    goto FAIL2;	}    }    *num_glyphs = gcp_results.nGlyphs;    *glyphs = malloc (sizeof (cairo_glyph_t) * gcp_results.nGlyphs);    if (!*glyphs) {	status = CAIRO_STATUS_NO_MEMORY;	goto FAIL2;    }    x_pos = x;    y_pos = y;    for (i = 0; i < gcp_results.nGlyphs; i++) {	(*glyphs)[i].index = glyph_indices[i];	(*glyphs)[i].x = x_pos ;	(*glyphs)[i].y = y_pos;	x_pos += x_incr * dx[i];	y_pos += y_incr * dx[i];    } FAIL2:    if (glyph_indices)	free (glyph_indices);    if (dx)	free (dx);    cairo_win32_scaled_font_done_font (&scaled_font->base); FAIL1:    free (utf16);    return status;}static cairo_status_t_cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font){    cairo_status_t status;    cairo_font_extents_t extents;    TEXTMETRIC metrics;    HDC hdc;    hdc = _get_global_font_dc ();    if (!hdc)	return CAIRO_STATUS_NO_MEMORY;    if (scaled_font->preserve_axes) {	/* For 90-degree rotations (including 0), we get the metrics	 * from the GDI in logical space, then convert back to font space	 */	status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);	if (status)	    return status;	GetTextMetrics (hdc, &metrics);	cairo_win32_scaled_font_done_font (&scaled_font->base);	extents.ascent = metrics.tmAscent / scaled_font->logical_scale;	extents.descent = metrics.tmDescent / scaled_font->logical_scale;	extents.height = (metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->logical_scale;	extents.max_x_advance = metrics.tmMaxCharWidth / scaled_font->logical_scale;	extents.max_y_advance = 0;    } else {	/* For all other transformations, we use the design metrics	 * of the font. The GDI results from GetTextMetrics() on a	 * transformed font are inexplicably large and we want to	 * avoid them.	 */	status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);	if (status)	    return status;	GetTextMetrics (hdc, &metrics);	_cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);	extents.ascent = (double)metrics.tmAscent / scaled_font->em_square;	extents.descent = metrics.tmDescent * scaled_font->em_square;	extents.height = (double)(metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->em_square;	extents.max_x_advance = (double)(metrics.tmMaxCharWidth) / scaled_font->em_square;	extents.max_y_advance = 0;    }    _cairo_scaled_font_set_metrics (&scaled_font->base, &extents);    return CAIRO_STATUS_SUCCESS;}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 const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } };    GLYPHMETRICS metrics;    cairo_status_t status;    cairo_text_extents_t extents;    HDC hdc;    hdc = _get_global_font_dc ();    if (!hdc)	return CAIRO_STATUS_NO_MEMORY;    if (scaled_font->preserve_axes) {	/* If we aren't rotating / skewing the axes, then we get the metrics	 * from the GDI in device space and convert to font space.	 */	status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);	if (status)	    return status;	if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),			      GGO_METRICS | GGO_GLYPH_INDEX,			      &metrics, 0, NULL, &matrix) == GDI_ERROR) {	  status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW");	  memset (&metrics, 0, sizeof (GLYPHMETRICS));	}	cairo_win32_scaled_font_done_font (&scaled_font->base);	if (scaled_font->swap_axes) {	    extents.x_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale;	    extents.y_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale;	    extents.width = metrics.gmBlackBoxY / scaled_font->y_scale;	    extents.height = metrics.gmBlackBoxX / scaled_font->x_scale;	    extents.x_advance = metrics.gmCellIncY / scaled_font->x_scale;	    extents.y_advance = metrics.gmCellIncX / scaled_font->y_scale;	} else {	    extents.x_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale;	    extents.y_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale;	    extents.width = metrics.gmBlackBoxX / scaled_font->x_scale;	    extents.height = metrics.gmBlackBoxY / scaled_font->y_scale;	    extents.x_advance = metrics.gmCellIncX / scaled_font->x_scale;	    extents.y_advance = metrics.gmCellIncY / scaled_font->y_scale;	}	if (scaled_font->swap_x) {	    extents.x_bearing = (- extents.x_bearing - extents.width);	    extents.x_advance = - extents.x_advance;	}	if (scaled_font->swap_y) {	    extents.y_bearing = (- extents.y_bearing - extents.height);	    extents.y_advance = - extents.y_advance;	}    } else {	/* For all other transformations, we use the design metrics

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -