📄 cairo-ft-font.c
字号:
cbox.yMax = (cbox.yMax + 63) & -64; width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6); height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6); stride = (width * hmul + 3) & ~3; if (width * height == 0) { cairo_format_t format; /* Looks like fb handles zero-sized images just fine */ switch (font_options->antialias) { case CAIRO_ANTIALIAS_NONE: format = CAIRO_FORMAT_A1; break; case CAIRO_ANTIALIAS_SUBPIXEL: format= CAIRO_FORMAT_ARGB32; break; case CAIRO_ANTIALIAS_DEFAULT: case CAIRO_ANTIALIAS_GRAY: default: format = CAIRO_FORMAT_A8; break; } (*surface) = (cairo_image_surface_t *) cairo_image_surface_create_for_data (NULL, format, 0, 0, 0); if ((*surface)->base.status) return CAIRO_STATUS_NO_MEMORY; } else { matrix.xx = matrix.yy = 0x10000L; matrix.xy = matrix.yx = 0; switch (font_options->antialias) { case CAIRO_ANTIALIAS_NONE: bitmap.pixel_mode = FT_PIXEL_MODE_MONO; bitmap.num_grays = 1; stride = ((width + 31) & -32) >> 3; break; case CAIRO_ANTIALIAS_DEFAULT: case CAIRO_ANTIALIAS_GRAY: bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; bitmap.num_grays = 256; stride = (width + 3) & -4; break; case CAIRO_ANTIALIAS_SUBPIXEL: switch (font_options->subpixel_order) { case CAIRO_SUBPIXEL_ORDER_RGB: case CAIRO_SUBPIXEL_ORDER_BGR: default: matrix.xx *= 3; hmul = 3; subpixel = TRUE; break; case CAIRO_SUBPIXEL_ORDER_VRGB: case CAIRO_SUBPIXEL_ORDER_VBGR: matrix.yy *= 3; vmul = 3; subpixel = TRUE; break; } FT_Outline_Transform (outline, &matrix); bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; bitmap.num_grays = 256; stride = (width * hmul + 3) & -4; } bitmap.pitch = stride; bitmap.width = width * hmul; bitmap.rows = height * vmul; bitmap.buffer = calloc (1, stride * bitmap.rows); if (bitmap.buffer == NULL) { return CAIRO_STATUS_NO_MEMORY; } FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul); if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) { free (bitmap.buffer); return CAIRO_STATUS_NO_MEMORY; } status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface); if (status) return status; } /* * Note: the font's coordinate system is upside down from ours, so the * Y coordinate of the control box needs to be negated. */ cairo_surface_set_device_offset (&(*surface)->base, floor ((double) cbox.xMin / 64.0), floor (-(double) cbox.yMax / 64.0)); return CAIRO_STATUS_SUCCESS;}/* Converts a bitmap (or other) FT_GlyphSlot into an image */static cairo_status_t_render_glyph_bitmap (FT_Face face, cairo_font_options_t *font_options, cairo_image_surface_t **surface){ FT_GlyphSlot glyphslot = face->glyph; cairo_status_t status = CAIRO_STATUS_SUCCESS; FT_Error error; /* According to the FreeType docs, glyphslot->format could be * something other than FT_GLYPH_FORMAT_OUTLINE or * FT_GLYPH_FORMAT_BITMAP. Calling FT_Render_Glyph gives FreeType * the opportunity to convert such to * bitmap. FT_GLYPH_FORMAT_COMPOSITE will not be encountered since * we avoid the FT_LOAD_NO_RECURSE flag. */ error = FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL); if (error) return CAIRO_STATUS_NO_MEMORY; status = _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface); if (status) return status; /* * Note: the font's coordinate system is upside down from ours, so the * Y coordinate of the control box needs to be negated. */ cairo_surface_set_device_offset (&(*surface)->base, glyphslot->bitmap_left, -glyphslot->bitmap_top); return status;}static cairo_status_t_transform_glyph_bitmap (cairo_matrix_t * shape, cairo_image_surface_t ** surface){ cairo_matrix_t original_to_transformed; cairo_matrix_t transformed_to_original; cairo_image_surface_t *old_image; cairo_surface_t *image; double x[4], y[4]; double origin_x, origin_y; int origin_width, origin_height; int i; int x_min, y_min, x_max, y_max; int width, height; cairo_status_t status; cairo_surface_pattern_t pattern; /* We want to compute a transform that takes the origin * (device_x_offset, device_y_offset) to 0,0, then applies * the "shape" portion of the font transform */ original_to_transformed = *shape; cairo_surface_get_device_offset (&(*surface)->base, &origin_x, &origin_y); origin_width = cairo_image_surface_get_width (&(*surface)->base); origin_height = cairo_image_surface_get_height (&(*surface)->base); cairo_matrix_translate (&original_to_transformed, origin_x, origin_y); /* Find the bounding box of the original bitmap under that * transform */ x[0] = 0; y[0] = 0; x[1] = origin_width; y[1] = 0; x[2] = origin_width; y[2] = origin_height; x[3] = 0; y[3] = origin_height; for (i = 0; i < 4; i++) cairo_matrix_transform_point (&original_to_transformed, &x[i], &y[i]); x_min = floor (x[0]); y_min = floor (y[0]); x_max = ceil (x[0]); y_max = ceil (y[0]); for (i = 1; i < 4; i++) { if (x[i] < x_min) x_min = floor (x[i]); if (x[i] > x_max) x_max = ceil (x[i]); if (y[i] < y_min) y_min = floor (y[i]); if (y[i] > y_max) y_max = ceil (y[i]); } /* Adjust the transform so that the bounding box starts at 0,0 ... * this gives our final transform from original bitmap to transformed * bitmap. */ original_to_transformed.x0 -= x_min; original_to_transformed.y0 -= y_min; /* Create the transformed bitmap */ width = x_max - x_min; height = y_max - y_min; transformed_to_original = original_to_transformed; status = cairo_matrix_invert (&transformed_to_original); if (status) return status; /* We need to pad out the width to 32-bit intervals for cairo-xlib-surface.c */ width = (width + 3) & ~3; image = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height); if (image->status) return CAIRO_STATUS_NO_MEMORY; /* Initialize it to empty */ _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR, CAIRO_COLOR_TRANSPARENT, 0, 0, width, height); /* Draw the original bitmap transformed into the new bitmap */ _cairo_pattern_init_for_surface (&pattern, &(*surface)->base); cairo_pattern_set_matrix (&pattern.base, &transformed_to_original); _cairo_surface_composite (CAIRO_OPERATOR_OVER, &pattern.base, NULL, image, 0, 0, 0, 0, 0, 0, width, height); _cairo_pattern_fini (&pattern.base); /* Now update the cache entry for the new bitmap, recomputing * the origin based on the final transform. */ origin_x = - origin_x; origin_y = - origin_y; cairo_matrix_transform_point (&original_to_transformed, &origin_x, &origin_y); old_image = (*surface); (*surface) = (cairo_image_surface_t *)image; cairo_surface_destroy (&old_image->base); cairo_surface_set_device_offset (&(*surface)->base, - floor (origin_x + 0.5), - floor (origin_y + 0.5)); return status;}static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = { _cairo_ft_unscaled_font_destroy,#if 0 _cairo_ft_unscaled_font_create_glyph#endif};/* cairo_ft_scaled_font_t */typedef struct _cairo_ft_scaled_font { cairo_scaled_font_t base; cairo_ft_unscaled_font_t *unscaled; cairo_ft_options_t ft_options;} cairo_ft_scaled_font_t;const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend;/* The load flags passed to FT_Load_Glyph control aspects like hinting and * antialiasing. Here we compute them from the fields of a FcPattern. */static cairo_ft_options_t_get_pattern_ft_options (FcPattern *pattern){ FcBool antialias, vertical_layout, hinting, autohint, bitmap, embolden; cairo_ft_options_t ft_options; int rgba;#ifdef FC_HINT_STYLE int hintstyle;#endif _cairo_font_options_init_default (&ft_options.base); ft_options.load_flags = FT_LOAD_DEFAULT; ft_options.extra_flags = 0;#ifndef FC_EMBEDDED_BITMAP#define FC_EMBEDDED_BITMAP "embeddedbitmap"#endif /* Check whether to force use of embedded bitmaps */ if (FcPatternGetBool (pattern, FC_EMBEDDED_BITMAP, 0, &bitmap) != FcResultMatch) bitmap = FcFalse; /* disable antialiasing if requested */ if (FcPatternGetBool (pattern, FC_ANTIALIAS, 0, &antialias) != FcResultMatch) antialias = FcTrue; if (antialias) { if (!bitmap) ft_options.load_flags |= FT_LOAD_NO_BITMAP; /* disable hinting if requested */ if (FcPatternGetBool (pattern, FC_HINTING, 0, &hinting) != FcResultMatch) hinting = FcTrue; if (FcPatternGetInteger (pattern, FC_RGBA, 0, &rgba) != FcResultMatch) rgba = FC_RGBA_UNKNOWN; switch (rgba) { case FC_RGBA_RGB: ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB; break; case FC_RGBA_BGR: ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR; break; case FC_RGBA_VRGB: ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB; break; case FC_RGBA_VBGR: ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR; break; case FC_RGBA_UNKNOWN: case FC_RGBA_NONE: default: break; } if (ft_options.base.subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;#ifdef FC_HINT_STYLE if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch) hintstyle = FC_HINT_FULL; if (!hinting) hintstyle = FC_HINT_NONE; switch (hintstyle) { case FC_HINT_NONE: ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE; break; case FC_HINT_SLIGHT: ft_options.base.hint_style = CAIRO_HINT_STYLE_SLIGHT; break; case FC_HINT_MEDIUM: default: ft_options.base.hint_style = CAIRO_HINT_STYLE_MEDIUM; break; case FC_HINT_FULL: ft_options.base.hint_style = CAIRO_HINT_STYLE_FULL; break; }#else /* !FC_HINT_STYLE */ if (!hinting) { ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE; }#endif /* FC_FHINT_STYLE */ } else { ft_options.base.antialias = CAIRO_ANTIALIAS_NONE; } /* force autohinting if requested */ if (FcPatternGetBool (pattern, FC_AUTOHINT, 0, &autohint) != FcResultMatch) autohint = FcFalse; if (autohint) ft_options.load_flags |= FT_LOAD_FORCE_AUTOHINT; if (FcPatternGetBool (pattern, FC_VERTICAL_LAYOUT, 0, &vertical_layout) != FcResultMatch) vertical_layout = FcFalse; if (vertical_layout) ft_options.load_flags |= FT_LOAD_VERTICAL_LAYOUT; #ifndef FC_EMBOLDEN#define FC_EMBOLDEN "embolden"#endif if (FcPatternGetBool (pattern, FC_EMBOLDEN, 0, &embolden) != FcResultMatch) embolden = FcFalse; if (embolden) ft_options.extra_flags |= CAIRO_FT_OPTIONS_EMBOLDEN; return ft_options;}static void_cairo_ft_options_merge (cairo_ft_options_t *options, cairo_ft_options_t *other){ int load_flags = other->load_flags; int load_target = FT_LOAD_TARGET_NORMAL; /* clear load target mode */ load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(other->load_flags))); if (load_flags & FT_LOAD_NO_HINTING) other->base.hint_style = CAIRO_HINT_STYLE_NONE; if (other->base.antialias == CAIRO_ANTIALIAS_NONE || options->base.antialias == CAIRO_ANTIALIAS_NONE) { options->base.antialias = CAIRO_ANTIALIAS_NONE; options->base.subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT; } if (other->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL && (options->base.antialias == CAIRO_ANTIALIAS_DEFAULT || options->base.antialias == CAIRO_ANTIALIAS_GRAY)) { options->base.antialias = CAIRO_ANTIALIAS_SUBPIXEL; options->base.subpixel_order = other->base.subpixel_order; } if (options->base.hint_style == CAIRO_HINT_STYLE_DEFAULT) options->base.hint_style = other->base.hint_style; if (other->base.hint_style == CAIRO_HINT_STYLE_NONE) options->base.hint_style = CAIRO_HINT_STYLE_NONE; if (options->base.antialias == CAIRO_ANTIALIAS_NONE) { if (options->base.hint_style == CAIRO_HINT_STYLE_NONE) load_flags |= FT_LOAD_NO_HINTING; else load_target = FT_LOAD_TARGET_MONO; load_flags |= FT_LOAD_MONOCHROME; } else { switch (options->base.hint_style) { case CAIRO_HINT_STYLE_NONE: load_flags |= FT_LOAD_NO_HINTING; break; case CAIRO_HINT_STYLE_SLIGHT: load_target = FT_LOAD_TARGET_LIGHT; break; case CAIRO_HINT_STYLE_MEDIUM: break; case CAIRO_HINT_STYLE_FULL: case CAIRO_HINT_STYLE_DEFAULT: if (options->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL) { switch (options->base.subpixel_order) { case CAIRO_SUBPIXEL_ORDER_DEFAULT: case CAIRO_SUBPIXEL_ORDER_RGB: case CAIRO_SUBPIXEL_ORDER_BGR: load_target |= FT_LOAD_TARGET_LCD; break; case CAIRO_SUBPIXEL_ORDER_VRGB: case CAIRO_SUBPIXEL_ORDER_VBGR: load_target |= FT_LOAD_TARGET_LCD_V; break; } } break; } } options->load_flags = load_flags | load_target; options->extra_flags = other->extra_flags;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -