[cairo-commit] cairo/src cairo-win32-font.c,1.23,1.24

Tim Rowley commit at pdx.freedesktop.org
Tue Jun 28 15:03:55 PDT 2005


Committed by: tor

Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv3998/src

Modified Files:
	cairo-win32-font.c 
Log Message:
	reviewed by: otaylor
	
	* src/cairo-win32-font.c (_cairo_win32_scaled_font_glyph_path):
	Implement.


Index: cairo-win32-font.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-win32-font.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- cairo-win32-font.c	15 Jun 2005 23:04:19 -0000	1.23
+++ cairo-win32-font.c	28 Jun 2005 22:03:53 -0000	1.24
@@ -1101,13 +1101,136 @@
     }
 }
 
+static cairo_fixed_t
+_cairo_fixed_from_FIXED (FIXED f)
+{
+    return *((cairo_fixed_t *)&f);
+}
+
 static cairo_status_t 
-_cairo_win32_scaled_font_glyph_path (void		*abstract_font,
-				     cairo_glyph_t	*glyphs, 
-				     int		 num_glyphs,
-				     cairo_path_fixed_t	*path)
+_cairo_win32_scaled_font_glyph_path (void               *abstract_font,
+                                     cairo_glyph_t      *glyphs, 
+                                     int                 num_glyphs,
+                                     cairo_path_fixed_t *path)
 {
-    return CAIRO_STATUS_SUCCESS;
+    static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, -1 } };
+    cairo_win32_scaled_font_t *scaled_font = abstract_font;
+    cairo_status_t status;
+    GLYPHMETRICS metrics;
+    HDC hdc;
+    int i;
+
+    hdc = _get_global_font_dc ();
+    if (!hdc)
+        return CAIRO_STATUS_NO_MEMORY;
+
+    status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
+    if (status)
+        return status;
+
+    for (i = 0; i < num_glyphs; i++)
+    {
+        DWORD bytesGlyph;
+        unsigned char *buffer, *ptr;
+
+        cairo_fixed_t x = _cairo_fixed_from_double (glyphs[i].x);
+        cairo_fixed_t y = _cairo_fixed_from_double (glyphs[i].y);
+
+        bytesGlyph = GetGlyphOutlineW (hdc, glyphs[i].index,
+                                       GGO_NATIVE | GGO_GLYPH_INDEX,
+                                       &metrics, 0, NULL, &matrix);
+
+        if (bytesGlyph == GDI_ERROR) {
+            status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path");
+            goto FAIL;
+        }
+
+        ptr = buffer = malloc (bytesGlyph);
+
+        if (!buffer) {
+            status = CAIRO_STATUS_NO_MEMORY;
+            goto FAIL;
+        }
+
+        if (GetGlyphOutlineW (hdc, glyphs[i].index,
+                              GGO_NATIVE | GGO_GLYPH_INDEX,
+                              &metrics, bytesGlyph, buffer, &matrix) == GDI_ERROR) {
+            status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path");
+            free (buffer);
+            goto FAIL;
+        }
+        
+        while (ptr < buffer + bytesGlyph) {
+            TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)ptr;
+            unsigned char *endPoly = ptr + header->cb;
+
+            ptr += sizeof (TTPOLYGONHEADER);
+
+            _cairo_path_fixed_move_to (path,
+                                       _cairo_fixed_from_FIXED (header->pfxStart.x) + x,
+                                       _cairo_fixed_from_FIXED (header->pfxStart.y) + y);
+
+            while (ptr < endPoly) {
+                TTPOLYCURVE *curve = (TTPOLYCURVE *)ptr;
+                POINTFX *points = curve->apfx;
+                int i;
+                switch (curve->wType) {
+                case TT_PRIM_LINE:
+                    for (i = 0; i < curve->cpfx; i++) {
+                        _cairo_path_fixed_line_to (path,
+                                                   _cairo_fixed_from_FIXED (points[i].x) + x,
+                                                   _cairo_fixed_from_FIXED (points[i].y) + y);
+                    }
+                    break;
+                case TT_PRIM_QSPLINE:
+                    for (i = 0; i < curve->cpfx - 1; i++) {
+                        cairo_fixed_t p1x, p1y, p2x, p2y, cx, cy, c1x, c1y, c2x, c2y;
+                        _cairo_path_fixed_get_current_point (path, &p1x, &p1y);
+                        cx = _cairo_fixed_from_FIXED (points[i].x) + x;
+                        cy = _cairo_fixed_from_FIXED (points[i].y) + y;
+
+                        if (i + 1 == curve->cpfx - 1) {
+                            p2x = _cairo_fixed_from_FIXED (points[i + 1].x) + x;
+                            p2y = _cairo_fixed_from_FIXED (points[i + 1].y) + y;
+                        } else {
+                            /* records with more than one curve use interpolation for
+                               control points, per http://support.microsoft.com/kb/q87115/ */
+                            p2x = (cx + _cairo_fixed_from_FIXED (points[i + 1].x) + x) / 2;
+                            p2y = (cy + _cairo_fixed_from_FIXED (points[i + 1].y) + y) / 2;
+                        }
+
+                        c1x = 2 * cx / 3 + p1x / 3;
+                        c1y = 2 * cy / 3 + p1y / 3;
+                        c2x = 2 * cx / 3 + p2x / 3;
+                        c2y = 2 * cy / 3 + p2y / 3;
+
+                        _cairo_path_fixed_curve_to (path, c1x, c1y, c2x, c2y, p2x, p2y);
+                    }
+                    break;
+                case TT_PRIM_CSPLINE:
+                    for (i = 0; i < curve->cpfx - 2; i += 2) {
+                        _cairo_path_fixed_curve_to (path,
+                                                    _cairo_fixed_from_FIXED (points[i].x) + x,
+                                                    _cairo_fixed_from_FIXED (points[i].y) + y,
+                                                    _cairo_fixed_from_FIXED (points[i + 1].x) + x,
+                                                    _cairo_fixed_from_FIXED (points[i + 1].y) + y,
+                                                    _cairo_fixed_from_FIXED (points[i + 2].x) + x,
+                                                    _cairo_fixed_from_FIXED (points[i + 2].y) + y);
+                    }
+                    break;
+                }
+                ptr += sizeof(TTPOLYCURVE) + sizeof (POINTFX) * (curve->cpfx - 1);
+            }
+            _cairo_path_fixed_close_path (path);
+        }
+        free(buffer);
+    }
+
+FAIL:
+
+    cairo_win32_scaled_font_done_font (&scaled_font->base);
+
+    return status;
 }
 
 const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend = {




More information about the cairo-commit mailing list