示例#1
0
/**
 * cairo_quartz_font_face_create_for_cgfont
 * @font: a #CGFontRef obtained through a method external to cairo.
 *
 * Creates a new font for the Quartz font backend based on a
 * #CGFontRef.  This font can then be used with
 * cairo_set_font_face() or cairo_scaled_font_create().
 *
 * Return value: a newly created #cairo_font_face_t. Free with
 *  cairo_font_face_destroy() when you are done using it.
 *
 * Since: 1.6
 */
cairo_font_face_t *
cairo_quartz_font_face_create_for_cgfont (CGFontRef font)
{
    cairo_quartz_font_face_t *font_face;

    quartz_font_ensure_symbols();

    font_face = malloc (sizeof (cairo_quartz_font_face_t));
    if (!font_face) {
	cairo_status_t ignore_status;
	ignore_status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
	return (cairo_font_face_t *)&_cairo_font_face_nil;
    }

    font_face->cgFont = CGFontRetain (font);

    if (CTFontCreateWithGraphicsFontPtr) {
        font_face->ctFont = CTFontCreateWithGraphicsFontPtr (font, 1.0, NULL, NULL);
    } else {
        font_face->ctFont = NULL;
    }

    _cairo_font_face_init (&font_face->base, &_cairo_quartz_font_face_backend);

    return &font_face->base;
}
/**
 * cairo_quartz_font_face_create_for_cgfont
 * @font: a #CGFontRef obtained through a method external to cairo.
 *
 * Creates a new font for the Quartz font backend based on a
 * #CGFontRef.  This font can then be used with
 * cairo_set_font_face() or cairo_scaled_font_create().
 *
 * Return value: a newly created #cairo_font_face_t. Free with
 *  cairo_font_face_destroy() when you are done using it.
 *
 * Since: 1.6
 */
cairo_font_face_t *
cairo_quartz_font_face_create_for_cgfont (CGFontRef font)
{
    cairo_quartz_font_face_t *font_face;

    quartz_font_ensure_symbols();

    font_face = malloc (sizeof (cairo_quartz_font_face_t));
    if (!font_face) {
	_cairo_error (CAIRO_STATUS_NO_MEMORY);
	return (cairo_font_face_t *)&_cairo_font_face_nil;
    }

    font_face->cgFont = CGFontRetain (font);

    _cairo_font_face_init (&font_face->base, &_cairo_quartz_font_face_backend);

    return &font_face->base;
}
/**
 * cairo_quartz_font_face_create_for_atsu_font_id:
 * @font_id: an ATSUFontID for the font.
 *
 * Creates a new font for the Quartz font backend based on an
 * #ATSUFontID. This font can then be used with
 * cairo_set_font_face() or cairo_scaled_font_create().
 *
 * Return value: a newly created #cairo_font_face_t. Free with
 *  cairo_font_face_destroy() when you are done using it.
 *
 * Since: 1.6
 **/
cairo_font_face_t *
cairo_quartz_font_face_create_for_atsu_font_id (ATSUFontID font_id)
{
    quartz_font_ensure_symbols();

    if (FMGetATSFontRefFromFontPtr != NULL) {
	ATSFontRef atsFont = FMGetATSFontRefFromFontPtr (font_id);
	CGFontRef cgFont = CGFontCreateWithPlatformFont (&atsFont);
	cairo_font_face_t *ff;

	ff = cairo_quartz_font_face_create_for_cgfont (cgFont);

	CGFontRelease (cgFont);

	return ff;
    } else {
	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
	return (cairo_font_face_t *)&_cairo_font_face_nil;
    }
}
static cairo_status_t
_cairo_quartz_font_face_scaled_font_create (void *abstract_face,
					    const cairo_matrix_t *font_matrix,
					    const cairo_matrix_t *ctm,
					    const cairo_font_options_t *options,
					    cairo_scaled_font_t **font_out)
{
    cairo_quartz_font_face_t *font_face = abstract_face;
    cairo_quartz_scaled_font_t *font = NULL;
    cairo_status_t status;
    cairo_font_extents_t fs_metrics;
    double ems;
    CGRect bbox;

    quartz_font_ensure_symbols();
    if (!_cairo_quartz_font_symbols_present)
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);

    font = malloc(sizeof(cairo_quartz_scaled_font_t));
    if (font == NULL)
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);

    memset (font, 0, sizeof(cairo_quartz_scaled_font_t));

    status = _cairo_scaled_font_init (&font->base,
				      &font_face->base, font_matrix, ctm, options,
				      &_cairo_quartz_scaled_font_backend);
    if (status)
	goto FINISH;

    ems = CGFontGetUnitsPerEmPtr (font_face->cgFont);

    /* initialize metrics */
    if (CGFontGetFontBBoxPtr && CGFontGetAscentPtr) {
	fs_metrics.ascent = (CGFontGetAscentPtr (font_face->cgFont) / ems);
	fs_metrics.descent = - (CGFontGetDescentPtr (font_face->cgFont) / ems);
	fs_metrics.height = fs_metrics.ascent + fs_metrics.descent +
	    (CGFontGetLeadingPtr (font_face->cgFont) / ems);

	bbox = CGFontGetFontBBoxPtr (font_face->cgFont);
	fs_metrics.max_x_advance = CGRectGetMaxX(bbox) / ems;
	fs_metrics.max_y_advance = 0.0;
    } else {
	CGGlyph wGlyph;
	UniChar u;

	quartz_CGFontMetrics *m;
	m = CGFontGetHMetricsPtr (font_face->cgFont);

	/* On OX 10.4, GetHMetricsPtr sometimes returns NULL for unknown reasons */
	if (!m) {
	    status = _cairo_error(CAIRO_STATUS_NULL_POINTER);
	    goto FINISH;
	}

	fs_metrics.ascent = (m->ascent / ems);
	fs_metrics.descent = - (m->descent / ems);
	fs_metrics.height = fs_metrics.ascent + fs_metrics.descent + (m->leading / ems);

	/* We kind of have to guess here; W's big, right? */
	u = (UniChar) 'W';
	CGFontGetGlyphsForUnicharsPtr (font_face->cgFont, &u, &wGlyph, 1);
	if (wGlyph && CGFontGetGlyphBBoxesPtr (font_face->cgFont, &wGlyph, 1, &bbox)) {
	    fs_metrics.max_x_advance = CGRectGetMaxX(bbox) / ems;
	    fs_metrics.max_y_advance = 0.0;
	} else {
	    fs_metrics.max_x_advance = 0.0;
	    fs_metrics.max_y_advance = 0.0;
	}
    }

    status = _cairo_scaled_font_set_metrics (&font->base, &fs_metrics);

FINISH:
    if (status != CAIRO_STATUS_SUCCESS) {
	free (font);
    } else {
	*font_out = (cairo_scaled_font_t*) font;
    }

    return status;
}
static cairo_status_t
_cairo_quartz_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
					cairo_font_face_t      **font_face)
{
    const char *family;
    char *full_name;
    CFStringRef cgFontName = NULL;
    CGFontRef cgFont = NULL;
    int loop;

    quartz_font_ensure_symbols();
    if (! _cairo_quartz_font_symbols_present)
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);

    family = toy_face->family;
    full_name = malloc (strlen (family) + 64); // give us a bit of room to tack on Bold, Oblique, etc.
    /* handle CSS-ish faces */
    if (!strcmp(family, "serif") || !strcmp(family, "Times Roman"))
	family = "Times";
    else if (!strcmp(family, "sans-serif") || !strcmp(family, "sans"))
	family = "Helvetica";
    else if (!strcmp(family, "cursive"))
	family = "Apple Chancery";
    else if (!strcmp(family, "fantasy"))
	family = "Papyrus";
    else if (!strcmp(family, "monospace") || !strcmp(family, "mono"))
	family = "Courier";

    /* Try to build up the full name, e.g. "Helvetica Bold Oblique" first,
     * then drop the bold, then drop the slant, then drop both.. finally
     * just use "Helvetica".  And if Helvetica doesn't exist, give up.
     */
    for (loop = 0; loop < 5; loop++) {
	if (loop == 4)
	    family = "Helvetica";

	strcpy (full_name, family);

	if (loop < 3 && (loop & 1) == 0) {
	    if (toy_face->weight == CAIRO_FONT_WEIGHT_BOLD)
		strcat (full_name, " Bold");
	}

	if (loop < 3 && (loop & 2) == 0) {
	    if (toy_face->slant == CAIRO_FONT_SLANT_ITALIC)
		strcat (full_name, " Italic");
	    else if (toy_face->slant == CAIRO_FONT_SLANT_OBLIQUE)
		strcat (full_name, " Oblique");
	}

	if (CGFontCreateWithFontNamePtr) {
	    cgFontName = CFStringCreateWithCString (NULL, full_name, kCFStringEncodingASCII);
	    cgFont = CGFontCreateWithFontNamePtr (cgFontName);
	    CFRelease (cgFontName);
	} else {
	    cgFont = CGFontCreateWithNamePtr (full_name);
	}

	if (cgFont)
	    break;
    }

    if (!cgFont) {
	/* Give up */
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    }

    *font_face = cairo_quartz_font_face_create_for_cgfont (cgFont);
    CGFontRelease (cgFont);

    return CAIRO_STATUS_SUCCESS;
}