📄 cairo-atsui-font.c
字号:
ATSUCreateAndCopyStyle(font->unscaled_style, &style); err = ATSUGlyphGetIdealMetrics(style, 1, &theGlyph, 0, &metricsH); err = ATSUSetAttributes(style, 1, theTag, theSizes, theValues); err = ATSUGlyphGetIdealMetrics(style, 1, &theGlyph, 0, &metricsV); extents.x_bearing = metricsH.sideBearing.x; extents.y_bearing = metricsV.advance.y; extents.width = metricsH.advance.x - metricsH.sideBearing.x - metricsH.otherSideBearing.x; extents.height = -metricsV.advance.y - metricsV.sideBearing.y - metricsV.otherSideBearing.y; extents.x_advance = metricsH.advance.x; extents.y_advance = 0; _cairo_scaled_glyph_set_metrics (scaled_glyph, &font->base, &extents); return CAIRO_STATUS_SUCCESS;}static OSStatus_move_to (const Float32Point *point, void *callback_data){ cairo_path_fixed_t *path = callback_data; _cairo_path_fixed_close_path (path); _cairo_path_fixed_move_to (path, _cairo_fixed_from_double(point->x), _cairo_fixed_from_double(point->y)); return noErr;}static OSStatus_line_to (const Float32Point *point, void *callback_data){ cairo_path_fixed_t *path = callback_data; _cairo_path_fixed_line_to (path, _cairo_fixed_from_double(point->x), _cairo_fixed_from_double(point->y)); return noErr;}static OSStatus_curve_to (const Float32Point *point1, const Float32Point *point2, const Float32Point *point3, void *callback_data){ cairo_path_fixed_t *path = callback_data; _cairo_path_fixed_curve_to (path, _cairo_fixed_from_double(point1->x), _cairo_fixed_from_double(point1->y), _cairo_fixed_from_double(point2->x), _cairo_fixed_from_double(point2->y), _cairo_fixed_from_double(point3->x), _cairo_fixed_from_double(point3->y)); return noErr;}static OSStatus_close_path (void *callback_data){ cairo_path_fixed_t *path = callback_data; _cairo_path_fixed_close_path (path); return noErr;}static cairo_status_t_cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph){ static ATSCubicMoveToUPP moveProc = NULL; static ATSCubicLineToUPP lineProc = NULL; static ATSCubicCurveToUPP curveProc = NULL; static ATSCubicClosePathUPP closePathProc = NULL; OSStatus err; cairo_path_fixed_t *path; path = _cairo_path_fixed_create (); if (!path) return CAIRO_STATUS_NO_MEMORY; if (moveProc == NULL) { moveProc = NewATSCubicMoveToUPP(_move_to); lineProc = NewATSCubicLineToUPP(_line_to); curveProc = NewATSCubicCurveToUPP(_curve_to); closePathProc = NewATSCubicClosePathUPP(_close_path); } err = ATSUGlyphGetCubicPaths(scaled_font->style, _cairo_scaled_glyph_index (scaled_glyph), moveProc, lineProc, curveProc, closePathProc, (void *)path, &err); _cairo_scaled_glyph_set_path (scaled_glyph, &scaled_font->base, path); return CAIRO_STATUS_SUCCESS;}static cairo_int_status_t_cairo_atsui_font_scaled_glyph_init (void *abstract_font, cairo_scaled_glyph_t *scaled_glyph, cairo_scaled_glyph_info_t info){ cairo_atsui_font_t *scaled_font = abstract_font; cairo_status_t status; if ((info & CAIRO_SCALED_GLYPH_INFO_METRICS) != 0) { status = _cairo_atsui_font_init_glyph_metrics (scaled_font, scaled_glyph); if (status) return status; } if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0) { status = _cairo_atsui_scaled_font_init_glyph_path (scaled_font, scaled_glyph); if (status) return status; } return CAIRO_STATUS_SUCCESS;}static cairo_int_status_t_cairo_atsui_font_text_to_glyphs (void *abstract_font, double x, double y, const char *utf8, cairo_glyph_t **glyphs, int *num_glyphs){ cairo_status_t status = CAIRO_STATUS_SUCCESS; uint16_t *utf16; int n16; OSStatus err; ATSUTextLayout textLayout; ATSLayoutRecord *layoutRecords; cairo_atsui_font_t *font = abstract_font; ItemCount glyphCount; int i; status = _cairo_utf8_to_utf16 ((unsigned char *)utf8, -1, &utf16, &n16); if (status) return status; err = ATSUCreateTextLayout(&textLayout); err = ATSUSetTextPointerLocation(textLayout, utf16, 0, n16, n16); /* Set the style for all of the text */ err = ATSUSetRunStyle(textLayout, font->style, kATSUFromTextBeginning, kATSUToTextEnd); err = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(textLayout, 0, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void *)&layoutRecords, &glyphCount); *num_glyphs = glyphCount - 1; *glyphs = (cairo_glyph_t *) malloc(*num_glyphs * (sizeof (cairo_glyph_t))); if (*glyphs == NULL) { return CAIRO_STATUS_NO_MEMORY; } for (i = 0; i < *num_glyphs; i++) { (*glyphs)[i].index = layoutRecords[i].glyphID; (*glyphs)[i].x = x + FixedToFloat(layoutRecords[i].realPos); (*glyphs)[i].y = y; } free (utf16); ATSUDirectReleaseLayoutDataArrayPtr(NULL, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void *) &layoutRecords); ATSUDisposeTextLayout(textLayout); return CAIRO_STATUS_SUCCESS;}static cairo_int_status_t_cairo_atsui_font_old_show_glyphs (void *abstract_font, cairo_operator_t op, cairo_pattern_t *pattern, cairo_surface_t *generic_surface, int source_x, int source_y, int dest_x, int dest_y, unsigned int width, unsigned int height, const cairo_glyph_t *glyphs, int num_glyphs){ cairo_atsui_font_t *font = abstract_font; CGContextRef myBitmapContext = 0, drawingContext; CGColorSpaceRef colorSpace = 0;; cairo_image_surface_t *destImageSurface; int i; void *extra = NULL; cairo_bool_t can_draw_directly; cairo_rectangle_int16_t rect; /* Check if we can draw directly to the destination surface */ can_draw_directly = _cairo_surface_is_quartz (generic_surface) && _cairo_pattern_is_opaque_solid (pattern) && op == CAIRO_OPERATOR_OVER; if (!can_draw_directly) { rect.x = dest_x; rect.y = dest_y; rect.width = width; rect.height = height; _cairo_surface_acquire_dest_image(generic_surface, &rect, &destImageSurface, &rect, &extra); /* Create a CGBitmapContext for the dest surface for drawing into */ colorSpace = CGColorSpaceCreateDeviceRGB(); myBitmapContext = CGBitmapContextCreate(destImageSurface->data, destImageSurface->width, destImageSurface->height, destImageSurface->depth / 4, destImageSurface->stride, colorSpace, kCGImageAlphaPremultipliedFirst); CGContextTranslateCTM(myBitmapContext, 0, destImageSurface->height); CGContextScaleCTM(myBitmapContext, 1.0f, -1.0f); drawingContext = myBitmapContext; } else { drawingContext = ((cairo_quartz_surface_t *)generic_surface)->context; CGContextSaveGState (drawingContext); } ATSFontRef atsFont = FMGetATSFontRefFromFont(font->fontID); CGFontRef cgFont = CGFontCreateWithPlatformFont(&atsFont); CGContextSetFont(drawingContext, cgFont); CGAffineTransform textTransform = CGAffineTransformMakeWithCairoFontScale(&font->base.scale); textTransform = CGAffineTransformScale(textTransform, 1.0f, -1.0f); CGContextSetFontSize(drawingContext, 1.0); CGContextSetTextMatrix(drawingContext, textTransform); if (pattern->type == CAIRO_PATTERN_TYPE_SOLID && _cairo_pattern_is_opaque_solid(pattern)) { cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *)pattern; CGContextSetRGBFillColor(drawingContext, solid->color.red, solid->color.green, solid->color.blue, 1.0f); } else { CGContextSetRGBFillColor(drawingContext, 0.0f, 0.0f, 0.0f, 0.0f); } if (_cairo_surface_is_quartz (generic_surface)) { cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *)generic_surface; if (surface->clip_region) { pixman_box16_t *boxes = pixman_region_rects (surface->clip_region); int num_boxes = pixman_region_num_rects (surface->clip_region); CGRect stack_rects[10]; CGRect *rects; int i; /* XXX: Return-value of malloc needs to be checked for * NULL. Can someone fix this who is more familiar with * the cleanup needed in this function? */ if (num_boxes > 10) rects = malloc (sizeof (CGRect) * num_boxes); else rects = stack_rects; for (i = 0; i < num_boxes; i++) { rects[i].origin.x = boxes[i].x1; rects[i].origin.y = boxes[i].y1; rects[i].size.width = boxes[i].x2 - boxes[i].x1; rects[i].size.height = boxes[i].y2 - boxes[i].y1; } CGContextClipToRects (drawingContext, rects, num_boxes); if (rects != stack_rects) free(rects); } } else { /* XXX: Need to get the text clipped */ } /* TODO - bold and italic text * * We could draw the text using ATSUI and get bold, italics * etc. for free, but ATSUI does a lot of text layout work * that we don't really need... */ for (i = 0; i < num_glyphs; i++) { CGGlyph theGlyph = glyphs[i].index; CGContextShowGlyphsAtPoint(drawingContext, glyphs[i].x, glyphs[i].y, &theGlyph, 1); } if (!can_draw_directly) { CGColorSpaceRelease(colorSpace); CGContextRelease(myBitmapContext); _cairo_surface_release_dest_image(generic_surface, &rect, destImageSurface, &rect, extra); } else { CGContextRestoreGState (drawingContext); } return CAIRO_STATUS_SUCCESS;}const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend = { CAIRO_FONT_TYPE_ATSUI, _cairo_atsui_font_create_toy, _cairo_atsui_font_fini, _cairo_atsui_font_scaled_glyph_init, _cairo_atsui_font_text_to_glyphs, NULL, /* ucs4_to_index */ _cairo_atsui_font_old_show_glyphs,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -