Back to index

lightning-sunbird  0.9+nobinonly
cairo-font-subset.c
Go to the documentation of this file.
00001 /* cairo - a vector graphics library with display and print output
00002  *
00003  * Copyright © 2004 Red Hat, Inc
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it either under the terms of the GNU Lesser General Public
00007  * License version 2.1 as published by the Free Software Foundation
00008  * (the "LGPL") or, at your option, under the terms of the Mozilla
00009  * Public License Version 1.1 (the "MPL"). If you do not alter this
00010  * notice, a recipient may use your version of this file under either
00011  * the MPL or the LGPL.
00012  *
00013  * You should have received a copy of the LGPL along with this library
00014  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
00015  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00016  * You should have received a copy of the MPL along with this library
00017  * in the file COPYING-MPL-1.1
00018  *
00019  * The contents of this file are subject to the Mozilla Public License
00020  * Version 1.1 (the "License"); you may not use this file except in
00021  * compliance with the License. You may obtain a copy of the License at
00022  * http://www.mozilla.org/MPL/
00023  *
00024  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
00025  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
00026  * the specific language governing rights and limitations.
00027  *
00028  * The Original Code is the cairo graphics library.
00029  *
00030  * The Initial Developer of the Original Code is Red Hat, Inc.
00031  *
00032  * Contributor(s):
00033  *     Kristian Høgsberg <krh@redhat.com>
00034  */
00035 
00036 #include "cairoint.h"
00037 #include "cairo-pdf.h"
00038 /* XXX: Eventually, we need to handle other font backends */
00039 #include "cairo-font-subset-private.h"
00040 #include "cairo-ft-private.h"
00041 
00042 #include <ft2build.h>
00043 #include FT_FREETYPE_H
00044 #include FT_OUTLINE_H
00045 #include FT_TRUETYPE_TAGS_H
00046 #include FT_TRUETYPE_TABLES_H
00047 
00048 typedef struct ft_subset_glyph ft_subset_glyph_t;
00049 struct ft_subset_glyph {
00050     int parent_index;
00051     unsigned long location;
00052 };
00053 
00054 struct cairo_font_subset_backend {
00055     int                     (*use_glyph)  (void *abstract_font,
00056                                     int glyph);
00057     cairo_status_t   (*generate)   (void *abstract_font,
00058                                     const char **data,
00059                                     unsigned long *length);
00060     void             (*destroy)    (void *abstract_font);
00061 };
00062 
00063 typedef struct cairo_pdf_ft_font cairo_pdf_ft_font_t;
00064 struct cairo_pdf_ft_font {
00065     cairo_font_subset_t base;
00066     ft_subset_glyph_t *glyphs;
00067     FT_Face face;
00068     int checksum_index;
00069     cairo_array_t output;
00070     int *parent_to_subset;
00071     cairo_status_t status;
00072 };
00073 
00074 static int
00075 cairo_pdf_ft_font_use_glyph (void *abstract_font, int glyph);
00076 
00077 
00078 #define ARRAY_LENGTH(a) ( (sizeof (a)) / (sizeof ((a)[0])) )
00079 
00080 #define SFNT_VERSION               0x00010000
00081 
00082 #ifdef WORDS_BIGENDIAN
00083 
00084 #define cpu_to_be16(v) (v)
00085 #define be16_to_cpu(v) (v)
00086 #define cpu_to_be32(v) (v)
00087 #define be32_to_cpu(v) (v)
00088 
00089 #else
00090 
00091 static inline unsigned short
00092 cpu_to_be16(unsigned short v)
00093 {
00094     return (v << 8) | (v >> 8);
00095 }
00096 
00097 static inline unsigned short
00098 be16_to_cpu(unsigned short v)
00099 {
00100     return cpu_to_be16 (v);
00101 }
00102 
00103 static inline unsigned long
00104 cpu_to_be32(unsigned long v)
00105 {
00106     return (cpu_to_be16 (v) << 16) | cpu_to_be16 (v >> 16);
00107 }
00108 
00109 static inline unsigned long
00110 be32_to_cpu(unsigned long v)
00111 {
00112     return cpu_to_be32 (v);
00113 }
00114 
00115 #endif
00116 
00117 static cairo_font_subset_backend_t cairo_pdf_ft_font_backend;
00118 
00119 int
00120 _cairo_font_subset_use_glyph (cairo_font_subset_t *font, int glyph)
00121 {
00122     return font->backend->use_glyph (font, glyph);
00123 }
00124 
00125 cairo_status_t
00126 _cairo_font_subset_generate (cairo_font_subset_t *font,
00127                       const char **data, unsigned long *length)
00128 {
00129     return font->backend->generate (font, data, length);
00130 }
00131 
00132 void
00133 _cairo_font_subset_destroy (cairo_font_subset_t *font)
00134 {
00135     font->backend->destroy (font);
00136 }
00137 
00138 cairo_font_subset_t *
00139 _cairo_font_subset_create (cairo_unscaled_font_t *unscaled_font)
00140 {
00141     cairo_ft_unscaled_font_t *ft_unscaled_font;
00142     FT_Face face;
00143     cairo_pdf_ft_font_t *font;
00144     unsigned long size;
00145     int i, j;
00146 
00147     /* XXX: Need to fix this to work with a general cairo_unscaled_font_t. */
00148     if (! _cairo_unscaled_font_is_ft (unscaled_font))
00149        return NULL;
00150 
00151     ft_unscaled_font = (cairo_ft_unscaled_font_t *) unscaled_font;
00152 
00153     face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font);
00154 
00155     /* We currently only support freetype truetype fonts. */
00156     size = 0;
00157     if (!FT_IS_SFNT (face) ||
00158        FT_Load_Sfnt_Table (face, TTAG_glyf, 0, NULL, &size) != 0)
00159        return NULL;
00160 
00161     font = malloc (sizeof (cairo_pdf_ft_font_t));
00162     if (font == NULL)
00163        return NULL;
00164 
00165     font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font);
00166     font->base.backend = &cairo_pdf_ft_font_backend;
00167 
00168     _cairo_array_init (&font->output, sizeof (char));
00169     if (_cairo_array_grow_by (&font->output, 4096) != CAIRO_STATUS_SUCCESS)
00170        goto fail1;
00171 
00172     font->glyphs = calloc (face->num_glyphs + 1, sizeof (ft_subset_glyph_t));
00173     if (font->glyphs == NULL)
00174        goto fail2;
00175 
00176     font->parent_to_subset = calloc (face->num_glyphs, sizeof (int));
00177     if (font->parent_to_subset == NULL)
00178        goto fail3;
00179 
00180     font->base.num_glyphs = 1;
00181     font->base.x_min = face->bbox.xMin;
00182     font->base.y_min = face->bbox.yMin;
00183     font->base.x_max = face->bbox.xMax;
00184     font->base.y_max = face->bbox.yMax;
00185     font->base.ascent = face->ascender;
00186     font->base.descent = face->descender;
00187     font->base.base_font = strdup (face->family_name);
00188     if (font->base.base_font == NULL)
00189        goto fail4;
00190 
00191     for (i = 0, j = 0; font->base.base_font[j]; j++) {
00192        if (font->base.base_font[j] == ' ')
00193            continue;
00194        font->base.base_font[i++] = font->base.base_font[j];
00195     }
00196     font->base.base_font[i] = '\0';
00197 
00198     font->base.widths = calloc (face->num_glyphs, sizeof (int));
00199     if (font->base.widths == NULL)
00200        goto fail5;
00201 
00202     _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
00203 
00204     font->status = CAIRO_STATUS_SUCCESS;
00205 
00206     return &font->base;
00207 
00208  fail5:
00209     free (font->base.base_font);
00210  fail4:
00211     free (font->parent_to_subset);
00212  fail3:
00213     free (font->glyphs);
00214  fail2:
00215     _cairo_array_fini (&font->output);
00216  fail1:
00217     free (font);
00218     return NULL;
00219 }
00220 
00221 static void
00222 cairo_pdf_ft_font_destroy (void *abstract_font)
00223 {
00224     cairo_pdf_ft_font_t *font = abstract_font;
00225 
00226     _cairo_unscaled_font_destroy (font->base.unscaled_font);
00227     free (font->base.base_font);
00228     free (font->parent_to_subset);
00229     free (font->glyphs);
00230     _cairo_array_fini (&font->output);
00231     free (font);
00232 }
00233 
00234 static void *
00235 cairo_pdf_ft_font_write (cairo_pdf_ft_font_t *font,
00236                       const void *data, size_t length)
00237 {
00238     void *p;
00239 
00240     p = _cairo_array_append (&font->output, data, length);
00241     if (p == NULL)
00242        font->status = CAIRO_STATUS_NO_MEMORY;
00243 
00244     return p;
00245 }
00246 
00247 static void
00248 cairo_pdf_ft_font_write_be16 (cairo_pdf_ft_font_t *font,
00249                            unsigned short value)
00250 {
00251     unsigned short be16_value;
00252 
00253     be16_value = cpu_to_be16 (value);
00254     cairo_pdf_ft_font_write (font, &be16_value, sizeof be16_value);
00255 }
00256 
00257 static void
00258 cairo_pdf_ft_font_write_be32 (cairo_pdf_ft_font_t *font, unsigned long value)
00259 {
00260     unsigned long be32_value;
00261 
00262     be32_value = cpu_to_be32 (value);
00263     cairo_pdf_ft_font_write (font, &be32_value, sizeof be32_value);
00264 }
00265 
00266 static unsigned long
00267 cairo_pdf_ft_font_align_output (cairo_pdf_ft_font_t *font)
00268 {
00269     int length, aligned;
00270     static const char pad[4];
00271 
00272     length = _cairo_array_num_elements (&font->output);
00273     aligned = (length + 3) & ~3;
00274     cairo_pdf_ft_font_write (font, pad, aligned - length);
00275 
00276     return aligned;
00277 }
00278 
00279 static int
00280 cairo_pdf_ft_font_write_cmap_table (cairo_pdf_ft_font_t *font, unsigned long tag)
00281 {
00282     int i;
00283 
00284     cairo_pdf_ft_font_write_be16 (font, 0);
00285     cairo_pdf_ft_font_write_be16 (font, 1);
00286 
00287     cairo_pdf_ft_font_write_be16 (font, 1);
00288     cairo_pdf_ft_font_write_be16 (font, 0);
00289     cairo_pdf_ft_font_write_be32 (font, 12);
00290 
00291     /* Output a format 6 encoding table. */
00292 
00293     cairo_pdf_ft_font_write_be16 (font, 6);
00294     cairo_pdf_ft_font_write_be16 (font, 10 + 2 * (font->base.num_glyphs - 1));
00295     cairo_pdf_ft_font_write_be16 (font, 0);
00296     cairo_pdf_ft_font_write_be16 (font, 1); /* First glyph */
00297     cairo_pdf_ft_font_write_be16 (font, font->base.num_glyphs - 1);
00298     for (i = 1; i < font->base.num_glyphs; i++)
00299        cairo_pdf_ft_font_write_be16 (font, i);
00300 
00301     return font->status;
00302 }
00303 
00304 static int
00305 cairo_pdf_ft_font_write_generic_table (cairo_pdf_ft_font_t *font,
00306                                    unsigned long tag)
00307 {
00308     unsigned char *buffer;
00309     unsigned long size;
00310 
00311     size = 0;
00312     FT_Load_Sfnt_Table (font->face, tag, 0, NULL, &size);
00313     buffer = cairo_pdf_ft_font_write (font, NULL, size);
00314     FT_Load_Sfnt_Table (font->face, tag, 0, buffer, &size);
00315     
00316     return 0;
00317 }
00318 
00319 
00320 typedef struct composite_glyph composite_glyph_t;
00321 struct composite_glyph {
00322     unsigned short flags;
00323     unsigned short index;
00324     unsigned short args[7]; /* 1 to 7 arguments depending on value of flags */
00325 };
00326 
00327 typedef struct glyph_data glyph_data_t;
00328 struct glyph_data {
00329     short             num_contours;
00330     char              data[8];
00331     composite_glyph_t glyph;
00332 };
00333 
00334 /* composite_glyph_t flags */
00335 #define ARG_1_AND_2_ARE_WORDS     0x0001
00336 #define WE_HAVE_A_SCALE           0x0008
00337 #define MORE_COMPONENTS           0x0020
00338 #define WE_HAVE_AN_X_AND_Y_SCALE  0x0040
00339 #define WE_HAVE_A_TWO_BY_TWO      0x0080
00340 
00341 static void
00342 cairo_pdf_ft_font_remap_composite_glyph (cairo_pdf_ft_font_t *font,
00343                                     unsigned char *buffer)
00344 {
00345     glyph_data_t *glyph_data;
00346     composite_glyph_t *composite_glyph;
00347     int num_args;
00348     int has_more_components;
00349     unsigned short flags;
00350     unsigned short index;
00351 
00352     glyph_data = (glyph_data_t *) buffer;
00353     if ((short)be16_to_cpu (glyph_data->num_contours) >= 0)
00354         return;
00355     
00356     composite_glyph = &glyph_data->glyph;
00357     do {
00358         flags = be16_to_cpu (composite_glyph->flags);
00359         has_more_components = flags & MORE_COMPONENTS;
00360         index = cairo_pdf_ft_font_use_glyph (font, be16_to_cpu (composite_glyph->index));
00361         composite_glyph->index = cpu_to_be16 (index);
00362         num_args = 1;
00363         if (flags & ARG_1_AND_2_ARE_WORDS)
00364             num_args += 1;
00365         if (flags & WE_HAVE_A_SCALE)
00366             num_args += 1;
00367         else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
00368             num_args += 2;
00369         else if (flags & WE_HAVE_A_TWO_BY_TWO)
00370             num_args += 3;
00371         composite_glyph = (composite_glyph_t *) &(composite_glyph->args[num_args]);
00372     } while (has_more_components);
00373 }
00374 
00375 static int
00376 cairo_pdf_ft_font_write_glyf_table (cairo_pdf_ft_font_t *font,
00377                                 unsigned long tag)
00378 {
00379     unsigned long start_offset, index, size;
00380     TT_Header *header;
00381     unsigned long begin, end;
00382     unsigned char *buffer;
00383     int i;
00384     union {
00385        unsigned char *bytes;
00386        unsigned short *short_offsets;
00387        unsigned long *long_offsets;
00388     } u;
00389 
00390     header = FT_Get_Sfnt_Table (font->face, ft_sfnt_head);
00391     if (header->Index_To_Loc_Format == 0)
00392        size = sizeof (short) * (font->face->num_glyphs + 1);
00393     else
00394        size = sizeof (long) * (font->face->num_glyphs + 1);
00395 
00396     u.bytes = malloc (size);
00397     if (u.bytes == NULL) {
00398        font->status = CAIRO_STATUS_NO_MEMORY;
00399        return font->status;
00400     }
00401     FT_Load_Sfnt_Table (font->face, TTAG_loca, 0, u.bytes, &size);
00402 
00403     start_offset = _cairo_array_num_elements (&font->output);
00404     for (i = 0; i < font->base.num_glyphs; i++) {
00405        index = font->glyphs[i].parent_index;
00406        if (header->Index_To_Loc_Format == 0) {
00407            begin = be16_to_cpu (u.short_offsets[index]) * 2;
00408            end = be16_to_cpu (u.short_offsets[index + 1]) * 2;
00409        }
00410        else {
00411            begin = be32_to_cpu (u.long_offsets[index]);
00412            end = be32_to_cpu (u.long_offsets[index + 1]);
00413        }
00414 
00415        size = end - begin;
00416 
00417        font->glyphs[i].location =
00418            cairo_pdf_ft_font_align_output (font) - start_offset;
00419        buffer = cairo_pdf_ft_font_write (font, NULL, size);
00420        if (buffer == NULL)
00421            break;
00422         if (size != 0) {
00423             FT_Load_Sfnt_Table (font->face, TTAG_glyf, begin, buffer, &size);
00424             cairo_pdf_ft_font_remap_composite_glyph (font, buffer);
00425         }
00426     }
00427 
00428     font->glyphs[i].location =
00429        cairo_pdf_ft_font_align_output (font) - start_offset;
00430 
00431     free (u.bytes);
00432 
00433     return font->status;
00434 }
00435 
00436 static int
00437 cairo_pdf_ft_font_write_head_table (cairo_pdf_ft_font_t *font,
00438                                 unsigned long tag)
00439 {
00440     TT_Header *head;
00441 
00442     head = FT_Get_Sfnt_Table (font->face, ft_sfnt_head);
00443 
00444     cairo_pdf_ft_font_write_be32 (font, head->Table_Version);
00445     cairo_pdf_ft_font_write_be32 (font, head->Font_Revision);
00446 
00447     font->checksum_index = _cairo_array_num_elements (&font->output);
00448     cairo_pdf_ft_font_write_be32 (font, 0);
00449     cairo_pdf_ft_font_write_be32 (font, head->Magic_Number);
00450 
00451     cairo_pdf_ft_font_write_be16 (font, head->Flags);
00452     cairo_pdf_ft_font_write_be16 (font, head->Units_Per_EM);
00453 
00454     cairo_pdf_ft_font_write_be32 (font, head->Created[0]);
00455     cairo_pdf_ft_font_write_be32 (font, head->Created[1]);
00456     cairo_pdf_ft_font_write_be32 (font, head->Modified[0]);
00457     cairo_pdf_ft_font_write_be32 (font, head->Modified[1]);
00458 
00459     cairo_pdf_ft_font_write_be16 (font, head->xMin);
00460     cairo_pdf_ft_font_write_be16 (font, head->yMin);
00461     cairo_pdf_ft_font_write_be16 (font, head->xMax);
00462     cairo_pdf_ft_font_write_be16 (font, head->yMax);
00463 
00464     cairo_pdf_ft_font_write_be16 (font, head->Mac_Style);
00465     cairo_pdf_ft_font_write_be16 (font, head->Lowest_Rec_PPEM);
00466 
00467     cairo_pdf_ft_font_write_be16 (font, head->Font_Direction);
00468     cairo_pdf_ft_font_write_be16 (font, head->Index_To_Loc_Format);
00469     cairo_pdf_ft_font_write_be16 (font, head->Glyph_Data_Format);
00470 
00471     return font->status;
00472 }
00473 
00474 static int cairo_pdf_ft_font_write_hhea_table (cairo_pdf_ft_font_t *font, unsigned long tag)
00475 {
00476     TT_HoriHeader *hhea;
00477 
00478     hhea = FT_Get_Sfnt_Table (font->face, ft_sfnt_hhea);
00479 
00480     cairo_pdf_ft_font_write_be32 (font, hhea->Version);
00481     cairo_pdf_ft_font_write_be16 (font, hhea->Ascender);
00482     cairo_pdf_ft_font_write_be16 (font, hhea->Descender);
00483     cairo_pdf_ft_font_write_be16 (font, hhea->Line_Gap);
00484 
00485     cairo_pdf_ft_font_write_be16 (font, hhea->advance_Width_Max);
00486 
00487     cairo_pdf_ft_font_write_be16 (font, hhea->min_Left_Side_Bearing);
00488     cairo_pdf_ft_font_write_be16 (font, hhea->min_Right_Side_Bearing);
00489     cairo_pdf_ft_font_write_be16 (font, hhea->xMax_Extent);
00490     cairo_pdf_ft_font_write_be16 (font, hhea->caret_Slope_Rise);
00491     cairo_pdf_ft_font_write_be16 (font, hhea->caret_Slope_Run);
00492     cairo_pdf_ft_font_write_be16 (font, hhea->caret_Offset);
00493 
00494     cairo_pdf_ft_font_write_be16 (font, 0);
00495     cairo_pdf_ft_font_write_be16 (font, 0);
00496     cairo_pdf_ft_font_write_be16 (font, 0);
00497     cairo_pdf_ft_font_write_be16 (font, 0);
00498 
00499     cairo_pdf_ft_font_write_be16 (font, hhea->metric_Data_Format);
00500     cairo_pdf_ft_font_write_be16 (font, font->base.num_glyphs);
00501 
00502     return font->status;
00503 }
00504 
00505 static int
00506 cairo_pdf_ft_font_write_hmtx_table (cairo_pdf_ft_font_t *font,
00507                                 unsigned long tag)
00508 {
00509     unsigned long entry_size;
00510     short *p;
00511     int i;
00512 
00513     for (i = 0; i < font->base.num_glyphs; i++) {
00514        entry_size = 2 * sizeof (short);
00515        p = cairo_pdf_ft_font_write (font, NULL, entry_size);
00516        FT_Load_Sfnt_Table (font->face, TTAG_hmtx, 
00517                          font->glyphs[i].parent_index * entry_size,
00518                          (FT_Byte *) p, &entry_size);
00519        font->base.widths[i] = be16_to_cpu (p[0]);
00520     }
00521 
00522     return font->status;
00523 }
00524 
00525 static int
00526 cairo_pdf_ft_font_write_loca_table (cairo_pdf_ft_font_t *font,
00527                                 unsigned long tag)
00528 {
00529     int i;
00530     TT_Header *header;
00531 
00532     header = FT_Get_Sfnt_Table (font->face, ft_sfnt_head);
00533 
00534     if (header->Index_To_Loc_Format == 0) {
00535        for (i = 0; i < font->base.num_glyphs + 1; i++)
00536            cairo_pdf_ft_font_write_be16 (font, font->glyphs[i].location / 2);
00537     }
00538     else {
00539        for (i = 0; i < font->base.num_glyphs + 1; i++)
00540            cairo_pdf_ft_font_write_be32 (font, font->glyphs[i].location);
00541     }
00542 
00543     return font->status;
00544 }
00545 
00546 static int
00547 cairo_pdf_ft_font_write_maxp_table (cairo_pdf_ft_font_t *font,
00548                                 unsigned long tag)
00549 {
00550     TT_MaxProfile *maxp;
00551 
00552     maxp = FT_Get_Sfnt_Table (font->face, ft_sfnt_maxp);
00553     
00554     cairo_pdf_ft_font_write_be32 (font, maxp->version);
00555     cairo_pdf_ft_font_write_be16 (font, font->base.num_glyphs);
00556     cairo_pdf_ft_font_write_be16 (font, maxp->maxPoints);
00557     cairo_pdf_ft_font_write_be16 (font, maxp->maxContours);
00558     cairo_pdf_ft_font_write_be16 (font, maxp->maxCompositePoints);
00559     cairo_pdf_ft_font_write_be16 (font, maxp->maxCompositeContours);
00560     cairo_pdf_ft_font_write_be16 (font, maxp->maxZones);
00561     cairo_pdf_ft_font_write_be16 (font, maxp->maxTwilightPoints);
00562     cairo_pdf_ft_font_write_be16 (font, maxp->maxStorage);
00563     cairo_pdf_ft_font_write_be16 (font, maxp->maxFunctionDefs);
00564     cairo_pdf_ft_font_write_be16 (font, maxp->maxInstructionDefs);
00565     cairo_pdf_ft_font_write_be16 (font, maxp->maxStackElements);
00566     cairo_pdf_ft_font_write_be16 (font, maxp->maxSizeOfInstructions);
00567     cairo_pdf_ft_font_write_be16 (font, maxp->maxComponentElements);
00568     cairo_pdf_ft_font_write_be16 (font, maxp->maxComponentDepth);
00569 
00570     return font->status;
00571 }
00572 
00573 typedef struct table table_t;
00574 struct table {
00575     unsigned long tag;
00576     int (*write) (cairo_pdf_ft_font_t *font, unsigned long tag);
00577 };
00578 
00579 static const table_t truetype_tables[] = {
00580     /* As we write out the glyf table we remap composite glyphs.
00581      * Remapping composite glyphs will reference the sub glyphs the
00582      * composite glyph is made up of.  That needs to be done first so
00583      * we have all the glyphs in the subset before going further. */
00584     { TTAG_glyf, cairo_pdf_ft_font_write_glyf_table },
00585     { TTAG_cmap, cairo_pdf_ft_font_write_cmap_table },
00586     { TTAG_cvt,  cairo_pdf_ft_font_write_generic_table },
00587     { TTAG_fpgm, cairo_pdf_ft_font_write_generic_table },
00588     { TTAG_head, cairo_pdf_ft_font_write_head_table },
00589     { TTAG_hhea, cairo_pdf_ft_font_write_hhea_table },
00590     { TTAG_hmtx, cairo_pdf_ft_font_write_hmtx_table },
00591     { TTAG_loca, cairo_pdf_ft_font_write_loca_table },
00592     { TTAG_maxp, cairo_pdf_ft_font_write_maxp_table },
00593     { TTAG_name, cairo_pdf_ft_font_write_generic_table },
00594     { TTAG_prep, cairo_pdf_ft_font_write_generic_table },
00595 };
00596 
00597 static cairo_status_t
00598 cairo_pdf_ft_font_write_offset_table (cairo_pdf_ft_font_t *font)
00599 {
00600     unsigned short search_range, entry_selector, range_shift;
00601     int num_tables;
00602 
00603     num_tables = ARRAY_LENGTH (truetype_tables);
00604     search_range = 1;
00605     entry_selector = 0;
00606     while (search_range * 2 <= num_tables) {
00607        search_range *= 2;
00608        entry_selector++;
00609     }
00610     search_range *= 16;
00611     range_shift = num_tables * 16 - search_range;
00612 
00613     cairo_pdf_ft_font_write_be32 (font, SFNT_VERSION);
00614     cairo_pdf_ft_font_write_be16 (font, num_tables);
00615     cairo_pdf_ft_font_write_be16 (font, search_range);
00616     cairo_pdf_ft_font_write_be16 (font, entry_selector);
00617     cairo_pdf_ft_font_write_be16 (font, range_shift);
00618 
00619     cairo_pdf_ft_font_write (font, NULL, ARRAY_LENGTH (truetype_tables) * 16);
00620 
00621     return font->status;
00622 }    
00623 
00624 static unsigned long
00625 cairo_pdf_ft_font_calculate_checksum (cairo_pdf_ft_font_t *font,
00626                         unsigned long start, unsigned long end)
00627 {
00628     unsigned long *padded_end;
00629     unsigned long *p;
00630     unsigned long checksum;
00631     char *data;
00632 
00633     checksum = 0; 
00634     data = _cairo_array_index (&font->output, 0);
00635     p = (unsigned long *) (data + start);
00636     padded_end = (unsigned long *) (data + ((end + 3) & ~3));
00637     while (p < padded_end)
00638        checksum += *p++;
00639 
00640     return checksum;
00641 }
00642 
00643 static void
00644 cairo_pdf_ft_font_update_entry (cairo_pdf_ft_font_t *font, int index, unsigned long tag,
00645                      unsigned long start, unsigned long end)
00646 {
00647     unsigned long *entry;
00648 
00649     entry = _cairo_array_index (&font->output, 12 + 16 * index);
00650     entry[0] = cpu_to_be32 (tag);
00651     entry[1] = cpu_to_be32 (cairo_pdf_ft_font_calculate_checksum (font, start, end));
00652     entry[2] = cpu_to_be32 (start);
00653     entry[3] = cpu_to_be32 (end - start);
00654 }
00655 
00656 static cairo_status_t
00657 cairo_pdf_ft_font_generate (void *abstract_font,
00658                          const char **data, unsigned long *length)
00659 {
00660     cairo_ft_unscaled_font_t *ft_unscaled_font;
00661     cairo_pdf_ft_font_t *font = abstract_font;
00662     unsigned long start, end, next, checksum, *checksum_location;
00663     int i;
00664 
00665     /* XXX: It would be cleaner to do something besides this cast
00666      * here. Perhaps cairo_pdf_ft_font_t should just have the
00667      * cairo_ft_unscaled_font_t rather than having the generic
00668      * cairo_unscaled_font_t in the base class? */
00669     ft_unscaled_font = (cairo_ft_unscaled_font_t *) font->base.unscaled_font;
00670 
00671     font->face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font);
00672 
00673     if (cairo_pdf_ft_font_write_offset_table (font))
00674        goto fail;
00675 
00676     start = cairo_pdf_ft_font_align_output (font);
00677     end = start;
00678 
00679     end = 0;
00680     for (i = 0; i < ARRAY_LENGTH (truetype_tables); i++) {
00681        if (truetype_tables[i].write (font, truetype_tables[i].tag))
00682            goto fail;
00683 
00684        end = _cairo_array_num_elements (&font->output);
00685        next = cairo_pdf_ft_font_align_output (font);
00686        cairo_pdf_ft_font_update_entry (font, i, truetype_tables[i].tag,
00687                                    start, end);
00688        start = next;
00689     }
00690 
00691     checksum =
00692        0xb1b0afba - cairo_pdf_ft_font_calculate_checksum (font, 0, end);
00693     checksum_location = _cairo_array_index (&font->output, font->checksum_index);
00694     *checksum_location = cpu_to_be32 (checksum);
00695 
00696     *data = _cairo_array_index (&font->output, 0);
00697     *length = _cairo_array_num_elements (&font->output);
00698 
00699  fail:
00700     _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
00701     font->face = NULL;
00702 
00703     return font->status;
00704 }
00705 
00706 static int
00707 cairo_pdf_ft_font_use_glyph (void *abstract_font, int glyph)
00708 {
00709     cairo_pdf_ft_font_t *font = abstract_font;
00710 
00711     if (font->parent_to_subset[glyph] == 0) {
00712        font->parent_to_subset[glyph] = font->base.num_glyphs;
00713        font->glyphs[font->base.num_glyphs].parent_index = glyph;
00714        font->base.num_glyphs++;
00715     }
00716 
00717     return font->parent_to_subset[glyph];
00718 }
00719 
00720 static cairo_font_subset_backend_t cairo_pdf_ft_font_backend = {
00721     cairo_pdf_ft_font_use_glyph,
00722     cairo_pdf_ft_font_generate,
00723     cairo_pdf_ft_font_destroy
00724 };