static void ar_card_theme_kde_paint_card (ArCardTheme *card_theme, cairo_t *cr, int card_id) { ArCardThemePreimage *preimage_card_theme = (ArCardThemePreimage *) card_theme; ArCardThemeKDE *theme = (ArCardThemeKDE *) card_theme; ArSvg *svg = preimage_card_theme->cards_svg; char node[32]; cairo_rectangle_t *card_extents; cairo_matrix_t matrix; cairo_font_options_t *font_options; if (G_UNLIKELY (card_id == AR_CARD_SLOT)) { ar_svg_render_cairo (preimage_card_theme->slot_preimage, cr, preimage_card_theme->card_size.width, preimage_card_theme->card_size.height); return; } if (theme->legacy) ar_card_get_legacy_node_by_id_snprintf (node, sizeof (node), card_id); else ar_card_get_node_by_id_snprintf (node, sizeof (node), card_id); card_extents = ar_card_theme_kde_get_card_extents (theme, card_id, node); if (!card_extents) return; cairo_save (cr); font_options = ar_svg_get_font_options (svg); if (font_options) { cairo_set_antialias (cr, cairo_font_options_get_antialias (font_options)); cairo_set_font_options (cr, font_options); } cairo_matrix_init_identity (&matrix); cairo_matrix_scale (&matrix, preimage_card_theme->card_size.width / card_extents->width, preimage_card_theme->card_size.height / card_extents->height); cairo_matrix_translate (&matrix, -card_extents->x, -card_extents->y); cairo_set_matrix (cr, &matrix); rsvg_handle_render_cairo_sub (RSVG_HANDLE (svg), cr, node); cairo_restore (cr); }
static int ui_set_antialias(lua_State *L) { struct context *c = lua_touserdata(L, 1); int enable = lua_toboolean(L, 2); cairo_antialias_t antialias = (enable) ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE; cairo_set_antialias(c->cr, antialias); cairo_font_options_t *options; options = cairo_font_options_create(); cairo_font_options_set_antialias(options, antialias); cairo_set_font_options(c->cr, options); return 0; }
static cairo_test_status_t draw (cairo_t *cr, int width, int height) { cairo_font_options_t *font_options; cairo_scaled_font_t *scaled_font; FT_Face face; FT_ULong charcode; FT_UInt idx; int i = 0; cairo_glyph_t glyphs[NUM_GLYPHS]; /* paint white so we don't need separate ref images for * RGB24 and ARGB32 */ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); cairo_paint (cr); cairo_select_font_face (cr, "Bitstream Vera Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size (cr, TEXT_SIZE); font_options = cairo_font_options_create (); cairo_get_font_options (cr, font_options); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF); cairo_set_font_options (cr, font_options); cairo_font_options_destroy (font_options); cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); scaled_font = cairo_get_scaled_font (cr); face = cairo_ft_scaled_font_lock_face (scaled_font); { charcode = FT_Get_First_Char(face, &idx); while (idx && (i < NUM_GLYPHS)) { glyphs[i] = (cairo_glyph_t) {idx, PAD + GRID_SIZE * (i/GRID_ROWS), PAD + TEXT_SIZE + GRID_SIZE * (i%GRID_ROWS)}; i++; charcode = FT_Get_Next_Char(face, charcode, &idx); } } cairo_ft_scaled_font_unlock_face (scaled_font); cairo_show_glyphs(cr, glyphs, i); return CAIRO_TEST_SUCCESS; }
ScreenPainter::ScreenPainter(ScPainter *p, PageItem *item) : m_painter(p) , m_item(item) , m_fillColor("", -1) , m_strokeColor("", -1) , m_cairoFace(NULL) , m_faceIndex(-10) // ScFace::faceIndex() defaults to -1, we need a different value { m_painter->save(); // Use slight hinting to be closer to old Scribus behaviour // We can use CAIRO_HINT_STYLE_NONE to be even more closer, but // slight is a good compromise cairo_font_options_t* options = cairo_font_options_create(); cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_SLIGHT); cairo_set_font_options(m_painter->context(), options); cairo_font_options_destroy(options); }
int renderGlyphs2Cairo(imageObj *img, textPathObj *tp, colorObj *c, colorObj *oc, int ow) { cairo_renderer *r = CAIRO_RENDERER(img); cairoCacheData *cache = MS_IMAGE_RENDERER_CACHE(img); cairoFaceCache *cairo_face = NULL; FT_Face prevface = NULL; int g; cairo_set_font_size(r->cr,MS_NINT(tp->glyph_size * 96.0/72.0)); for(g=0;g<tp->numglyphs;g++) { glyphObj *gl = &tp->glyphs[g]; cairo_glyph_t glyph; /* load the glyph's face into cairo, if not already present */ if(gl->face->face != prevface) { cairo_face = getCairoFontFace(cache,gl->face->face); cairo_set_font_face(r->cr, cairo_face->face); cairo_set_font_options(r->cr,cairo_face->options); prevface = gl->face->face; cairo_set_font_size(r->cr,MS_NINT(tp->glyph_size * 96.0/72.0)); } cairo_save(r->cr); cairo_translate(r->cr,gl->pnt.x,gl->pnt.y); if(gl->rot != 0.0) cairo_rotate(r->cr, -gl->rot); glyph.x = glyph.y = 0; glyph.index = gl->glyph->key.codepoint; cairo_glyph_path(r->cr,&glyph,1); cairo_restore(r->cr); } if (oc) { cairo_save(r->cr); msCairoSetSourceColor(r->cr, oc); cairo_set_line_width(r->cr, ow + 1); cairo_stroke_preserve(r->cr); cairo_restore(r->cr); } if(c) { msCairoSetSourceColor(r->cr, c); cairo_fill(r->cr); } cairo_new_path(r->cr); return MS_SUCCESS; }
static double count_glyphs (double font_size, cairo_antialias_t antialias, cairo_t *cr, int width, int height) { const char text[] = "the jay, pig, fox, zebra and my wolves quack"; cairo_scaled_font_t *scaled_font; cairo_glyph_t *glyphs = NULL; cairo_text_extents_t extents; cairo_font_options_t *options; cairo_status_t status; int num_glyphs; int glyphs_per_line, lines_per_loop; options = cairo_font_options_create (); cairo_font_options_set_antialias (options, antialias); cairo_set_font_options (cr, options); cairo_font_options_destroy (options); cairo_select_font_face (cr, "@cairo:", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size (cr, font_size); scaled_font = cairo_get_scaled_font (cr); status = cairo_scaled_font_text_to_glyphs (scaled_font, 0., 0., text, -1, &glyphs, &num_glyphs, NULL, NULL, NULL); if (status) return 0; cairo_scaled_font_glyph_extents (scaled_font, glyphs, num_glyphs, &extents); cairo_glyph_free (glyphs); glyphs_per_line = num_glyphs * width / extents.width + 1; lines_per_loop = height / extents.height + 1; return glyphs_per_line * lines_per_loop / 1000.; /* kiloglyphs */ }
static cairo_t * _cairo_user_scaled_font_create_meta_context (cairo_user_scaled_font_t *scaled_font) { cairo_content_t content; cairo_surface_t *meta_surface; cairo_t *cr; content = scaled_font->base.options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_ALPHA; meta_surface = _cairo_meta_surface_create (content, -1, -1); cr = cairo_create (meta_surface); cairo_surface_destroy (meta_surface); cairo_set_matrix (cr, &scaled_font->base.scale); cairo_set_font_size (cr, 1.0); cairo_set_font_options (cr, &scaled_font->base.options); return cr; }
static cairo_test_status_t draw (cairo_t *cr, int width, int height) { cairo_text_extents_t extents; cairo_font_options_t *font_options; const char black[] = "black", blue[] = "blue"; /* We draw in the default black, so paint white first. */ cairo_save (cr); cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */ cairo_paint (cr); cairo_restore (cr); cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY " Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size (cr, TEXT_SIZE); font_options = cairo_font_options_create (); cairo_get_font_options (cr, font_options); cairo_font_options_set_antialias (font_options, CAIRO_ANTIALIAS_GRAY); cairo_set_font_options (cr, font_options); cairo_font_options_destroy (font_options); cairo_set_source_rgb (cr, 0, 0, 0); /* black */ cairo_text_extents (cr, black, &extents); cairo_move_to (cr, -extents.x_bearing, -extents.y_bearing); cairo_show_text (cr, black); cairo_translate (cr, 0, -extents.y_bearing + 1); cairo_set_source_rgb (cr, 0, 0, 1); /* blue */ cairo_text_extents (cr, blue, &extents); cairo_move_to (cr, -extents.x_bearing, -extents.y_bearing); cairo_show_text (cr, blue); return CAIRO_TEST_SUCCESS; }
static cairo_test_status_t draw (cairo_t *cr, int width, int height) { cairo_font_options_t *options; cairo_set_source_rgb (cr, 1, 1, 1); cairo_paint (cr); cairo_set_source_rgb (cr, 0, 0, 0); cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE); cairo_select_font_face (cr, "@cairo:", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); options = cairo_font_options_create (); cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_NONE); cairo_set_font_options (cr, options); cairo_font_options_destroy (options); cairo_set_font_size (cr, 16); cairo_move_to (cr, 4, 14); cairo_show_text (cr, "Is cairo's twin giza?"); cairo_move_to (cr, 4, 34); cairo_text_path (cr, "Is cairo's twin giza?"); cairo_fill (cr); cairo_move_to (cr, 4, 54); cairo_text_path (cr, "Is cairo's twin giza?"); cairo_set_line_width (cr, 2/16.); cairo_stroke (cr); return CAIRO_TEST_SUCCESS; }
static cairo_test_status_t draw (cairo_t *cr, int width, int height) { cairo_text_extents_t extents; cairo_font_options_t *font_options; static char black[] = "black", blue[] = "blue"; cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); cairo_paint (cr); cairo_select_font_face (cr, "Bitstream Vera Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size (cr, TEXT_SIZE); font_options = cairo_font_options_create (); cairo_get_font_options (cr, font_options); cairo_font_options_set_antialias (font_options, CAIRO_ANTIALIAS_SUBPIXEL); cairo_font_options_set_subpixel_order (font_options, CAIRO_SUBPIXEL_ORDER_RGB); cairo_set_font_options (cr, font_options); cairo_font_options_destroy (font_options); cairo_set_source_rgb (cr, 0, 0, 0); /* black */ cairo_text_extents (cr, black, &extents); cairo_move_to (cr, -extents.x_bearing, -extents.y_bearing); cairo_show_text (cr, black); cairo_translate (cr, 0, -extents.y_bearing + 1); cairo_set_source_rgb (cr, 0, 0, 1); /* blue */ cairo_text_extents (cr, blue, &extents); cairo_move_to (cr, -extents.x_bearing, -extents.y_bearing); cairo_show_text (cr, blue); return CAIRO_TEST_SUCCESS; }
void GUIFont_GetGreaterSize(const char *AFontName, float AHeight, unsigned int *ACharWidth, unsigned int *ACharHeight) { cairo_text_extents_t *BExtents = (cairo_text_extents_t *)malloc(sizeof(cairo_text_extents_t)); unsigned char *BText = (unsigned char *)malloc(sizeof(unsigned char) * 2); BText[0] = 0; BText[1] = '\0'; cairo_surface_t *BSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1); cairo_t *BContext = cairo_create(BSurface); cairo_font_options_t *cfo = cairo_font_options_create(); cairo_font_options_set_antialias(cfo, CAIRO_ANTIALIAS_SUBPIXEL); cairo_set_font_options(BContext, cfo); cairo_select_font_face(BContext, AFontName, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(BContext, AHeight); for (BText[0] = 0; BText[0] < 255; BText[0]++) { cairo_text_extents(BContext, BText, BExtents); if (BExtents) { if (*ACharHeight < BExtents->height) { *ACharHeight = BExtents->height; }; if (*ACharWidth < BExtents->width) { *ACharWidth = BExtents->width; }; }; }; cairo_destroy(BContext); cairo_surface_destroy(BSurface); };
void Initialize_Graphics(cairo_t *cr) { // int Height,OldMaxX; // int t,t1; // t is unused // int t1; int x,dx; MaxX = WINDOW_WIDTH; MaxY = WINDOW_WIDTH; #ifdef GUI_INTERFACE cairo_scale(SF_rgb_context, 1, 1); #endif #ifdef GUI cairo_scale(cr, 1, 1); #else cairo_scale(cr, 1.0/SCALE_F, 1.0/SCALE_F); #endif cairo_set_antialias(cr, CAIRO_ANTIALIAS_BEST); cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE); cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); if(cairo_surface_get_type(cairo_get_target(cr)) == CAIRO_SURFACE_TYPE_XLIB) { // Supply a value VAL between 100.0 and 240.0 (as a double) cairo_set_line_width(cr, (435.0 * 1) / ((double) MaxY * 1)); } else if(cairo_surface_get_type(cairo_get_target(cr)) == CAIRO_SURFACE_TYPE_IMAGE) { #ifdef __APPLE__ cairo_set_line_width(cr, DEFAULT_LINE_WIDTH); #else cairo_set_line_width(cr, DEFAULT_LINE_WIDTH); #endif } else // Mostly quartz? { cairo_set_line_width(cr, (390.1 * 1) / ((double) MaxY * 1)); // for image_surf use 239 } // cairo_set_line_width(cr, (90.1 * 1) / ((double) MaxY * 1)); //// Cairo uses a different coordinate system than graphics.h, so we reflect Cairo's through //// the x-asis to make it equal to that of graphics.h. //// cairo_matrix_t x_reflection_matrix; // Reflecting it however means that text will also be reflected. We therefore also use a // reflection matrix for drawing fonts to reflect text back. // cairo_matrix_t font_reflection_matrix; // We need the options to turn off font anti-aliasing cairo_font_options_t *font_options = cairo_font_options_create(); // cairo_matrix_init_identity(&x_reflection_matrix); // x_reflection_matrix.yy = -1.0; // cairo_set_matrix(cr, &x_reflection_matrix); cairo_set_font_size(cr, POINTS_FONT_SIZE); // cairo_set_font_size(cr, 5.9); // cairo_get_font_matrix(cr, &font_reflection_matrix); // font_reflection_matrix.yy = font_reflection_matrix.yy * -1; // font_reflection_matrix.x0 += side_panel_size; // see (1) // cairo_set_font_matrix(cr, &font_reflection_matrix); // Translate negative height down because the reflection draws on top of the drawing surface // (i.e. out of frame, directly on top of the frame) // (1) Also translate the matrix over the x-axis to emulate the fact that DOS places the SF // square in the middle. // cairo_translate(cr, side_panel_size, -MaxY); // cairo_translate(cr, 0, -MaxY); // Turning off anti-alaising cairo_get_font_options(cr, font_options); cairo_font_options_set_antialias(font_options, CAIRO_ANTIALIAS_BEST); cairo_set_font_options(cr, font_options); cairo_select_font_face(cr,"DriodSans",CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_NORMAL); cairo_font_options_destroy(font_options); // Sets all the values in the array to the empty path // Gives a vague warning, probably because this only works for types with the size of an int // (source: SO) // memset(PrevMissile, empty_path, MAX_NO_OF_MISSILES); // PrevMissile = {empty_path}; // Attemps above don't work, so we initialize manually // clears the screen, probably the dos screen, and sets the current graphics write // pointer to (0,0) // cleardevice(); // The "textheight" function returns the height of a string in pixels. // Height=textheight("H"); /* Get basic text height */ // Height = TEXT_HEIGHT; // // OldMaxX=MaxX; // t1=4*Height; // // Panel_Y_End=MaxY; // Panel_Y_Start=MaxY-t1+2; // MaxY_Panel=Panel_Y_End-Panel_Y_Start; // MaxY=MaxY-t1; // MaxX=MaxY; // Any modern graphics library should handle this "if" statements themselves, if needed at // all because we don't really need to know anymore wether or not we are on a vga display. // This aspect ratio stuff has to do with the fact if your display has square pixels or not. // AspectRatio is defined in opengraphics. Pixels are always square nowadays // if(AspectRatio==1.0) /* VGA HI */ square pixel ratio // MaxX=MaxY; // else /* for all others */ // { // MaxX=MaxX*AspectRatio; /********* MaxX and MaxY give a square */ // MaxX=MaxX-t1/AspectRatio; /******** less two panel lines */ // } // Xmargin=OldMaxX/2-MaxX/2; // printf("Xmargin: %d", Xmargin); // cairo_translate(cr, Xmargin, 0); // -- void setviewport(int left, int top, int right, int bottom, int clip); // setviewport function is used to restrict drawing to a particular portion on the screen. // For example "setviewport(100 , 100, 200, 200, 1)" will restrict our drawing activity // inside the rectangle(100,100, 200, 200). // // left, top, right, bottom are the coordinates of main diagonal of rectangle in which we wish to restrict our drawing. Also note that the point (left, top) becomes the new origin. // setviewport( Xmargin, 0, Xmargin+MaxX, MaxY, 1); dx=MaxX/8; Points_X=x=2*TEXT_WIDTH; x=x+dx; Control_X=x; x=x+dx; Velocity_X=x; x=x+dx; Vulner_X=x; x=x+dx; IFF_X=x; x=x+dx; Interval_X=x; x=x+dx; Speed_X=x; x=x+dx; Shots_X=x; }
static cairo_test_status_t cairo_test_for_target (cairo_test_t *test, cairo_boilerplate_target_t *target, int dev_offset) { cairo_test_status_t status; cairo_surface_t *surface = NULL; cairo_t *cr; char *png_name, *ref_name, *diff_name, *offset_str; cairo_test_status_t ret = CAIRO_TEST_SUCCESS; cairo_content_t expected_content; cairo_font_options_t *font_options; const char *format; /* Get the strings ready that we'll need. */ format = cairo_boilerplate_content_name (target->content); if (dev_offset) xasprintf (&offset_str, "-%d", dev_offset); else offset_str = strdup(""); xasprintf (&png_name, "%s-%s-%s%s%s", test->name, target->name, format, offset_str, CAIRO_TEST_PNG_SUFFIX); ref_name = cairo_ref_name_for_test_target_format (test->name, target->name, format); xasprintf (&diff_name, "%s-%s-%s%s%s", test->name, target->name, format, offset_str, CAIRO_TEST_DIFF_SUFFIX); if (target->is_vector) { int i; for (i = 0; vector_ignored_tests[i] != NULL; i++) if (strcmp (test->name, vector_ignored_tests[i]) == 0) { cairo_test_log ("Error: Skipping for vector target %s\n", target->name); ret = CAIRO_TEST_UNTESTED; goto UNWIND_STRINGS; } } if (ret == CAIRO_TEST_SUCCESS) { /* Run the actual drawing code. */ if (test->width && test->height) { test->width += dev_offset; test->height += dev_offset; } surface = (target->create_surface) (test->name, target->content, test->width, test->height, CAIRO_BOILERPLATE_MODE_TEST, &target->closure); if (test->width && test->height) { test->width -= dev_offset; test->height -= dev_offset;; } } if (surface == NULL) { cairo_test_log ("Error: Failed to set %s target\n", target->name); ret = CAIRO_TEST_UNTESTED; goto UNWIND_STRINGS; } /* Check that we created a surface of the expected type. */ if (cairo_surface_get_type (surface) != target->expected_type) { cairo_test_log ("Error: Created surface is of type %d (expected %d)\n", cairo_surface_get_type (surface), target->expected_type); ret = CAIRO_TEST_FAILURE; goto UNWIND_SURFACE; } /* Check that we created a surface of the expected content, * (ignore the articifical * CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED value). */ expected_content = target->content; if (expected_content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED) expected_content = CAIRO_CONTENT_COLOR_ALPHA; if (cairo_surface_get_content (surface) != expected_content) { cairo_test_log ("Error: Created surface has content %d (expected %d)\n", cairo_surface_get_content (surface), expected_content); ret = CAIRO_TEST_FAILURE; goto UNWIND_SURFACE; } cairo_surface_set_device_offset (surface, dev_offset, dev_offset); cr = cairo_create (surface); /* Clear to transparent (or black) depending on whether the target * surface supports alpha. */ cairo_save (cr); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint (cr); cairo_restore (cr); /* Set all components of font_options to avoid backend differences * and reduce number of needed reference images. */ font_options = cairo_font_options_create (); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_ON); cairo_font_options_set_antialias (font_options, CAIRO_ANTIALIAS_GRAY); cairo_set_font_options (cr, font_options); cairo_font_options_destroy (font_options); status = (test->draw) (cr, test->width, test->height); /* Then, check all the different ways it could fail. */ if (status) { cairo_test_log ("Error: Function under test failed\n"); ret = status; goto UNWIND_CAIRO; } if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) { cairo_test_log ("Error: Function under test left cairo status in an error state: %s\n", cairo_status_to_string (cairo_status (cr))); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } /* Skip image check for tests with no image (width,height == 0,0) */ if (test->width != 0 && test->height != 0) { buffer_diff_result_t result; cairo_status_t diff_status; xunlink (png_name); (target->write_to_png) (surface, png_name); if (!ref_name) { cairo_test_log ("Error: Cannot find reference image for %s/%s-%s-%s%s\n",srcdir, test->name, target->name, format, CAIRO_TEST_REF_SUFFIX); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } cairo_test_log ("Comparing result against reference image: %s\n", ref_name); if (target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED) { diff_status= image_diff_flattened (png_name, ref_name, diff_name, dev_offset, dev_offset, 0, 0, &result); } else { diff_status = image_diff (png_name, ref_name, diff_name, dev_offset, dev_offset, 0, 0, &result); } if (diff_status) { cairo_test_log ("Error: Failed to compare images: %s\n", cairo_status_to_string (diff_status)); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } if (result.pixels_changed && result.max_diff > target->error_tolerance) { ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } } UNWIND_CAIRO: cairo_destroy (cr); UNWIND_SURFACE: cairo_surface_destroy (surface); cairo_debug_reset_static_data (); if (target->cleanup) target->cleanup (target->closure); UNWIND_STRINGS: if (png_name) free (png_name); if (ref_name) free (ref_name); if (diff_name) free (diff_name); if (offset_str) free (offset_str); return ret; }
/** * Initialize a new console */ Console* new_Console(cairo_t* context, double font_size) { //printf("Console::Console(cairo_t@%p)\n", context); Console* self; self = malloc(sizeof(Console)); self->head = null; self->tail = null; self->cursor = null; self->width = default_width; self->height = default_height; self->pad = 4; self->font_filename = "./Monaco_Linux.ttf"; /* TODO */ self->font_size = font_size; self->transparency = 1.0; self->antialias_text = false; self->antialias_graphics = true; /* initialize lithp, cairo - and define callbacks */ self->lithp = new_LithpInterpreter(); char* cairo_init [] = { //"(set 'libcairo (xl:dlopen \"libcairo.dylib\"))", //"(set 'libcairo (xl:dlopen \"libcairo.so.2\"))", //"(set 'libcairo (xl:dlopen \"/Users/antoine/Projects/phlo/install/lib/libcairo.dylib\"))", #if defined(__linux__) "(set 'libcairo (xl:dlopen \"libcairo.so.2\"))", #elif defined(__APPLE__) && defined(__MACH__) "(set 'libcairo (xl:dlopen \"libcairo.dylib\"))", #endif "(set 'cairo:set-source-rgb (xl:dlsym libcairo \"cairo_set_source_rgb\"))", "(set 'cairo:rectangle (xl:dlsym libcairo \"cairo_rectangle\"))", "(set 'cairo:fill (xl:dlsym libcairo \"cairo_fill\"))", "(set 'cairo:translate (xl:dlsym libcairo \"cairo_translate\"))", "(set 'cairo:rotate (xl:dlsym libcairo \"cairo_rotate\"))", "(set 'cairo:move-to (xl:dlsym libcairo \"cairo_move_to\"))", "(set 'cairo:set-source-rgba (xl:dlsym libcairo \"cairo_set_source_rgba\"))", "(set 'console:width 492)", "(set 'console:height 344)", "(set 'pi 3.141592)", "(set 'pretty '(lambda (cr arc theta) " " (cond ((lte arc 0.0) 0.0) " " ('t (progn " " (cairo:rotate cr theta) " " (cairo:rectangle cr 20.0 20.0 140.0 20.0) " " (cairo:fill cr) " " (pretty cr (sub arc theta) theta)))))) ", "(set 'console:expose-event '(lambda (context) " " (cairo:set-source-rgb context 0.5 0.5 1.0) " " (cairo:translate context (div console:width 2.0) (div console:height 2.0))" " (pretty context (mul pi 2.0) (div pi 4.0))))", //"(set 'console:expose-event '(lambda (context) ()))", null }; for (size_t t = 0; cairo_init[t] != null; t++) { Expression* callback = Expression_parse_utf8(cairo_init[t], null, &self->lithp->symbol_list); _gc_protect(callback); Expression_eval(callback, self->lithp->environment); _gc_unprotect(callback); } /* initialize and configure console font */ FT_Library library; int error = FT_Init_FreeType(&library); if (error) { perror("Could not open FreeType library"); exit(EXIT_FAILURE); } self->font_face = malloc(sizeof(FT_Face*)); error = FT_New_Face(library, self->font_filename, 0, self->font_face); if (error) { perror("Could not open font"); exit(EXIT_FAILURE); } cairo_set_font_face(context, cairo_ft_font_face_create_for_ft_face(*self->font_face, 0)); cairo_set_font_size(context, self->font_size); cairo_font_options_t* font_options = cairo_font_options_create(); cairo_get_font_options(context, font_options); if (self->antialias_text) { cairo_font_options_set_antialias(font_options, CAIRO_ANTIALIAS_NONE); } cairo_set_font_options(context, font_options); self->font_extents = malloc(sizeof(cairo_font_extents_t)); cairo_font_extents(context, self->font_extents); /* some sample text */ //wchar_t* test_text = L"ABCDEFGHIJKLM\nNOPQRSTUVWXYZ\nabcdefghijklm\nnopqrstuvwxyz\n1234567890\0"; wchar_t* test_text = L" \n "; unsigned int n; for (n = 0; n < wcslen(test_text); n++) { // Console_append(self, test_text[n]); Console_insert(self, test_text[n]); } self->cursor = self->head; return self; }
void Context::setFontOptions( const FontOptions *options ) { cairo_set_font_options( mCairo, const_cast<FontOptions*>( options )->getCairoFontOptions() ); }
static GpStatus MeasureString (GpGraphics *graphics, GDIPCONST WCHAR *stringUnicode, int *length, GDIPCONST GpFont *font, GDIPCONST RectF *rc_org, GDIPCONST GpStringFormat *format, GpBrush *brush, RectF *boundingBox, int *codepointsFitted, int *linesFilled, WCHAR *CleanString, GpStringDetailStruct* StringDetails, GpDrawTextData *data) { BYTE *String; /* Holds the UTF8 version of our sanitized string */ unsigned long StringLen; /* Length of CleanString */ GDIPCONST WCHAR *Src; WCHAR *Dest; unsigned long i; unsigned long j; GpStringDetailStruct *CurrentDetail; GpStringDetailStruct *CurrentLineStart; /* For rendering engine, to bump LineLen */ float *TabStops; int NumOfTabStops; int WrapPoint; /* Array index of wrap character */ int WrapX; /* Width of text at wrap character */ float CursorX; /* Current X position of drawing cursor */ float CursorY; /* Current Y position of drawing cursor */ int MaxX; /* Largest X of cursor */ int MaxXatY; /* Y coordinate of line with largest X, needed for MaxX resetting on wrap */ int MaxY; /* Largest Y of cursor */ int FrameWidth; /* rc->Width (or rc->Height if vertical) */ int FrameHeight; /* rc->Height (or rc->Width if vertical) */ int AlignHorz; /* Horizontal Alignment mode */ int AlignVert; /* Vertical Alignment mode */ int LineHeight; /* Height of a line with given font */ cairo_font_extents_t FontExtent; /* Info about our font */ cairo_font_options_t *FontOptions; RectF rc_coords, *rc = &rc_coords; float FontSize; if (OPTIMIZE_CONVERSION (graphics)) { rc->X = rc_org->X; rc->Y = rc_org->Y; rc->Width = rc_org->Width; rc->Height = rc_org->Height; } else { rc->X = gdip_unitx_convgr (graphics, rc_org->X); rc->Y = gdip_unity_convgr (graphics, rc_org->Y); rc->Width = gdip_unitx_convgr (graphics, rc_org->Width); rc->Height = gdip_unity_convgr (graphics, rc_org->Height); } #ifdef DRAWSTRING_DEBUG printf("GdipDrawString(...) called (length=%d, fontsize=%d)\n", length, (int)font->sizeInPixels); #endif TabStops = format->tabStops; NumOfTabStops = format->numtabStops; /* Prepare our various buffers and variables */ StringLen = *length; if (data) data->has_hotkeys = FALSE; /* Set aliasing mode */ FontOptions = cairo_font_options_create(); switch(graphics->text_mode) { default: case TextRenderingHintSystemDefault: { cairo_font_options_set_antialias(FontOptions, CAIRO_ANTIALIAS_DEFAULT); //cairo_font_options_set_hint_style(FontOptions, CAIRO_HINT_STYLE_NONE); //cairo_font_options_set_subpixel_order(FontOptions, CAIRO_SUBPIXEL_ORDER_DEFAULT); //cairo_font_options_set_hint_style(FontOptions, CAIRO_HINT_STYLE_DEFAULT); //cairo_font_options_set_hint_metrics(FontOptions, CAIRO_HINT_METRICS_DEFAULT); break; } // FIXME - pick matching settings for each text mode case TextRenderingHintSingleBitPerPixelGridFit: case TextRenderingHintSingleBitPerPixel: case TextRenderingHintAntiAliasGridFit: case TextRenderingHintAntiAlias: { cairo_font_options_set_antialias(FontOptions, CAIRO_ANTIALIAS_DEFAULT); break; } case TextRenderingHintClearTypeGridFit: { cairo_font_options_set_antialias(FontOptions, CAIRO_ANTIALIAS_DEFAULT); break; } } cairo_set_font_options(graphics->ct, FontOptions); cairo_font_options_destroy(FontOptions); // Do we want this here? /* Commented out until we properly save/restore AA settings; should fix bug #76135 cairo_set_antialias(graphics->ct, CAIRO_ANTIALIAS_NONE); */ /* Get font size information; how expensive is the cairo stuff here? */ cairo_set_font_face (graphics->ct, (cairo_font_face_t*) font->cairofnt); /* Set our font; this will also be used for later drawing */ /* this will always return the same value, except when printing */ FontSize = (graphics->type == gtPostScript) ? font->emSize : font->sizeInPixels; cairo_set_font_size (graphics->ct, FontSize); cairo_font_extents (graphics->ct, &FontExtent); /* Get the size we're looking for */ /* cairo_font_set_transform(font->cairofnt, SavedMatrix);*/ /* Restore the matrix */ if ((LineHeight=FontExtent.ascent)<1) { LineHeight=1; } #ifdef DRAWSTRING_DEBUG printf("Font extents: ascent:%d, descent: %d, height:%d, maxXadvance:%d, maxYadvance:%d\n", (int)FontExtent.ascent, (int)FontExtent.descent, (int)FontExtent.height, (int)FontExtent.max_x_advance, (int)FontExtent.max_y_advance); #endif /* Sanitize string, remove formatting chars and build description array */ #ifdef DRAWSTRING_DEBUG printf("GdipDrawString(...) Sanitizing string, StringLen=%d\n", StringLen); #endif Src=stringUnicode; /* unless specified we don't consider the trailing spaces, unless there is just one space (#80680) */ if ((format->formatFlags & StringFormatFlagsMeasureTrailingSpaces) == 0) { while ((StringLen > 0) && (isspace ((int) ( *(Src + StringLen - 1))))) StringLen--; if (StringLen == 0) StringLen = 1; } Dest=CleanString; CurrentDetail=StringDetails; for (i=0; i<StringLen; i++) { switch(*Src) { case '\r': { /* CR */ Src++; continue; } case '\t': { /* Tab */ if (NumOfTabStops > 0) { CurrentDetail->Flags |= STRING_DETAIL_TAB; } Src++; continue; } case '\n': { /* LF */ CurrentDetail->Flags |= STRING_DETAIL_LF; CurrentDetail->Linefeeds++; Src++; continue; } case '&': { /* We print *all* chars if no hotkeys */ if (format->hotkeyPrefix==HotkeyPrefixNone) { break; } Src++; if (*Src=='&') { /* We skipped the first '&', the break will make us drop to copying the second */ break; } CurrentDetail->Flags |= STRING_DETAIL_HOTKEY; if (data) data->has_hotkeys = TRUE; continue; } /* Boy, this must be slow, FIXME somehow */ default: { if (((format->formatFlags & StringFormatFlagsNoWrap)==0) || ((format->trimming != StringTrimmingCharacter) && (format->trimming != StringTrimmingNone))) { break; } /* Fall through */ } case ' ': case '.': { /* Mark where we can break for a new line */ CurrentDetail->Flags |= STRING_DETAIL_BREAK; break; } } *Dest=*Src; Src++; Dest++; CurrentDetail++; } *Dest='\0'; /* Recalculate StringLen; we may have shortened String */ Dest=CleanString; StringLen=0; while (*Dest!=0) { StringLen++; Dest++; } /* Don't bother doing anything else if the length is 0 */ if (StringLen == 0) { *length = 0; return Ok; } /* Convert string from Gdiplus format to UTF8, suitable for cairo */ String = (BYTE*) ucs2_to_utf8 ((const gunichar2 *)CleanString, -1); if (!String) return OutOfMemory; #ifdef DRAWSTRING_DEBUG printf("Sanitized string: >%s<, length %d (utf8-length:%d)\n", String, StringLen, strlen((char *)String)); #endif /* Generate size array */ if (CalculateStringWidths (graphics->ct, font, CleanString, StringLen, StringDetails)==0) { /* FIXME; pick right return code */ GdipFree(String); return Ok; } GdipFree (String); CursorX=0; CursorY=0; MaxX=0; MaxXatY=0; MaxY=0; CurrentLineStart=StringDetails; CurrentDetail=StringDetails; CurrentDetail->Flags |= STRING_DETAIL_LINESTART; WrapPoint=-1; WrapX=0; if (format->formatFlags & StringFormatFlagsDirectionVertical) { FrameWidth = SAFE_FLOAT_TO_UINT32 (rc->Height); FrameHeight = SAFE_FLOAT_TO_UINT32 (rc->Width); } else { FrameWidth = SAFE_FLOAT_TO_UINT32 (rc->Width); FrameHeight = SAFE_FLOAT_TO_UINT32 (rc->Height); } #ifdef DRAWSTRING_DEBUG printf("Frame %d x %d\n", FrameWidth, FrameHeight); #endif for (i=0; i<StringLen; i++) { /* Handle tabs and new lines */ if (CurrentDetail->Flags & STRING_DETAIL_TAB) { float tab_pos; int tab_index; tab_pos = format->firstTabOffset; tab_index = 0; while (CursorX > tab_pos) { tab_pos += TabStops[tab_index % NumOfTabStops]; tab_index++; } CursorX = tab_pos; CurrentLineStart = CurrentDetail; CurrentDetail->Flags |= STRING_DETAIL_LINESTART; } if (CurrentDetail->Flags & STRING_DETAIL_LF) { CursorX = 0; CursorY += LineHeight * CurrentDetail->Linefeeds; CurrentDetail->Flags |= STRING_DETAIL_LINESTART; CurrentLineStart = CurrentDetail; #ifdef DRAWSTRING_DEBUG { int j; for (j=0; j<CurrentDetail->Linefeeds; j++) { printf("<LF>\n"); } } #endif } #ifdef DRAWSTRING_DEBUG printf("[%3d] X: %3d, Y:%3d, '%c' | ", i, (int)CursorX, (int)CursorY, CleanString[i]>=32 ? CleanString[i] : '?'); #endif /* Remember where to wrap next, but only if wrapping allowed */ if (((format->formatFlags & StringFormatFlagsNoWrap)==0) && (CurrentDetail->Flags & STRING_DETAIL_BREAK)) { if (CleanString[i] == ' ') { WrapPoint=i+1; /* We skip the break char itself, keeping it at the end of the old line */ } else { WrapPoint=i; } if (CursorX>MaxX) { WrapX=CursorX; } else { WrapX=MaxX; } #ifdef DRAWSTRING_DEBUG printf("<W>"); #endif } /* New line voids any previous wrap point */ if (CurrentDetail->Flags & STRING_DETAIL_LINESTART) { WrapPoint=-1; } CurrentDetail->PosX=CursorX; CurrentDetail->PosY=CursorY; /* Advance cursor */ CursorX+=CurrentDetail->Width; if (MaxX<CursorX) { MaxX=CursorX; MaxXatY=CursorY; } /* Time for a new line? Go back to last WrapPoint and wrap */ if (FrameWidth && CursorX>FrameWidth) { if (WrapPoint!=-1) { /** Re-Calculate line lengths **/ /* Old line */ CurrentLineStart->LineLen-=i-WrapPoint; if (MaxXatY==CursorY) { MaxX=WrapX; } /* Remove the trailing space from being counted if we're not supposed to */ if (((format->formatFlags & StringFormatFlagsMeasureTrailingSpaces)==0) && (WrapPoint>0)) { if (CleanString[WrapPoint-1]==' ') { if (MaxXatY==CursorY) { MaxX-=StringDetails[WrapPoint-1].Width; } StringDetails[WrapPoint-1].Width=0; CurrentLineStart->LineLen--; } } /* New line */ CurrentLineStart=&(StringDetails[WrapPoint]); CurrentLineStart->Flags|=STRING_DETAIL_LINESTART; CurrentLineStart->LineLen=0; /* Generate CursorX/Y for new line */ CursorY+=LineHeight; CursorX=CurrentLineStart->Width; i=WrapPoint; #ifdef DRAWSTRING_DEBUG printf("\n<Forcing break at index %d, CursorX:%f, LineLen:%d>\n", WrapPoint, CursorX, CurrentLineStart->LineLen); #endif CurrentDetail=&(StringDetails[WrapPoint]); CurrentDetail->PosX=0; CurrentDetail->PosY=CursorY; WrapPoint=-1; } else { /* This line is too long and has no wrap points, check if we need to insert ellipsis. To keep at least a bit of performance, we cheat - we don't actually calculate the size of the elipsis chars but assume that they're always smaller than any other character. And we don't try to hard to fit as many chars as possible. */ int EndOfLine; #ifdef DRAWSTRING_DEBUG printf("No wrappoint (yet) set\n"); #endif /* Find end of line, index i is the first char no longer visible on the line */ EndOfLine=i; if ((format->formatFlags & StringFormatFlagsNoWrap)==0) { while (EndOfLine<StringLen && ((StringDetails[EndOfLine].Flags & STRING_DETAIL_LF)==0)) { EndOfLine++; } } else { while (EndOfLine<StringLen && ((StringDetails[EndOfLine].Flags & (STRING_DETAIL_LF | STRING_DETAIL_BREAK))==0)) { EndOfLine++; } if (EndOfLine<StringLen) { if (StringDetails[EndOfLine].Flags & STRING_DETAIL_BREAK) { EndOfLine++; } } } if ((format->trimming==StringTrimmingEllipsisWord) || (format->trimming==StringTrimmingEllipsisCharacter)) { if (CurrentLineStart->LineLen>3) { if (format->trimming==StringTrimmingEllipsisCharacter) { CleanString[i-1]='.'; CleanString[i-2]='.'; CleanString[i-3]='.'; } else { int found=0; j=i; while(j>(i-CurrentLineStart->LineLen)) { if (CleanString[j]==' ') { CleanString[j]='.'; CurrentLineStart->LineLen-=i-j-1; if ((j+1)<EndOfLine) { CleanString[j+1]='.'; CurrentLineStart->LineLen++; } if ((j+2)<EndOfLine) { CleanString[j+2]='.'; CurrentLineStart->LineLen++; } found=1; break; } j--; } if (!found) { CleanString[i-1]='.'; CleanString[i-2]='.'; CleanString[i-3]='.'; } } } } else if (format->trimming==StringTrimmingEllipsisPath) { int k; float LineWidth; /* Find end of line, index i is the first char no longer visible on the line */ EndOfLine=i; while (EndOfLine<StringLen && ((StringDetails[EndOfLine].Flags & (STRING_DETAIL_LF | STRING_DETAIL_BREAK))==0)) { EndOfLine++; } /* Whack the center, make sure we've got space in the string */ if (CurrentLineStart->LineLen>3) { j=i-(CurrentLineStart->LineLen/2); CleanString[j-1]='.'; CleanString[j]='.'; CleanString[j+1]='.'; /* Have just enough to include our ellipsis */ LineWidth=0; for (k=i-CurrentLineStart->LineLen; k<(j+1); k++) { LineWidth+=StringDetails[k].Width; } CurrentLineStart->LineLen=i-j+3; /* 3=ellipsis */ /* Now figure out how many chars from the end of the string we have to copy */ j+=2; /* Points to the char behind the last ellipsis */ k=EndOfLine-1; while ((LineWidth+StringDetails[k].Width)<FrameWidth) { LineWidth+=StringDetails[k].Width; k--; } memcpy (&CleanString[j], &CleanString[k+1], sizeof(WCHAR)*(EndOfLine-k-1)); CurrentLineStart->LineLen+=EndOfLine-k-1; } } else { #ifdef DRAWSTRING_DEBUG /* Just cut off the text */ printf("End of line at index:%d\n", EndOfLine); #endif CurrentLineStart->LineLen=EndOfLine; } if ((format->formatFlags & StringFormatFlagsNoWrap)!=0) { // Avoid endless loops, always print at least one char if (CurrentLineStart->LineLen == 0) { CurrentLineStart->LineLen = 1; } break; } /* avoid endless loop when wrapping is allowed */ if (CurrentLineStart->LineLen == 0) { CurrentLineStart->LineLen = 1; } /* New line */ CurrentLineStart=&(StringDetails[EndOfLine]); CurrentLineStart->Flags|=STRING_DETAIL_LINESTART; CurrentLineStart->LineLen=0; /* Generate CursorX/Y for new line */ CursorY+=LineHeight; CursorX=CurrentLineStart->Width; i=EndOfLine; CurrentDetail=&(StringDetails[EndOfLine]); CurrentDetail->PosX=0; CurrentDetail->PosY=CursorY; } } /* Still visible? */ if ((FrameWidth && CursorX>FrameWidth) || (FrameHeight && ((CursorY>FrameHeight) || ((format->formatFlags & StringFormatFlagsLineLimit) && (CursorY+LineHeight)>FrameHeight)))) { CurrentDetail->Flags|=STRING_DETAIL_HIDDEN; #ifdef DRAWSTRING_DEBUG if (CurrentDetail->Flags & STRING_DETAIL_LINESTART) { printf("<LSTART-H>"); } else { printf("<H>"); } #endif } else { if (MaxY<CursorY) { MaxY=CursorY; } } #ifdef DRAWSTRING_DEBUG if (i % 3 == 2) { printf("\n"); } #endif CurrentDetail++; CurrentLineStart->LineLen++; } /* We ignored it above, for shorter of calculations, also, add a bit of padding */ MaxY+=LineHeight+FontExtent.descent; #ifdef DRAWSTRING_DEBUG printf("\n"); printf("Bounding box: %d x %d\n", MaxX, MaxY); printf("Line layout [Total len %d]:\n", StringLen); for (i=0; i<StringLen; i++) { if (StringDetails[i].Flags & STRING_DETAIL_LF) { for (j=0; j<StringDetails[i].Linefeeds; j++) { printf("\n"); } } if (StringDetails[i].Flags & STRING_DETAIL_LINESTART) { printf("[Len %2d %dx%d] ", StringDetails[i].LineLen, (int)StringDetails[i].PosX, (int)StringDetails[i].PosY); for (j=0; j<StringDetails[i].LineLen; j++) { printf("%c", CleanString[i+j]); } if (j == 0) { break; } i+=j-1; printf("\n"); } } #endif /* Prepare alignment handling */ AlignHorz = format->alignment; if (format->formatFlags & StringFormatFlagsDirectionRightToLeft) { if (format->alignment==StringAlignmentNear) { AlignHorz=StringAlignmentFar; } else if (format->alignment==StringAlignmentFar) { AlignHorz=StringAlignmentNear; } } AlignVert = format->lineAlignment; /* At this point we know our bounding box, what characters are to be displayed and where every character goes */ if (boundingBox) { boundingBox->X = rc->X; boundingBox->Y = rc->Y; if (format->formatFlags & StringFormatFlagsDirectionVertical) { boundingBox->Width = MaxY; boundingBox->Height = MaxX; } else { boundingBox->Width = MaxX; boundingBox->Height = MaxY; } if ((rc->Width > 0) && (boundingBox->Width > rc->Width)) { boundingBox->Width = rc->Width; } if ((rc->Height > 0) && (boundingBox->Height > rc->Height)) { boundingBox->Height = rc->Height; } /* avoid conversion computations if possible */ if (!OPTIMIZE_CONVERSION (graphics)) { boundingBox->X = gdip_convgr_unitx (graphics, boundingBox->X); boundingBox->Y = gdip_convgr_unity (graphics, boundingBox->Y); boundingBox->Width = gdip_convgr_unitx (graphics, boundingBox->Width); boundingBox->Height = gdip_convgr_unity (graphics, boundingBox->Height); } switch (AlignVert) { case StringAlignmentCenter: if (format->formatFlags & StringFormatFlagsDirectionVertical) { boundingBox->X += (FrameHeight - MaxY) * 0.5; } else { boundingBox->Y += (FrameHeight - MaxY) * 0.5; } break; case StringAlignmentFar: if (format->formatFlags & StringFormatFlagsDirectionVertical) { boundingBox->X += (FrameHeight - MaxY); } else { boundingBox->Y += (FrameHeight - MaxY); } break; } switch (AlignHorz) { case StringAlignmentCenter: if (format->formatFlags & StringFormatFlagsDirectionVertical) { boundingBox->Y += (FrameWidth - MaxX) * 0.5; } else { boundingBox->X += (FrameWidth - MaxX) * 0.5; } break; case StringAlignmentFar: if (format->formatFlags & StringFormatFlagsDirectionVertical) { boundingBox->Y += (FrameWidth - MaxX); } else { boundingBox->X += (FrameWidth - MaxX); } break; } } if (codepointsFitted) { /* how many characters from the string can be drawn in the boundingBox (#76664) */ double max_width = boundingBox ? (boundingBox->X + boundingBox->Width) : rc->X + min (MaxX, rc->Width); double max_height = boundingBox ? (boundingBox->Y + boundingBox->Height) : rc->Y + min (MaxY, rc->Height); int charactersFitted; for (charactersFitted = 0; charactersFitted < StringLen; charactersFitted++) { if ((StringDetails[charactersFitted].PosX + StringDetails[charactersFitted].Width) > max_width) break; if (StringDetails[charactersFitted].PosY + LineHeight > max_height) break; } *codepointsFitted = charactersFitted; } if (linesFilled) { /* how many *complete* lines fits in our calculated boundingBox */ double height = (boundingBox) ? boundingBox->Height : min (MaxY, rc->Height); *linesFilled = floor (height / LineHeight); } if (AlignHorz != StringAlignmentNear || AlignVert != StringAlignmentNear) { // Update alignment int length = 0; int current_line_length = 0; for (i = 0; i < StringLen; i++) { if (i == current_line_length) { length = StringDetails[i].LineLen; current_line_length = min(length + i, StringLen); } switch (AlignHorz) { case StringAlignmentNear: break; case StringAlignmentCenter: if ((current_line_length == 1) || (StringDetails [current_line_length - 1].PosX > 0)) { StringDetails[i].PosX += (FrameWidth - StringDetails [current_line_length - 1].PosX - StringDetails [current_line_length - 1].Width) / 2; } break; case StringAlignmentFar: StringDetails[i].PosX += FrameWidth - StringDetails [current_line_length - 1].PosX - StringDetails [current_line_length - 1].Width; break; } switch (AlignVert) { case StringAlignmentNear: break; case StringAlignmentCenter: StringDetails[i].PosY += (FrameHeight - MaxY) / 2; break; case StringAlignmentFar: StringDetails[i].PosY += FrameHeight - MaxY; break; } } } /* if asked, supply extra data to be reused when drawing the same string */ if (data) { data->align_horz = AlignHorz; data->align_vert = AlignVert; data->line_height = LineHeight; data->max_y = MaxY; data->descent = FontExtent.descent; } return Ok; }
/* * render functions */ static void begin_render(DiaRenderer *self) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); if (renderer->surface) renderer->cr = cairo_create (renderer->surface); else g_assert (renderer->cr); cairo_scale (renderer->cr, renderer->scale, renderer->scale); cairo_translate (renderer->cr, -renderer->dia->extents.left, -renderer->dia->extents.top); /* clear background */ if (renderer->with_alpha) { cairo_set_operator (renderer->cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_rgba (renderer->cr, renderer->dia->bg_color.red, renderer->dia->bg_color.green, renderer->dia->bg_color.blue, 0.0); } else { cairo_set_source_rgba (renderer->cr, renderer->dia->bg_color.red, renderer->dia->bg_color.green, renderer->dia->bg_color.blue, 1.0); } cairo_paint (renderer->cr); if (renderer->with_alpha) { /* restore to default drawing */ cairo_set_operator (renderer->cr, CAIRO_OPERATOR_OVER); cairo_set_source_rgba (renderer->cr, renderer->dia->bg_color.red, renderer->dia->bg_color.green, renderer->dia->bg_color.blue, 1.0); } #ifdef HAVE_PANGOCAIRO_H if (!renderer->layout) renderer->layout = pango_cairo_create_layout (renderer->cr); #endif cairo_set_fill_rule (renderer->cr, CAIRO_FILL_RULE_EVEN_ODD); #if 0 /* try to work around bug #341481 - no luck */ { cairo_font_options_t *fo = cairo_font_options_create (); cairo_get_font_options (renderer->cr, fo); /* try to switch off kerning */ cairo_font_options_set_hint_style (fo, CAIRO_HINT_STYLE_NONE); cairo_font_options_set_hint_metrics (fo, CAIRO_HINT_METRICS_OFF); cairo_set_font_options (renderer->cr, fo); cairo_font_options_destroy (fo); #ifdef HAVE_PANGOCAIRO_H pango_cairo_update_context (renderer->cr, pango_layout_get_context (renderer->layout)); pango_layout_context_changed (renderer->layout); #endif } #endif DIAG_STATE(renderer->cr) }
int main(int argc, char * argv[]) { double width = 320, height = 240; double f, delta = 0.125; cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *crc = cairo_create(surface); cairo_text_extents_t extents; cairo_font_options_t* font; // Set up font (face is second field in 'xlsfonts'; first field is foundry) font = cairo_font_options_create(); cairo_font_options_set_antialias(font, CAIRO_ANTIALIAS_SUBPIXEL); cairo_set_font_options(crc, font); cairo_select_font_face(crc, "nimbus sans l", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_set_font_size(crc, 16); cairo_font_options_destroy(font); // Background cairo_rectangle(crc, 0, 0, width, height); cairo_set_source_rgb(crc, 1, 1, 1); cairo_fill(crc); // Fill cairo_move_to(crc, 0, 220); for (f = -4; f < 4; f += delta) { double v = exp(-f * f / 2) / sqrt(2 * M_PI); cairo_line_to(crc, width * (f + 4) / 8, 220 - v * height); } cairo_close_path(crc); cairo_set_source_rgb(crc, 122 / 255.0, 143 / 255.0, 248 / 255.0); cairo_fill(crc); // Graph cairo_move_to(crc, 0, 220); for (f = -4; f < 4; f += delta) { double v = exp(-f * f / 2) / sqrt(2 * M_PI); cairo_line_to(crc, width * (f + 4) / 8, 220 - v * height); } cairo_set_line_width(crc, 2); cairo_set_source_rgb(crc, 7 / 255.0, 16 / 255.0, 141 / 255.0); cairo_stroke(crc); // Vertical Axis cairo_set_source_rgb(crc, 0, 0, 0); cairo_move_to(crc, width / 2, 0); cairo_line_to(crc, width / 2, height); cairo_stroke(crc); // Horizontal Axis cairo_move_to(crc, 0, 220); cairo_line_to(crc, width, 220); cairo_stroke(crc); // Horizontal Ticks cairo_set_line_width(crc, 1); for (f = -4; f < 4; f++) { cairo_move_to(crc, width * (f + 4) / 8, 220 - 5); cairo_line_to(crc, width * (f + 4) / 8, 220 + 5); cairo_stroke(crc); if (f > -4 && f != 0 && f < +4) { char str[] = "+3"; if (f > 0) sprintf(str, "%d", (int) f); else sprintf(str, "%d", (int) f); cairo_text_extents(crc, str, &extents); cairo_move_to(crc, width * (f + 4) / 8 - extents.width / 2, 220 + 7 + extents.height); cairo_show_text(crc, str); } } // Vertical Ticks for (f = +1; f >= -1; f -= 0.1) { cairo_move_to(crc, width / 2 - 5, 220 + f * height); cairo_line_to(crc, width / 2 + 5, 220 + f * height); cairo_stroke(crc); } cairo_text_extents(crc, "0.5", &extents); cairo_move_to(crc, width / 2 + 7, 220 - 0.5 * height + extents.height / 2); cairo_show_text(crc, "0.5"); cairo_surface_write_to_png(surface, "gauss.png"); return 0; }
/* * render functions */ static void begin_render(DiaRenderer *self, const Rectangle *update) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); real onedu = 0.0; real lmargin = 0.0, tmargin = 0.0; gboolean paginated = renderer->surface && /* only with our own pagination, not GtkPrint */ cairo_surface_get_type (renderer->surface) == CAIRO_SURFACE_TYPE_PDF && !renderer->skip_show_page; if (renderer->surface && !renderer->cr) renderer->cr = cairo_create (renderer->surface); else g_assert (renderer->cr); /* remember current state, so we can start from new with every page */ cairo_save (renderer->cr); if (paginated && renderer->dia) { DiagramData *data = renderer->dia; /* Dia's paper.width already contains the scale, cairo needs it without * Similar for margins, Dia's without, but cairo wants them? */ real width = (data->paper.lmargin + data->paper.width * data->paper.scaling + data->paper.rmargin) * (72.0 / 2.54) + 0.5; real height = (data->paper.tmargin + data->paper.height * data->paper.scaling + data->paper.bmargin) * (72.0 / 2.54) + 0.5; /* "Changes the size of a PDF surface for the current (and * subsequent) pages." Pagination setup? */ cairo_pdf_surface_set_size (renderer->surface, width, height); lmargin = data->paper.lmargin / data->paper.scaling; tmargin = data->paper.tmargin / data->paper.scaling; } cairo_scale (renderer->cr, renderer->scale, renderer->scale); /* to ensure no clipping at top/left we need some extra gymnastics, * otherwise a box with a line witdh one one pixel might loose the * top/left border as in bug #147386 */ ensure_minimum_one_device_unit (renderer, &onedu); if (update && paginated) { cairo_rectangle (renderer->cr, lmargin, tmargin, update->right - update->left, update->bottom - update->top); cairo_clip (renderer->cr); cairo_translate (renderer->cr, -update->left + lmargin, -update->top + tmargin); } else cairo_translate (renderer->cr, -renderer->dia->extents.left + onedu, -renderer->dia->extents.top + onedu); /* no more blurred UML diagrams */ cairo_set_antialias (renderer->cr, CAIRO_ANTIALIAS_NONE); /* clear background */ if (renderer->with_alpha) { cairo_set_operator (renderer->cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_rgba (renderer->cr, renderer->dia->bg_color.red, renderer->dia->bg_color.green, renderer->dia->bg_color.blue, 0.0); } else { cairo_set_source_rgba (renderer->cr, renderer->dia->bg_color.red, renderer->dia->bg_color.green, renderer->dia->bg_color.blue, 1.0); } cairo_paint (renderer->cr); if (renderer->with_alpha) { /* restore to default drawing */ cairo_set_operator (renderer->cr, CAIRO_OPERATOR_OVER); cairo_set_source_rgba (renderer->cr, renderer->dia->bg_color.red, renderer->dia->bg_color.green, renderer->dia->bg_color.blue, 1.0); } #ifdef HAVE_PANGOCAIRO_H if (!renderer->layout) renderer->layout = pango_cairo_create_layout (renderer->cr); #endif cairo_set_fill_rule (renderer->cr, CAIRO_FILL_RULE_EVEN_ODD); #if 0 /* try to work around bug #341481 - no luck */ { cairo_font_options_t *fo = cairo_font_options_create (); cairo_get_font_options (renderer->cr, fo); /* try to switch off kerning */ cairo_font_options_set_hint_style (fo, CAIRO_HINT_STYLE_NONE); cairo_font_options_set_hint_metrics (fo, CAIRO_HINT_METRICS_OFF); cairo_set_font_options (renderer->cr, fo); cairo_font_options_destroy (fo); #ifdef HAVE_PANGOCAIRO_H pango_cairo_update_context (renderer->cr, pango_layout_get_context (renderer->layout)); pango_layout_context_changed (renderer->layout); #endif } #endif DIAG_STATE(renderer->cr) }
bool TextPainter::prepareBuffer() { if (_cairoWidth <= 0 || _cairoHeight <= 0) return false; if (_context) cairo_destroy(_context); if (_surface) cairo_surface_destroy(_surface); // ensure a valid opengl context OpenGl::Guard guard; // bind buffer for writing glCheck(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, _buf)); // discard previous buffer (so we don't have to wait for GPU until we can // map) and create new buffer glCheck(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, _cairoWidth*_cairoHeight*sizeof(cairo_pixel_t), 0, GL_DYNAMIC_DRAW)); // bind buffer for reading glCheck(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, _buf)); LOG_ALL(textpainterlog) << "determine raster position of " << _glRoi.minX + 1.0/_lastResolution.x << ", " << _glRoi.maxY - 1.0/_lastResolution.y << " [gl]" << std::endl; // get the window coordinates of the lower-left corner of the rectangle we // want to draw to int r[4]; glCheck(glRasterPos2f(_glRoi.minX + 1.0/_lastResolution.x, _glRoi.maxY - 1.0/_lastResolution.y)); glCheck(glGetIntegerv(GL_CURRENT_RASTER_POSITION, r)); _rasterPos.x = r[0]; _rasterPos.y = r[1]; LOG_ALL(textpainterlog) << "read content from raster position " << _rasterPos << std::endl; // load current content to buffer glCheck(glReadPixels( _rasterPos.x, _rasterPos.y, _cairoWidth, _cairoHeight, detail::pixel_format_traits<cairo_pixel_t>::gl_format, detail::pixel_format_traits<cairo_pixel_t>::gl_type, 0)); // map the pixel buffer object unsigned char* p = (unsigned char*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB); // wrap the buffer in a cairo surface _surface = cairo_image_surface_create_for_data( p, CAIRO_FORMAT_ARGB32, _cairoWidth, _cairoHeight, cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, _cairoWidth)); // create a context for the surface _context = cairo_create(_surface); // set antialiasing options cairo_set_font_options(_context, _fontOptions); return true; }
static cairo_test_status_t draw (cairo_t *cr, int width, int height) { const cairo_test_context_t *ctx = cairo_test_get_context (cr); FcPattern *pattern; cairo_font_face_t *font_face; cairo_font_extents_t font_extents; cairo_font_options_t *font_options; cairo_status_t status; char *filename; int face_count; struct stat stat_buf; xasprintf (&filename, "%s/%s", ctx->srcdir, FONT); if (stat (filename, &stat_buf) || ! S_ISREG (stat_buf.st_mode)) { cairo_test_log (ctx, "Error finding font: %s: file not found?\n", filename); return CAIRO_TEST_FAILURE; } pattern = FcFreeTypeQuery ((unsigned char *)filename, 0, NULL, &face_count); free (filename); if (! pattern) { cairo_test_log (ctx, "FcFreeTypeQuery failed.\n"); return cairo_test_status_from_status (ctx, CAIRO_STATUS_NO_MEMORY); } font_face = cairo_ft_font_face_create_for_pattern (pattern); FcPatternDestroy (pattern); status = cairo_font_face_status (font_face); if (status) { cairo_test_log (ctx, "Error creating font face for %s: %s\n", filename, cairo_status_to_string (status)); return cairo_test_status_from_status (ctx, status); } if (cairo_font_face_get_type (font_face) != CAIRO_FONT_TYPE_FT) { cairo_test_log (ctx, "Unexpected value from cairo_font_face_get_type: %d (expected %d)\n", cairo_font_face_get_type (font_face), CAIRO_FONT_TYPE_FT); cairo_font_face_destroy (font_face); return CAIRO_TEST_FAILURE; } cairo_set_font_face (cr, font_face); cairo_font_face_destroy (font_face); font_options = cairo_font_options_create (); #define CHECK_FONT_EXTENTS(comment) do {\ cairo_test_status_t test_status; \ test_status = check_font_extents (ctx, cr, (comment)); \ if (test_status != CAIRO_TEST_SUCCESS) { \ cairo_font_options_destroy (font_options); \ return test_status; \ } \ } while (0) cairo_font_extents (cr, &font_extents); CHECK_FONT_EXTENTS ("default"); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_ON); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_ON"); cairo_move_to (cr, 1, font_extents.ascent - 1); cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); /* blue */ cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_NONE"); cairo_show_text (cr, "the "); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_SLIGHT); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_SLIGHT"); cairo_show_text (cr, "quick "); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_MEDIUM); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_MEDIUM"); cairo_show_text (cr, "brown"); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_FULL); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_FULL"); cairo_show_text (cr, " fox"); /* Switch from show_text to text_path/fill to exercise bug #7889 */ cairo_text_path (cr, " jumps over a lazy dog"); cairo_fill (cr); /* And test it rotated as well for the sake of bug #7888 */ cairo_translate (cr, width, height); cairo_rotate (cr, M_PI); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_DEFAULT); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_OFF"); cairo_move_to (cr, 1, font_extents.height - font_extents.descent - 1); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_NONE"); cairo_show_text (cr, "the "); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_SLIGHT); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_SLIGHT"); cairo_show_text (cr, "quick"); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_MEDIUM); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_MEDIUM"); cairo_show_text (cr, " brown"); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_FULL); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_FULL"); cairo_show_text (cr, " fox"); cairo_text_path (cr, " jumps over"); cairo_text_path (cr, " a lazy dog"); cairo_fill (cr); cairo_font_options_destroy (font_options); return CAIRO_TEST_SUCCESS; }
static cairo_test_status_t cairo_test_for_target (cairo_test_context_t *ctx, const cairo_boilerplate_target_t *target, int dev_offset, cairo_bool_t similar) { cairo_test_status_t status; cairo_surface_t *surface = NULL; cairo_t *cr; const char *empty_str = ""; char *offset_str; char *base_name, *base_path; char *out_png_path; char *ref_path = NULL, *ref_png_path, *cmp_png_path = NULL; char *new_path = NULL, *new_png_path; char *xfail_path = NULL, *xfail_png_path; char *base_ref_png_path; char *base_new_png_path; char *base_xfail_png_path; char *diff_png_path; char *test_filename = NULL, *pass_filename = NULL, *fail_filename = NULL; cairo_test_status_t ret; cairo_content_t expected_content; cairo_font_options_t *font_options; const char *format; cairo_bool_t have_output = FALSE; cairo_bool_t have_result = FALSE; void *closure; double width, height; cairo_bool_t have_output_dir; #if HAVE_MEMFAULT int malloc_failure_iterations = ctx->malloc_failure; int last_fault_count = 0; #endif /* Get the strings ready that we'll need. */ format = cairo_boilerplate_content_name (target->content); if (dev_offset) xasprintf (&offset_str, ".%d", dev_offset); else offset_str = (char *) empty_str; xasprintf (&base_name, "%s.%s.%s%s%s", ctx->test_name, target->name, format, similar ? ".similar" : "", offset_str); if (offset_str != empty_str) free (offset_str); ref_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_REF_SUFFIX, CAIRO_TEST_PNG_EXTENSION); new_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_NEW_SUFFIX, CAIRO_TEST_PNG_EXTENSION); xfail_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_XFAIL_SUFFIX, CAIRO_TEST_PNG_EXTENSION); base_ref_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, NULL, NULL, format, CAIRO_TEST_REF_SUFFIX, CAIRO_TEST_PNG_EXTENSION); base_new_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, NULL, NULL, format, CAIRO_TEST_NEW_SUFFIX, CAIRO_TEST_PNG_EXTENSION); base_xfail_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, NULL, NULL, format, CAIRO_TEST_XFAIL_SUFFIX, CAIRO_TEST_PNG_EXTENSION); if (target->file_extension != NULL) { ref_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_REF_SUFFIX, target->file_extension); new_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_NEW_SUFFIX, target->file_extension); xfail_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_XFAIL_SUFFIX, target->file_extension); } have_output_dir = _cairo_test_mkdir (ctx->output); xasprintf (&base_path, "%s/%s", have_output_dir ? ctx->output : ".", base_name); xasprintf (&out_png_path, "%s" CAIRO_TEST_OUT_PNG, base_path); xasprintf (&diff_png_path, "%s" CAIRO_TEST_DIFF_PNG, base_path); if (ctx->test->requirements != NULL) { const char *required; required = target->is_vector ? "target=raster" : "target=vector"; if (strstr (ctx->test->requirements, required) != NULL) { cairo_test_log (ctx, "Error: Skipping for %s target %s\n", target->is_vector ? "vector" : "raster", target->name); ret = CAIRO_TEST_UNTESTED; goto UNWIND_STRINGS; } required = target->is_recording ? "target=!recording" : "target=recording"; if (strstr (ctx->test->requirements, required) != NULL) { cairo_test_log (ctx, "Error: Skipping for %s target %s\n", target->is_recording ? "recording" : "non-recording", target->name); ret = CAIRO_TEST_UNTESTED; goto UNWIND_STRINGS; } } width = ctx->test->width; height = ctx->test->height; if (width && height) { width += dev_offset; height += dev_offset; } #if HAVE_MEMFAULT REPEAT: MEMFAULT_CLEAR_FAULTS (); MEMFAULT_RESET_LEAKS (); ctx->last_fault_count = 0; last_fault_count = MEMFAULT_COUNT_FAULTS (); /* Pre-initialise fontconfig so that the configuration is loaded without * malloc failures (our primary goal is to test cairo fault tolerance). */ #if HAVE_FCINIT FcInit (); #endif MEMFAULT_ENABLE_FAULTS (); #endif have_output = FALSE; have_result = FALSE; /* Run the actual drawing code. */ ret = CAIRO_TEST_SUCCESS; surface = (target->create_surface) (base_path, target->content, width, height, ctx->test->width + 25 * NUM_DEVICE_OFFSETS, ctx->test->height + 25 * NUM_DEVICE_OFFSETS, CAIRO_BOILERPLATE_MODE_TEST, &closure); if (surface == NULL) { cairo_test_log (ctx, "Error: Failed to set %s target\n", target->name); ret = CAIRO_TEST_UNTESTED; goto UNWIND_STRINGS; } #if HAVE_MEMFAULT if (ctx->malloc_failure && MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 && cairo_surface_status (surface) == CAIRO_STATUS_NO_MEMORY) { goto REPEAT; } #endif if (cairo_surface_status (surface)) { MF (MEMFAULT_PRINT_FAULTS ()); cairo_test_log (ctx, "Error: Created an error surface: %s\n", cairo_status_to_string (cairo_surface_status (surface))); ret = CAIRO_TEST_FAILURE; goto UNWIND_STRINGS; } /* Check that we created a surface of the expected type. */ if (cairo_surface_get_type (surface) != target->expected_type) { MF (MEMFAULT_PRINT_FAULTS ()); cairo_test_log (ctx, "Error: Created surface is of type %d (expected %d)\n", cairo_surface_get_type (surface), target->expected_type); ret = CAIRO_TEST_UNTESTED; goto UNWIND_SURFACE; } /* Check that we created a surface of the expected content, * (ignore the artificial CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED value). */ expected_content = cairo_boilerplate_content (target->content); if (cairo_surface_get_content (surface) != expected_content) { MF (MEMFAULT_PRINT_FAULTS ()); cairo_test_log (ctx, "Error: Created surface has content %d (expected %d)\n", cairo_surface_get_content (surface), expected_content); ret = CAIRO_TEST_FAILURE; goto UNWIND_SURFACE; } if (cairo_surface_set_user_data (surface, &cairo_boilerplate_output_basename_key, base_path, NULL)) { #if HAVE_MEMFAULT cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); goto REPEAT; #else ret = CAIRO_TEST_FAILURE; goto UNWIND_SURFACE; #endif } cairo_surface_set_device_offset (surface, dev_offset, dev_offset); cr = cairo_create (surface); if (cairo_set_user_data (cr, &_cairo_test_context_key, (void*) ctx, NULL)) { #if HAVE_MEMFAULT cairo_destroy (cr); cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); goto REPEAT; #else ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; #endif } if (similar) cairo_push_group_with_content (cr, expected_content); /* Clear to transparent (or black) depending on whether the target * surface supports alpha. */ cairo_save (cr); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint (cr); cairo_restore (cr); /* Set all components of font_options to avoid backend differences * and reduce number of needed reference images. */ font_options = cairo_font_options_create (); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_ON); cairo_font_options_set_antialias (font_options, CAIRO_ANTIALIAS_GRAY); cairo_set_font_options (cr, font_options); cairo_font_options_destroy (font_options); cairo_save (cr); alarm (ctx->timeout); status = (ctx->test->draw) (cr, ctx->test->width, ctx->test->height); alarm (0); cairo_restore (cr); if (similar) { cairo_pop_group_to_source (cr); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_paint (cr); } #if HAVE_MEMFAULT MEMFAULT_DISABLE_FAULTS (); /* repeat test after malloc failure injection */ if (ctx->malloc_failure && MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 && (status == CAIRO_TEST_NO_MEMORY || cairo_status (cr) == CAIRO_STATUS_NO_MEMORY || cairo_surface_status (surface) == CAIRO_STATUS_NO_MEMORY)) { cairo_destroy (cr); cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); cairo_debug_reset_static_data (); #if HAVE_FCFINI FcFini (); #endif if (MEMFAULT_COUNT_LEAKS () > 0) { MEMFAULT_PRINT_FAULTS (); MEMFAULT_PRINT_LEAKS (); } goto REPEAT; } #endif /* Then, check all the different ways it could fail. */ if (status) { cairo_test_log (ctx, "Error: Function under test failed\n"); ret = status; goto UNWIND_CAIRO; } #if HAVE_MEMFAULT if (MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 && MEMFAULT_HAS_FAULTS ()) { VALGRIND_PRINTF ("Unreported memfaults..."); MEMFAULT_PRINT_FAULTS (); } #endif if (target->finish_surface != NULL) { #if HAVE_MEMFAULT /* We need to re-enable faults as most recording-surface processing * is done during cairo_surface_finish(). */ MEMFAULT_CLEAR_FAULTS (); last_fault_count = MEMFAULT_COUNT_FAULTS (); MEMFAULT_ENABLE_FAULTS (); #endif /* also check for infinite loops whilst replaying */ alarm (ctx->timeout); status = target->finish_surface (surface); alarm (0); #if HAVE_MEMFAULT MEMFAULT_DISABLE_FAULTS (); if (ctx->malloc_failure && MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 && status == CAIRO_STATUS_NO_MEMORY) { cairo_destroy (cr); cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); cairo_debug_reset_static_data (); #if HAVE_FCFINI FcFini (); #endif if (MEMFAULT_COUNT_LEAKS () > 0) { MEMFAULT_PRINT_FAULTS (); MEMFAULT_PRINT_LEAKS (); } goto REPEAT; } #endif if (status) { cairo_test_log (ctx, "Error: Failed to finish surface: %s\n", cairo_status_to_string (status)); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } } /* Skip image check for tests with no image (width,height == 0,0) */ if (ctx->test->width != 0 && ctx->test->height != 0) { cairo_surface_t *ref_image; cairo_surface_t *test_image; cairo_surface_t *diff_image; buffer_diff_result_t result; cairo_status_t diff_status; if (ref_png_path == NULL) { cairo_test_log (ctx, "Error: Cannot find reference image for %s\n", base_name); /* we may be running this test to generate reference images */ _xunlink (ctx, out_png_path); /* be more generous as we may need to use external renderers */ alarm (4 * ctx->timeout); test_image = target->get_image_surface (surface, 0, ctx->test->width, ctx->test->height); alarm (0); diff_status = cairo_surface_write_to_png (test_image, out_png_path); cairo_surface_destroy (test_image); if (diff_status) { if (cairo_surface_status (test_image) == CAIRO_STATUS_INVALID_STATUS) ret = CAIRO_TEST_CRASHED; else ret = CAIRO_TEST_FAILURE; cairo_test_log (ctx, "Error: Failed to write output image: %s\n", cairo_status_to_string (diff_status)); } have_output = TRUE; ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } if (target->file_extension != NULL) { /* compare vector surfaces */ char *filenames[] = { ref_png_path, ref_path, new_png_path, new_path, xfail_png_path, xfail_path, base_ref_png_path, base_new_png_path, base_xfail_png_path, }; xasprintf (&test_filename, "%s.out%s", base_path, target->file_extension); xasprintf (&pass_filename, "%s.pass%s", base_path, target->file_extension); xasprintf (&fail_filename, "%s.fail%s", base_path, target->file_extension); if (cairo_test_file_is_older (pass_filename, filenames, ARRAY_SIZE (filenames))) { _xunlink (ctx, pass_filename); } if (cairo_test_file_is_older (fail_filename, filenames, ARRAY_SIZE (filenames))) { _xunlink (ctx, fail_filename); } if (cairo_test_files_equal (out_png_path, ref_path)) { cairo_test_log (ctx, "Vector surface matches reference.\n"); have_output = FALSE; ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, new_path)) { cairo_test_log (ctx, "Vector surface matches current failure.\n"); have_output = FALSE; ret = CAIRO_TEST_NEW; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, xfail_path)) { cairo_test_log (ctx, "Vector surface matches known failure.\n"); have_output = FALSE; ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } if (cairo_test_files_equal (test_filename, pass_filename)) { /* identical output as last known PASS */ cairo_test_log (ctx, "Vector surface matches last pass.\n"); have_output = TRUE; ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (test_filename, fail_filename)) { /* identical output as last known FAIL, fail */ cairo_test_log (ctx, "Vector surface matches last fail.\n"); have_result = TRUE; /* presume these were kept around as well */ have_output = TRUE; ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } } /* be more generous as we may need to use external renderers */ alarm (4 * ctx->timeout); test_image = target->get_image_surface (surface, 0, ctx->test->width, ctx->test->height); alarm (0); if (cairo_surface_status (test_image)) { cairo_test_log (ctx, "Error: Failed to extract image: %s\n", cairo_status_to_string (cairo_surface_status (test_image))); if (cairo_surface_status (test_image) == CAIRO_STATUS_INVALID_STATUS) ret = CAIRO_TEST_CRASHED; else ret = CAIRO_TEST_FAILURE; cairo_surface_destroy (test_image); goto UNWIND_CAIRO; } _xunlink (ctx, out_png_path); diff_status = cairo_surface_write_to_png (test_image, out_png_path); if (diff_status) { cairo_test_log (ctx, "Error: Failed to write output image: %s\n", cairo_status_to_string (diff_status)); cairo_surface_destroy (test_image); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } have_output = TRUE; /* binary compare png files (no decompression) */ if (target->file_extension == NULL) { char *filenames[] = { ref_png_path, new_png_path, xfail_png_path, base_ref_png_path, base_new_png_path, base_xfail_png_path, }; xasprintf (&test_filename, "%s", out_png_path); xasprintf (&pass_filename, "%s.pass.png", base_path); xasprintf (&fail_filename, "%s.fail.png", base_path); if (cairo_test_file_is_older (pass_filename, filenames, ARRAY_SIZE (filenames))) { _xunlink (ctx, pass_filename); } if (cairo_test_file_is_older (fail_filename, filenames, ARRAY_SIZE (filenames))) { _xunlink (ctx, fail_filename); } if (cairo_test_files_equal (test_filename, pass_filename)) { cairo_test_log (ctx, "PNG file exactly matches last pass.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, ref_png_path)) { cairo_test_log (ctx, "PNG file exactly matches reference image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, new_png_path)) { cairo_test_log (ctx, "PNG file exactly matches current failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_NEW; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, xfail_png_path)) { cairo_test_log (ctx, "PNG file exactly matches known failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } if (cairo_test_files_equal (test_filename, fail_filename)) { cairo_test_log (ctx, "PNG file exactly matches last fail.\n"); have_result = TRUE; /* presume these were kept around as well */ cairo_surface_destroy (test_image); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } } else { if (cairo_test_files_equal (out_png_path, ref_png_path)) { cairo_test_log (ctx, "PNG file exactly matches reference image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, new_png_path)) { cairo_test_log (ctx, "PNG file exactly matches current failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_NEW; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, xfail_png_path)) { cairo_test_log (ctx, "PNG file exactly matches known failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } } if (cairo_test_files_equal (out_png_path, base_ref_png_path)) { cairo_test_log (ctx, "PNG file exactly reference image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, base_new_png_path)) { cairo_test_log (ctx, "PNG file exactly current failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_NEW; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, base_xfail_png_path)) { cairo_test_log (ctx, "PNG file exactly known failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } /* first compare against the ideal reference */ ref_image = cairo_test_get_reference_image (ctx, base_ref_png_path, target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED); if (cairo_surface_status (ref_image)) { cairo_test_log (ctx, "Error: Cannot open reference image for %s: %s\n", base_ref_png_path, cairo_status_to_string (cairo_surface_status (ref_image))); cairo_surface_destroy (test_image); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } diff_image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ctx->test->width, ctx->test->height); cmp_png_path = base_ref_png_path; diff_status = image_diff (ctx, test_image, ref_image, diff_image, &result); _xunlink (ctx, diff_png_path); if (diff_status || image_diff_is_failure (&result, target->error_tolerance)) { /* that failed, so check against the specific backend */ ref_image = cairo_test_get_reference_image (ctx, ref_png_path, target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED); if (cairo_surface_status (ref_image)) { cairo_test_log (ctx, "Error: Cannot open reference image for %s: %s\n", ref_png_path, cairo_status_to_string (cairo_surface_status (ref_image))); cairo_surface_destroy (test_image); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } cmp_png_path = ref_png_path; diff_status = image_diff (ctx, test_image, ref_image, diff_image, &result); if (diff_status) { cairo_test_log (ctx, "Error: Failed to compare images: %s\n", cairo_status_to_string (diff_status)); ret = CAIRO_TEST_FAILURE; } else if (image_diff_is_failure (&result, target->error_tolerance)) { ret = CAIRO_TEST_FAILURE; diff_status = cairo_surface_write_to_png (diff_image, diff_png_path); if (diff_status) { cairo_test_log (ctx, "Error: Failed to write differences image: %s\n", cairo_status_to_string (diff_status)); } else { have_result = TRUE; } cairo_test_copy_file (test_filename, fail_filename); } else { /* success */ cairo_test_copy_file (test_filename, pass_filename); } } else { /* success */ cairo_test_copy_file (test_filename, pass_filename); } /* If failed, compare against the current image output, * and attempt to detect systematic failures. */ if (ret == CAIRO_TEST_FAILURE) { char *image_out_path; image_out_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, "image", "image", format, CAIRO_TEST_OUT_SUFFIX, CAIRO_TEST_PNG_EXTENSION); if (image_out_path != NULL) { if (cairo_test_files_equal (out_png_path, image_out_path)) { ret = CAIRO_TEST_XFAILURE; } else { ref_image = cairo_image_surface_create_from_png (image_out_path); if (cairo_surface_status (ref_image) == CAIRO_STATUS_SUCCESS) { diff_status = image_diff (ctx, test_image, ref_image, diff_image, &result); if (diff_status == CAIRO_STATUS_SUCCESS && !image_diff_is_failure (&result, target->error_tolerance)) { ret = CAIRO_TEST_XFAILURE; } cairo_surface_destroy (ref_image); } } free (image_out_path); } } cairo_surface_destroy (test_image); cairo_surface_destroy (diff_image); } if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) { cairo_test_log (ctx, "Error: Function under test left cairo status in an error state: %s\n", cairo_status_to_string (cairo_status (cr))); ret = CAIRO_TEST_ERROR; goto UNWIND_CAIRO; } UNWIND_CAIRO: free (test_filename); free (fail_filename); free (pass_filename); test_filename = fail_filename = pass_filename = NULL; #if HAVE_MEMFAULT if (ret == CAIRO_TEST_FAILURE) MEMFAULT_PRINT_FAULTS (); #endif cairo_destroy (cr); UNWIND_SURFACE: cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); #if HAVE_MEMFAULT cairo_debug_reset_static_data (); #if HAVE_FCFINI FcFini (); #endif if (MEMFAULT_COUNT_LEAKS () > 0) { if (ret != CAIRO_TEST_FAILURE) MEMFAULT_PRINT_FAULTS (); MEMFAULT_PRINT_LEAKS (); } if (ret == CAIRO_TEST_SUCCESS && --malloc_failure_iterations > 0) goto REPEAT; #endif if (have_output) cairo_test_log (ctx, "OUTPUT: %s\n", out_png_path); if (have_result) { if (cmp_png_path == NULL) { /* XXX presume we matched the normal ref last time */ cmp_png_path = ref_png_path; } cairo_test_log (ctx, "REFERENCE: %s\nDIFFERENCE: %s\n", cmp_png_path, diff_png_path); } UNWIND_STRINGS: free (out_png_path); free (ref_png_path); free (base_ref_png_path); free (ref_path); free (new_png_path); free (base_new_png_path); free (new_path); free (xfail_png_path); free (base_xfail_png_path); free (xfail_path); free (diff_png_path); free (base_path); free (base_name); return ret; }
void lime_cairo_set_font_options (double handle, double options) { cairo_set_font_options ((cairo_t*)(intptr_t)handle, (cairo_font_options_t*)(intptr_t)options); }
void flush() { cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_A8, _totalWidth, _maxHeight); cairo_t *cr = cairo_create(surface); int pos = 0; cairo_set_source_rgba (cr, 0., 0., 0., 0); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_paint(cr); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_font_options_t *fontOptions = cairo_font_options_create(); cairo_get_font_options(cr, fontOptions); cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_FULL); cairo_font_options_set_antialias(fontOptions, CAIRO_ANTIALIAS_GRAY); cairo_set_font_options(cr, fontOptions); cairo_font_options_destroy(fontOptions); cairo_set_source_rgba(cr, 1, 1, 1, 1); for(std::vector<element>::iterator it = _elements.begin(); it != _elements.end(); ++it) { cairo_move_to(cr, pos - it->xBearing, -it->yBearing); cairo_set_font_size(cr, it->fontSize); cairo_set_font_face(cr, it->fontFace); cairo_show_text(cr, it->text.c_str()); cairo_font_face_destroy(it->fontFace); pos += it->width; } cairo_destroy(cr); //setup matrices GLint matrixMode; GLuint textureId; glGetIntegerv (GL_MATRIX_MODE, &matrixMode); glMatrixMode (GL_PROJECTION); glPushMatrix(); glLoadIdentity (); glMatrixMode (GL_MODELVIEW); glPushMatrix(); glLoadIdentity (); float winw = Fl_Window::current()->w(); float winh = Fl_Window::current()->h(); glScalef (2.0f / winw, 2.0f / winh, 1.0f); glTranslatef (-winw / 2.0f, -winh / 2.0f, 0.0f); //write the texture on screen glEnable(GL_TEXTURE_RECTANGLE_ARB); glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glGenTextures(1, &textureId); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, textureId); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_ALPHA, cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface), 0, GL_ALPHA, GL_UNSIGNED_BYTE, cairo_image_surface_get_data(surface)); //glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_SRC0_ALPHA); //printf("error %i %s\n", __LINE__, gluErrorString(glGetError())); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); pos = 0; for(std::vector<element>::iterator it = _elements.begin(); it != _elements.end(); ++it) { glTranslatef(it->x, it->y, it->z); glColor4f(it->r, it->g, it->b, it->alpha); int Lx = it->width; int Ly = it->height; glBegin (GL_QUADS); glTexCoord2f (pos, 0); glVertex2f (0.0f, Ly); glTexCoord2f (pos + Lx, 0); glVertex2f (Lx, Ly); glTexCoord2f (pos + Lx, Ly); glVertex2f (Lx, 0.0f); glTexCoord2f (pos, Ly); glVertex2f (0.0f, 0.0f); glEnd (); pos += Lx; glTranslatef(-it->x, -it->y, -it->z); } glDeleteTextures(1, &textureId); glPopAttrib(); // reset original matrices glPopMatrix(); // GL_MODELVIEW glMatrixMode (GL_PROJECTION); glPopMatrix(); glMatrixMode (matrixMode); _elements.clear(); _maxHeight = 0; _totalWidth = 0; cairo_surface_destroy(surface); }
TGUIFont *Alloc_GUIFont(const char *AFontName, float AHeight) { TGUIFont *BFont = (TGUIFont *)malloc(sizeof(TGUIFont)); BFont->FGridWidth = 0; BFont->FGridHeight = 0; BFont->FHeight = AHeight; BFont->FExtents = (TGUIFontExtent *)malloc(sizeof(TGUIFontExtent) * 256); TGUIFontExtent *BCharExtent = BFont->FExtents; cairo_text_extents_t *BExtents = (cairo_text_extents_t *)malloc(sizeof(cairo_text_extents_t)); int BRow = 0; int BColumn = 0; GUIFont_GetGreaterSize(AFontName, AHeight, &BFont->FGridWidth, &BFont->FGridHeight); printf("[MESSAGE] Font grid of size (%i, %i).\n", BFont->FGridWidth, BFont->FGridHeight); BFont->FTextureWidth = Get_NextP2(BFont->FGridWidth * 16); BFont->FTextureHeight = Get_NextP2(BFont->FGridHeight * 16); printf("[MESSAGE] Font texture of size (%i, %i).\n", BFont->FTextureWidth, BFont->FTextureHeight); unsigned char *BData = NULL; unsigned char *BText = (unsigned char *)malloc(sizeof(unsigned char) * 2); BText[0] = 0; BText[1] = '\0'; // Create texture data . cairo_surface_t *BSurface = cairo_image_surface_create(CAIRO_FORMAT_A8, BFont->FTextureWidth, BFont->FTextureHeight); cairo_t *BContext = cairo_create(BSurface); cairo_set_antialias(BContext, CAIRO_ANTIALIAS_NONE); cairo_set_operator(BContext, CAIRO_OPERATOR_OVER); cairo_set_source_rgba(BContext, 0.0, 0.0, 0.0, 0.0); cairo_font_options_t *cfo = cairo_font_options_create(); cairo_font_options_set_antialias(cfo, CAIRO_ANTIALIAS_SUBPIXEL); cairo_set_font_options(BContext, cfo); cairo_set_source_rgba(BContext, 0.0, 0.0, 0.0, 1.0); cairo_select_font_face(BContext, AFontName, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(BContext, AHeight); for (BText[0] = 0; BText[0] < 255; BText[0]++) { cairo_text_extents(BContext, BText, BExtents); if (BExtents) { BCharExtent->FAdvanceX = BExtents->x_advance; if (BText[0] == 32) { //BCharExtent->FAdvanceX = BFont->FGridWidth; }; BCharExtent->FAdvanceY = BExtents->y_advance; BCharExtent->FBearingX = BExtents->x_bearing; BCharExtent->FBearingY = BExtents->y_bearing; BCharExtent->FWidth = BExtents->width; BCharExtent->FHeight = BExtents->height; BRow = BText[0] / 16; BColumn = BText[0] % 16; cairo_move_to(BContext, -BExtents->x_bearing + (BColumn * BFont->FGridWidth), -BExtents->y_bearing + (BRow * BFont->FGridHeight)); cairo_show_text(BContext, BText); } else { printf("[MESSAGE] Fail to create font. Extents of char %i returned as null.\n", BText[0]); return NULL; }; BCharExtent++; }; cairo_surface_flush(BSurface); //cairo_surface_write_to_png(BSurface, "/home/felipefs/Desktop/texture.png"); BData = cairo_image_surface_get_data(BSurface); glGenTextures(1, &BFont->FTexture); glBindTexture(GL_TEXTURE_2D, BFont->FTexture); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, BFont->FTextureWidth, BFont->FTextureHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, BData); cairo_destroy(BContext); cairo_surface_destroy(BSurface); //free(BData); if (glIsTexture(BFont->FTexture) == GL_FALSE) { printf("[ERROR] Fail to create character texture of size %ix%i.\n", BFont->FTextureWidth, BFont->FTextureHeight); }; printf("[MESSAGE] Font created.\n"); return BFont; };
static cairo_time_t do_glyphs (double font_size, cairo_antialias_t antialias, cairo_t *cr, int width, int height, int loops) { const char text[] = "the jay, pig, fox, zebra and my wolves quack"; cairo_scaled_font_t *scaled_font; cairo_glyph_t *glyphs = NULL, *glyphs_copy; cairo_text_extents_t extents; cairo_font_options_t *options; cairo_status_t status; double x, y; int num_glyphs, n; options = cairo_font_options_create (); cairo_font_options_set_antialias (options, antialias); cairo_set_font_options (cr, options); cairo_font_options_destroy (options); cairo_select_font_face (cr, "@cairo:", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size (cr, font_size); scaled_font = cairo_get_scaled_font (cr); status = cairo_scaled_font_text_to_glyphs (scaled_font, 0., 0., text, -1, &glyphs, &num_glyphs, NULL, NULL, NULL); if (status) return 0; glyphs_copy = cairo_glyph_allocate (num_glyphs); if (glyphs_copy == NULL) { cairo_glyph_free (glyphs); return 0; } cairo_scaled_font_glyph_extents (scaled_font, glyphs, num_glyphs, &extents); cairo_perf_timer_start (); while (loops--) { y = 0; do { x = 0; do { for (n = 0; n < num_glyphs; n++) { glyphs_copy[n] = glyphs[n]; glyphs_copy[n].x += x; glyphs_copy[n].y += y; } cairo_show_glyphs (cr, glyphs_copy, num_glyphs); x += extents.width; } while (x < width); y += extents.height; } while (y < height); } cairo_perf_timer_stop (); cairo_glyph_free (glyphs); cairo_glyph_free (glyphs_copy); return cairo_perf_timer_elapsed (); }
void lime_cairo_set_font_options (value handle, value options) { cairo_set_font_options ((cairo_t*)val_data (handle), (cairo_font_options_t*)val_data (options)); }
int main(int argc, char** argv) { int c; float col_r, col_g, col_b = -1.0f; Options opt; while ((c = getopt(argc, argv, "a:x:y:f:s:t:n:w:r:g:b:c:h:i:j:o:v")) != -1) { switch(c) { /* verbose */ /* ------------------------------------------------------- */ case 'v': { opt.verbose = 0; break; } /* color */ /* ------------------------------------------------------- */ case 'r': { col_r = convert_type<float>(optarg); break; } case 'g': { col_g = convert_type<float>(optarg); break; } case 'b': { col_b = convert_type<float>(optarg); break; } /* ------------------------------------------------------- */ /* hashtag */ case 'h': { opt.hashtag = convert_type<std::string>(optarg); break; } case 'i': { opt.hashtag_x = convert_type<int>(optarg); break; } case 'j': { opt.hashtag_y = convert_type<int>(optarg); break; } /* ------------------------------------------------------- */ /* foreground */ case 'c': { opt.foreground_file = convert_type<std::string>(optarg); break; } /* ------------------------------------------------------- */ /* background */ case 'x': { opt.background_x = convert_type<int>(optarg); break; } case 'y': { opt.background_y = convert_type<int>(optarg); break; } case 'f': { opt.background_file = convert_type<std::string>(optarg); break; } /* ------------------------------------------------------- */ /* visible size */ case 'a': { opt.visible_size = convert_type<float>(optarg); break; } /* ------------------------------------------------------- */ /* output */ case 'o': { opt.output_file = convert_type<std::string>(optarg); break; } /* ------------------------------------------------------- */ /* name */ case 'n': { opt.name = convert_type<std::string>(optarg); /* we expect that r,g,b has been set */ if (0 > col_r) { printf("Error: you haven't set -r -g -b for the name.\n"); exit(EXIT_FAILURE); } opt.name_r = col_r; opt.name_g = col_g; opt.name_b = col_b; break; } /* name x position */ case 's': { opt.name_x = convert_type<int>(optarg); break; } /* name y position */ case 't': { opt.name_y = convert_type<int>(optarg); break; } /* name font size */ case 'w': { opt.name_font_size = convert_type<float>(optarg); break; } default: { printf("Unkown option\n"); break; } } } if (false == opt.validate()) { printf("+ error: cannot validate the given options.\n"); exit(EXIT_FAILURE); } opt.print(); /* ------------------------------------------------------------------------------------ */ Image img; std::string path; std::string ext; cairo_surface_t* surf_bg = NULL; cairo_format_t img_format = CAIRO_FORMAT_INVALID; path = opt.foreground_file; if (false == rx_file_exists(path)) { printf("+ error: cannot find the file: %s\n", path.c_str()); exit(EXIT_FAILURE); } cairo_surface_t* surf_overlay = cairo_image_surface_create_from_png(path.c_str()); if (NULL == surf_overlay) { printf("Error: cannot create s1\n"); exit(EXIT_FAILURE); } path = opt.background_file; if (false == rx_file_exists(path)) { printf("Error: file doesn't exist: %s\n", path.c_str()); exit(EXIT_FAILURE); } /* check what file type was given. */ ext = rx_get_file_ext(path); if (ext == "jpg") { printf("+ warning: jpg as input doesn't seem to work\n"); /* cairo doesn't have support for PNG? */ if (0 > rx_load_jpg(path, &img.pixels, img.width, img.height, img.channels)) { printf("Error: failed to load: %s\n", path.c_str()); exit(EXIT_FAILURE); } if (0 == img.width || 0 == img.height || 0 == img.channels) { printf("Error: image has invalid flags: %d x %d, channels: %d\n", img.width, img.height, img.channels); exit(EXIT_FAILURE); } if (3 == img.channels) { img_format = CAIRO_FORMAT_RGB24; printf("+ Using RGB24\n"); } else if(4 == img.channels) { img_format = CAIRO_FORMAT_ARGB32; printf("+ Using ARGB32\n"); } else { printf("Error: unsupported number of channels: %d.\n", img.channels); exit(EXIT_FAILURE); } if (NULL != img.pixels && NULL == surf_bg) { printf("Stride: %d\n", cairo_format_stride_for_width(img_format, img.width)); printf("Info: creating %d x %d, channels: %d\n", img.width, img.height, img.channels); surf_bg = cairo_image_surface_create_for_data(img.pixels, img_format, img.width, img.height, cairo_format_stride_for_width(img_format, img.width)); #if 0 /* TESTING */ cairo_t* cr = cairo_create(surf_bg); if (NULL == cr) { printf("Error: cannot create the cairo"); exit(EXIT_FAILURE); } path = rx_get_exe_path() +"/generated_polaroid.png"; cairo_surface_write_to_png(surf_bg, path.c_str()); printf("Created\n"); exit(0); /* END TESTING */ #endif } } else if (ext == "png") { /* use cairo png load feature. */ surf_bg = cairo_image_surface_create_from_png(path.c_str()); if (NULL == surf_bg) { printf("Error: cannot create s2\n"); exit(EXIT_FAILURE); } } else { printf("Error: unsupported file format: %s\n", ext.c_str()); exit(EXIT_FAILURE); } /* make sure the background is loaded correctly (aka the photo) */ if (NULL == surf_bg) { printf("Error: cannot create background surface.\n"); exit(EXIT_FAILURE); } if (CAIRO_STATUS_SUCCESS != cairo_surface_status(surf_bg)) { printf("Error: something went wrong: %d\n", cairo_surface_status(surf_bg)); exit(EXIT_FAILURE); } float source_width = cairo_image_surface_get_width(surf_bg); float source_height = cairo_image_surface_get_height(surf_bg); /* create output */ int dest_width = cairo_image_surface_get_width(surf_overlay); int dest_height = cairo_image_surface_get_height(surf_overlay); if (0 == opt.verbose) { printf("+ Output size: %d x %d\n", dest_width, dest_height); } cairo_surface_t* surf_out = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, dest_width, dest_height); if (NULL == surf_out) { printf("Error: cannot create cairo_surface_t\n"); exit(EXIT_FAILURE); } if (0 == opt.verbose) { printf("+ Info: creating output surface: %d x %d\n", dest_width, dest_height); } cairo_t* cr = cairo_create(surf_out); if (NULL == cr) { printf("Error: cannot create the cairo"); exit(EXIT_FAILURE); } float scale_factor = opt.visible_size / source_width; if (0 == opt.verbose) { printf("+ Scale factor: %f\n", scale_factor); } /* paint background */ cairo_save(cr); cairo_scale(cr, scale_factor, scale_factor); cairo_set_source_surface(cr, surf_bg, opt.background_x, opt.background_y); cairo_rectangle(cr, 0, 0, img.width, img.height); cairo_paint(cr); cairo_restore(cr); /* paint overlay */ cairo_set_source_surface(cr, surf_overlay, 0, 0); cairo_paint(cr); cairo_surface_flush(surf_out); /* font settings. */ cairo_font_options_t* font_options = cairo_font_options_create(); if (NULL == font_options) { printf("+ Error: cannot create font options. Cannot create polaroid.\n"); exit(EXIT_FAILURE); } cairo_font_options_set_antialias(font_options, CAIRO_ANTIALIAS_BEST); cairo_font_options_set_hint_metrics(font_options, CAIRO_HINT_METRICS_DEFAULT); cairo_set_font_options (cr, font_options); cairo_select_font_face(cr, "Platform", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_set_source_rgba(cr, opt.name_r, opt.name_g, opt.name_b, 1.0); /* name */ if (0 != opt.name.size()) { cairo_move_to(cr, opt.name_x, opt.name_y); cairo_set_font_size(cr, opt.name_font_size); cairo_show_text(cr, opt.name.c_str()); cairo_stroke(cr); cairo_fill(cr); } /* hashtag */ if (0 != opt.hashtag.size()) { cairo_select_font_face(cr, "Platform", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_move_to(cr, opt.hashtag_x, opt.hashtag_y); cairo_set_font_size(cr, opt.name_font_size); cairo_show_text(cr, opt.hashtag.c_str()); cairo_stroke(cr); cairo_fill(cr); } cairo_surface_flush(surf_out); /* write out */ path = opt.output_file; cairo_surface_write_to_png(surf_out, path.c_str()); /* cleanup */ cairo_surface_destroy(surf_out); cairo_surface_destroy(surf_bg); cairo_surface_destroy(surf_overlay); cairo_destroy(cr); if (0 == opt.verbose) { printf("\n"); } return 0; }
static cairo_test_status_t draw (cairo_t *cr, int width, int height) { const cairo_test_context_t *ctx = cairo_test_get_context (cr); glyph_array_t glyphs; cairo_font_options_t *font_options; cairo_status_t status; /* paint white so we don't need separate ref images for * RGB24 and ARGB32 */ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); cairo_paint (cr); cairo_select_font_face (cr, "Bitstream Vera Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size (cr, TEXT_SIZE); font_options = cairo_font_options_create (); cairo_get_font_options (cr, font_options); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF); cairo_set_font_options (cr, font_options); cairo_font_options_destroy (font_options); cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); glyph_array_init (&glyphs, 1, TEXT_SIZE); status = glyph_array_add_text(&glyphs, cr, "AWAY again", 0.0); if (status) return cairo_test_status_from_status (ctx, status); glyph_array_rel_move_to (&glyphs, TEXT_SIZE*1, 0.0); status = glyph_array_add_text(&glyphs, cr, "character space", TEXT_SIZE*0.3); if (status) return cairo_test_status_from_status (ctx, status); glyph_array_show (&glyphs, cr); glyph_array_init (&glyphs, 1, TEXT_SIZE*2 + 4); status = glyph_array_add_text(&glyphs, cr, "Increasing", 0.0); if (status) return cairo_test_status_from_status (ctx, status); glyph_array_rel_move_to (&glyphs, TEXT_SIZE*0.5, 0.0); status = glyph_array_add_text(&glyphs, cr, "space", 0.0); if (status) return cairo_test_status_from_status (ctx, status); glyph_array_rel_move_to (&glyphs, TEXT_SIZE*1.0, 0.0); status = glyph_array_add_text(&glyphs, cr, "between", 0.0); if (status) return cairo_test_status_from_status (ctx, status); glyph_array_rel_move_to (&glyphs, TEXT_SIZE*1.5, 0.0); status = glyph_array_add_text(&glyphs, cr, "words", 0.0); if (status) return cairo_test_status_from_status (ctx, status); glyph_array_show (&glyphs, cr); return CAIRO_TEST_SUCCESS; }
static void set_cf_antialias(cairo_t *cc) { cairo_font_options_t *fo = cairo_font_options_create(); cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_SUBPIXEL); cairo_set_font_options(cc, fo); cairo_font_options_destroy(fo); }