Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /* cairo - a vector graphics library with display and print output
  2.  *
  3.  * Copyright © 2004 Red Hat, Inc
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it either under the terms of the GNU Lesser General Public
  7.  * License version 2.1 as published by the Free Software Foundation
  8.  * (the "LGPL") or, at your option, under the terms of the Mozilla
  9.  * Public License Version 1.1 (the "MPL"). If you do not alter this
  10.  * notice, a recipient may use your version of this file under either
  11.  * the MPL or the LGPL.
  12.  *
  13.  * You should have received a copy of the LGPL along with this library
  14.  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  15.  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  16.  * You should have received a copy of the MPL along with this library
  17.  * in the file COPYING-MPL-1.1
  18.  *
  19.  * The contents of this file are subject to the Mozilla Public License
  20.  * Version 1.1 (the "License"); you may not use this file except in
  21.  * compliance with the License. You may obtain a copy of the License at
  22.  * http://www.mozilla.org/MPL/
  23.  *
  24.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  25.  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  26.  * the specific language governing rights and limitations.
  27.  *
  28.  * The Original Code is the cairo graphics library.
  29.  *
  30.  * The Initial Developer of the Original Code is Red Hat, Inc.
  31.  *
  32.  * Contributor(s):
  33.  *      Kristian Høgsberg <krh@redhat.com>
  34.  *      Adrian Johnson <ajohnson@redneon.com>
  35.  */
  36.  
  37. /*
  38.  * Useful links:
  39.  * http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6.html
  40.  * http://www.microsoft.com/typography/specs/default.htm
  41.  */
  42.  
  43. #define _BSD_SOURCE /* for snprintf(), strdup() */
  44. #include "cairoint.h"
  45. #include "cairo-error-private.h"
  46.  
  47. #if CAIRO_HAS_FONT_SUBSET
  48.  
  49. #include "cairo-scaled-font-subsets-private.h"
  50. #include "cairo-truetype-subset-private.h"
  51.  
  52.  
  53. typedef struct subset_glyph subset_glyph_t;
  54. struct subset_glyph {
  55.     int parent_index;
  56.     unsigned long location;
  57. };
  58.  
  59. typedef struct _cairo_truetype_font cairo_truetype_font_t;
  60.  
  61. typedef struct table table_t;
  62. struct table {
  63.     unsigned long tag;
  64.     cairo_status_t (*write) (cairo_truetype_font_t *font, unsigned long tag);
  65.     int pos; /* position in the font directory */
  66. };
  67.  
  68. struct _cairo_truetype_font {
  69.  
  70.     cairo_scaled_font_subset_t *scaled_font_subset;
  71.  
  72.     table_t truetype_tables[10];
  73.     int num_tables;
  74.  
  75.     struct {
  76.         char *font_name;
  77.         char *ps_name;
  78.         unsigned int num_glyphs;
  79.         int *widths;
  80.         long x_min, y_min, x_max, y_max;
  81.         long ascent, descent;
  82.         int  units_per_em;
  83.     } base;
  84.  
  85.     subset_glyph_t *glyphs;
  86.     const cairo_scaled_font_backend_t *backend;
  87.     int num_glyphs_in_face;
  88.     int checksum_index;
  89.     cairo_array_t output;
  90.     cairo_array_t string_offsets;
  91.     unsigned long last_offset;
  92.     unsigned long last_boundary;
  93.     int *parent_to_subset;
  94.     cairo_status_t status;
  95.  
  96. };
  97.  
  98. /*
  99.  * Test that the structs we define for TrueType tables have the
  100.  * correct size, ie. they are not padded.
  101.  */
  102. #define check(T, S) COMPILE_TIME_ASSERT (sizeof (T) == (S))
  103. check (tt_head_t,       54);
  104. check (tt_hhea_t,       36);
  105. check (tt_maxp_t,       32);
  106. check (tt_name_record_t, 12);
  107. check (tt_name_t,       18);
  108. check (tt_name_t,       18);
  109. check (tt_composite_glyph_t, 16);
  110. check (tt_glyph_data_t, 26);
  111. #undef check
  112.  
  113. static cairo_status_t
  114. cairo_truetype_font_use_glyph (cairo_truetype_font_t        *font,
  115.                                unsigned short                glyph,
  116.                                unsigned short               *out);
  117.  
  118. #define SFNT_VERSION                    0x00010000
  119. #define SFNT_STRING_MAX_LENGTH  65535
  120.  
  121. static cairo_status_t
  122. _cairo_truetype_font_set_error (cairo_truetype_font_t *font,
  123.                                 cairo_status_t status)
  124. {
  125.     if (status == CAIRO_STATUS_SUCCESS || status == CAIRO_INT_STATUS_UNSUPPORTED)
  126.         return status;
  127.  
  128.     _cairo_status_set_error (&font->status, status);
  129.  
  130.     return _cairo_error (status);
  131. }
  132.  
  133. static cairo_status_t
  134. _cairo_truetype_font_create (cairo_scaled_font_subset_t  *scaled_font_subset,
  135.                              cairo_truetype_font_t      **font_return)
  136. {
  137.     cairo_status_t status;
  138.     cairo_truetype_font_t *font;
  139.     const cairo_scaled_font_backend_t *backend;
  140.     tt_head_t head;
  141.     tt_hhea_t hhea;
  142.     tt_maxp_t maxp;
  143.     unsigned long size;
  144.  
  145.     backend = scaled_font_subset->scaled_font->backend;
  146.     if (!backend->load_truetype_table)
  147.         return CAIRO_INT_STATUS_UNSUPPORTED;
  148.  
  149.     /* FIXME: We should either support subsetting vertical fonts, or fail on
  150.      * vertical.  Currently font_options_t doesn't have vertical flag, but
  151.      * it should be added in the future.  For now, the freetype backend
  152.      * returns UNSUPPORTED in load_truetype_table if the font is vertical.
  153.      *
  154.      *  if (cairo_font_options_get_vertical_layout (scaled_font_subset->scaled_font))
  155.      *   return CAIRO_INT_STATUS_UNSUPPORTED;
  156.      */
  157.  
  158.     size = sizeof (tt_head_t);
  159.     status = backend->load_truetype_table (scaled_font_subset->scaled_font,
  160.                                           TT_TAG_head, 0,
  161.                                           (unsigned char *) &head,
  162.                                           &size);
  163.     if (unlikely (status))
  164.         return status;
  165.  
  166.     size = sizeof (tt_maxp_t);
  167.     status = backend->load_truetype_table (scaled_font_subset->scaled_font,
  168.                                            TT_TAG_maxp, 0,
  169.                                            (unsigned char *) &maxp,
  170.                                            &size);
  171.     if (unlikely (status))
  172.         return status;
  173.  
  174.     size = sizeof (tt_hhea_t);
  175.     status = backend->load_truetype_table (scaled_font_subset->scaled_font,
  176.                                            TT_TAG_hhea, 0,
  177.                                            (unsigned char *) &hhea,
  178.                                            &size);
  179.     if (unlikely (status))
  180.         return status;
  181.  
  182.     font = malloc (sizeof (cairo_truetype_font_t));
  183.     if (unlikely (font == NULL))
  184.         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  185.  
  186.     font->backend = backend;
  187.     font->num_glyphs_in_face = be16_to_cpu (maxp.num_glyphs);
  188.     font->scaled_font_subset = scaled_font_subset;
  189.  
  190.     font->last_offset = 0;
  191.     font->last_boundary = 0;
  192.     _cairo_array_init (&font->output, sizeof (char));
  193.     status = _cairo_array_grow_by (&font->output, 4096);
  194.     if (unlikely (status))
  195.         goto fail1;
  196.  
  197.     font->glyphs = calloc (font->num_glyphs_in_face + 1, sizeof (subset_glyph_t));
  198.     if (unlikely (font->glyphs == NULL)) {
  199.         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  200.         goto fail1;
  201.     }
  202.  
  203.     font->parent_to_subset = calloc (font->num_glyphs_in_face, sizeof (int));
  204.     if (unlikely (font->parent_to_subset == NULL)) {
  205.         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  206.         goto fail2;
  207.     }
  208.  
  209.     font->base.num_glyphs = 0;
  210.     font->base.x_min = (int16_t) be16_to_cpu (head.x_min);
  211.     font->base.y_min = (int16_t) be16_to_cpu (head.y_min);
  212.     font->base.x_max = (int16_t) be16_to_cpu (head.x_max);
  213.     font->base.y_max = (int16_t) be16_to_cpu (head.y_max);
  214.     font->base.ascent = (int16_t) be16_to_cpu (hhea.ascender);
  215.     font->base.descent = (int16_t) be16_to_cpu (hhea.descender);
  216.     font->base.units_per_em = (int16_t) be16_to_cpu (head.units_per_em);
  217.     if (font->base.units_per_em == 0)
  218.         font->base.units_per_em = 2048;
  219.  
  220.     font->base.ps_name = NULL;
  221.     font->base.font_name = NULL;
  222.     status = _cairo_truetype_read_font_name (scaled_font_subset->scaled_font,
  223.                                              &font->base.ps_name,
  224.                                              &font->base.font_name);
  225.     if (_cairo_status_is_error (status))
  226.         goto fail3;
  227.  
  228.     /* If the PS name is not found, create a CairoFont-x-y name. */
  229.     if (font->base.ps_name == NULL) {
  230.         font->base.ps_name = malloc (30);
  231.         if (unlikely (font->base.ps_name == NULL)) {
  232.             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  233.             goto fail3;
  234.         }
  235.  
  236.         snprintf(font->base.ps_name, 30, "CairoFont-%u-%u",
  237.                  scaled_font_subset->font_id,
  238.                  scaled_font_subset->subset_id);
  239.     }
  240.  
  241.     font->base.widths = calloc (font->num_glyphs_in_face, sizeof (int));
  242.     if (unlikely (font->base.widths == NULL)) {
  243.         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  244.         goto fail4;
  245.     }
  246.  
  247.     _cairo_array_init (&font->string_offsets, sizeof (unsigned long));
  248.     status = _cairo_array_grow_by (&font->string_offsets, 10);
  249.     if (unlikely (status))
  250.         goto fail5;
  251.  
  252.     font->status = CAIRO_STATUS_SUCCESS;
  253.  
  254.     *font_return = font;
  255.  
  256.     return CAIRO_STATUS_SUCCESS;
  257.  
  258.  fail5:
  259.     _cairo_array_fini (&font->string_offsets);
  260.     free (font->base.widths);
  261.  fail4:
  262.     free (font->base.ps_name);
  263.  fail3:
  264.     free (font->parent_to_subset);
  265.     if (font->base.font_name)
  266.         free (font->base.font_name);
  267.  fail2:
  268.     free (font->glyphs);
  269.  fail1:
  270.     _cairo_array_fini (&font->output);
  271.     free (font);
  272.  
  273.     return status;
  274. }
  275.  
  276. static void
  277. cairo_truetype_font_destroy (cairo_truetype_font_t *font)
  278. {
  279.     _cairo_array_fini (&font->string_offsets);
  280.     free (font->base.widths);
  281.     free (font->base.ps_name);
  282.     if (font->base.font_name)
  283.         free (font->base.font_name);
  284.     free (font->parent_to_subset);
  285.     free (font->glyphs);
  286.     _cairo_array_fini (&font->output);
  287.     free (font);
  288. }
  289.  
  290. static cairo_status_t
  291. cairo_truetype_font_allocate_write_buffer (cairo_truetype_font_t  *font,
  292.                                            size_t                  length,
  293.                                            unsigned char         **buffer)
  294. {
  295.     cairo_status_t status;
  296.  
  297.     if (font->status)
  298.         return font->status;
  299.  
  300.     status = _cairo_array_allocate (&font->output, length, (void **) buffer);
  301.     if (unlikely (status))
  302.         return _cairo_truetype_font_set_error (font, status);
  303.  
  304.     return CAIRO_STATUS_SUCCESS;
  305. }
  306.  
  307. static void
  308. cairo_truetype_font_write (cairo_truetype_font_t *font,
  309.                            const void            *data,
  310.                            size_t                 length)
  311. {
  312.     cairo_status_t status;
  313.  
  314.     if (font->status)
  315.         return;
  316.  
  317.     status = _cairo_array_append_multiple (&font->output, data, length);
  318.     if (unlikely (status))
  319.         status = _cairo_truetype_font_set_error (font, status);
  320. }
  321.  
  322. static void
  323. cairo_truetype_font_write_be16 (cairo_truetype_font_t *font,
  324.                                 uint16_t               value)
  325. {
  326.     uint16_t be16_value;
  327.  
  328.     if (font->status)
  329.         return;
  330.  
  331.     be16_value = cpu_to_be16 (value);
  332.     cairo_truetype_font_write (font, &be16_value, sizeof be16_value);
  333. }
  334.  
  335. static void
  336. cairo_truetype_font_write_be32 (cairo_truetype_font_t *font,
  337.                                 uint32_t               value)
  338. {
  339.     uint32_t be32_value;
  340.  
  341.     if (font->status)
  342.         return;
  343.  
  344.     be32_value = cpu_to_be32 (value);
  345.     cairo_truetype_font_write (font, &be32_value, sizeof be32_value);
  346. }
  347.  
  348. static cairo_status_t
  349. cairo_truetype_font_align_output (cairo_truetype_font_t     *font,
  350.                                   unsigned long             *aligned)
  351. {
  352.     int length, pad;
  353.     unsigned char *padding;
  354.  
  355.     length = _cairo_array_num_elements (&font->output);
  356.     *aligned = (length + 3) & ~3;
  357.     pad = *aligned - length;
  358.  
  359.     if (pad) {
  360.         cairo_status_t status;
  361.  
  362.         status = cairo_truetype_font_allocate_write_buffer (font, pad,
  363.                                                             &padding);
  364.         if (unlikely (status))
  365.             return status;
  366.  
  367.         memset (padding, 0, pad);
  368.     }
  369.  
  370.     return CAIRO_STATUS_SUCCESS;
  371. }
  372.  
  373. static cairo_status_t
  374. cairo_truetype_font_check_boundary (cairo_truetype_font_t *font,
  375.                                     unsigned long          boundary)
  376. {
  377.     cairo_status_t status;
  378.  
  379.     if (font->status)
  380.         return font->status;
  381.  
  382.     if (boundary - font->last_offset > SFNT_STRING_MAX_LENGTH)
  383.     {
  384.         status = _cairo_array_append (&font->string_offsets,
  385.                                       &font->last_boundary);
  386.         if (unlikely (status))
  387.             return _cairo_truetype_font_set_error (font, status);
  388.  
  389.         font->last_offset = font->last_boundary;
  390.     }
  391.     font->last_boundary = boundary;
  392.  
  393.     return CAIRO_STATUS_SUCCESS;
  394. }
  395.  
  396. static cairo_status_t
  397. cairo_truetype_font_write_cmap_table (cairo_truetype_font_t *font,
  398.                                       unsigned long          tag)
  399. {
  400.     unsigned int i;
  401.  
  402.     cairo_truetype_font_write_be16 (font, 0);  /* Table version */
  403.     cairo_truetype_font_write_be16 (font, 2);  /* Num tables */
  404.  
  405.     cairo_truetype_font_write_be16 (font, 3);  /* Platform */
  406.     cairo_truetype_font_write_be16 (font, 0);  /* Encoding */
  407.     cairo_truetype_font_write_be32 (font, 20); /* Offset to start of table */
  408.  
  409.     cairo_truetype_font_write_be16 (font, 1);  /* Platform */
  410.     cairo_truetype_font_write_be16 (font, 0);  /* Encoding */
  411.     cairo_truetype_font_write_be32 (font, 52); /* Offset to start of table */
  412.  
  413.     /* Output a format 4 encoding table. */
  414.  
  415.     cairo_truetype_font_write_be16 (font, 4);  /* Format */
  416.     cairo_truetype_font_write_be16 (font, 32); /* Length */
  417.     cairo_truetype_font_write_be16 (font, 0);  /* Version */
  418.     cairo_truetype_font_write_be16 (font, 4);  /* 2*segcount */
  419.     cairo_truetype_font_write_be16 (font, 4);  /* searchrange */
  420.     cairo_truetype_font_write_be16 (font, 1);  /* entry selector */
  421.     cairo_truetype_font_write_be16 (font, 0);  /* rangeshift */
  422.     cairo_truetype_font_write_be16 (font, 0xf000 + font->base.num_glyphs - 1); /* end count[0] */
  423.     cairo_truetype_font_write_be16 (font, 0xffff);  /* end count[1] */
  424.     cairo_truetype_font_write_be16 (font, 0);       /* reserved */
  425.     cairo_truetype_font_write_be16 (font, 0xf000);  /* startCode[0] */
  426.     cairo_truetype_font_write_be16 (font, 0xffff);  /* startCode[1] */
  427.     cairo_truetype_font_write_be16 (font, 0x1000);  /* delta[0] */
  428.     cairo_truetype_font_write_be16 (font, 1);       /* delta[1] */
  429.     cairo_truetype_font_write_be16 (font, 0);       /* rangeOffset[0] */
  430.     cairo_truetype_font_write_be16 (font, 0);       /* rangeOffset[1] */
  431.  
  432.     /* Output a format 6 encoding table. */
  433.  
  434.     cairo_truetype_font_write_be16 (font, 6);
  435.     cairo_truetype_font_write_be16 (font, 10 + 2 * font->base.num_glyphs);
  436.     cairo_truetype_font_write_be16 (font, 0);
  437.     cairo_truetype_font_write_be16 (font, 0); /* First character */
  438.     cairo_truetype_font_write_be16 (font, font->base.num_glyphs);
  439.     for (i = 0; i < font->base.num_glyphs; i++)
  440.         cairo_truetype_font_write_be16 (font, i);
  441.  
  442.     return font->status;
  443. }
  444.  
  445. static cairo_status_t
  446. cairo_truetype_font_write_generic_table (cairo_truetype_font_t *font,
  447.                                          unsigned long          tag)
  448. {
  449.     cairo_status_t status;
  450.     unsigned char *buffer;
  451.     unsigned long size;
  452.  
  453.     if (font->status)
  454.         return font->status;
  455.  
  456.     size = 0;
  457.     status = font->backend->load_truetype_table(font->scaled_font_subset->scaled_font,
  458.                                                 tag, 0, NULL, &size);
  459.     if (unlikely (status))
  460.         return _cairo_truetype_font_set_error (font, status);
  461.  
  462.     status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
  463.     if (unlikely (status))
  464.         return _cairo_truetype_font_set_error (font, status);
  465.  
  466.     status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
  467.                                                  tag, 0, buffer, &size);
  468.     if (unlikely (status))
  469.         return _cairo_truetype_font_set_error (font, status);
  470.  
  471.     return CAIRO_STATUS_SUCCESS;
  472. }
  473.  
  474. static cairo_status_t
  475. cairo_truetype_font_remap_composite_glyph (cairo_truetype_font_t        *font,
  476.                                            unsigned char                *buffer,
  477.                                            unsigned long                 size)
  478. {
  479.     tt_glyph_data_t *glyph_data;
  480.     tt_composite_glyph_t *composite_glyph;
  481.     int num_args;
  482.     int has_more_components;
  483.     unsigned short flags;
  484.     unsigned short index;
  485.     cairo_status_t status;
  486.     unsigned char *end = buffer + size;
  487.  
  488.     if (font->status)
  489.         return font->status;
  490.  
  491.     glyph_data = (tt_glyph_data_t *) buffer;
  492.     if ((unsigned char *)(&glyph_data->data) >= end)
  493.         return CAIRO_INT_STATUS_UNSUPPORTED;
  494.  
  495.     if ((int16_t)be16_to_cpu (glyph_data->num_contours) >= 0)
  496.         return CAIRO_STATUS_SUCCESS;
  497.  
  498.     composite_glyph = &glyph_data->glyph;
  499.     do {
  500.         if ((unsigned char *)(&composite_glyph->args[1]) > end)
  501.             return CAIRO_INT_STATUS_UNSUPPORTED;
  502.  
  503.         flags = be16_to_cpu (composite_glyph->flags);
  504.         has_more_components = flags & TT_MORE_COMPONENTS;
  505.         status = cairo_truetype_font_use_glyph (font, be16_to_cpu (composite_glyph->index), &index);
  506.         if (unlikely (status))
  507.             return status;
  508.  
  509.         composite_glyph->index = cpu_to_be16 (index);
  510.         num_args = 1;
  511.         if (flags & TT_ARG_1_AND_2_ARE_WORDS)
  512.             num_args += 1;
  513.  
  514.         if (flags & TT_WE_HAVE_A_SCALE)
  515.             num_args += 1;
  516.         else if (flags & TT_WE_HAVE_AN_X_AND_Y_SCALE)
  517.             num_args += 2;
  518.         else if (flags & TT_WE_HAVE_A_TWO_BY_TWO)
  519.             num_args += 4;
  520.  
  521.         composite_glyph = (tt_composite_glyph_t *) &(composite_glyph->args[num_args]);
  522.     } while (has_more_components);
  523.  
  524.     return CAIRO_STATUS_SUCCESS;
  525. }
  526.  
  527. static cairo_status_t
  528. cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
  529.                                       unsigned long          tag)
  530. {
  531.     unsigned long start_offset, index, size, next;
  532.     tt_head_t header;
  533.     unsigned long begin, end;
  534.     unsigned char *buffer;
  535.     unsigned int i;
  536.     union {
  537.         unsigned char *bytes;
  538.         uint16_t      *short_offsets;
  539.         uint32_t      *long_offsets;
  540.     } u;
  541.     cairo_status_t status;
  542.  
  543.     if (font->status)
  544.         return font->status;
  545.  
  546.     size = sizeof (tt_head_t);
  547.     status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
  548.                                                  TT_TAG_head, 0,
  549.                                                  (unsigned char*) &header, &size);
  550.     if (unlikely (status))
  551.         return _cairo_truetype_font_set_error (font, status);
  552.  
  553.     if (be16_to_cpu (header.index_to_loc_format) == 0)
  554.         size = sizeof (int16_t) * (font->num_glyphs_in_face + 1);
  555.     else
  556.         size = sizeof (int32_t) * (font->num_glyphs_in_face + 1);
  557.  
  558.     u.bytes = malloc (size);
  559.     if (unlikely (u.bytes == NULL))
  560.         return _cairo_truetype_font_set_error (font, CAIRO_STATUS_NO_MEMORY);
  561.  
  562.     status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
  563.                                                  TT_TAG_loca, 0, u.bytes, &size);
  564.     if (unlikely (status))
  565.         return _cairo_truetype_font_set_error (font, status);
  566.  
  567.     start_offset = _cairo_array_num_elements (&font->output);
  568.     for (i = 0; i < font->base.num_glyphs; i++) {
  569.         index = font->glyphs[i].parent_index;
  570.         if (be16_to_cpu (header.index_to_loc_format) == 0) {
  571.             begin = be16_to_cpu (u.short_offsets[index]) * 2;
  572.             end = be16_to_cpu (u.short_offsets[index + 1]) * 2;
  573.         }
  574.         else {
  575.             begin = be32_to_cpu (u.long_offsets[index]);
  576.             end = be32_to_cpu (u.long_offsets[index + 1]);
  577.         }
  578.  
  579.         /* quick sanity check... */
  580.         if (end < begin) {
  581.             status = CAIRO_INT_STATUS_UNSUPPORTED;
  582.             goto FAIL;
  583.         }
  584.  
  585.         size = end - begin;
  586.         status = cairo_truetype_font_align_output (font, &next);
  587.         if (unlikely (status))
  588.             goto FAIL;
  589.  
  590.         status = cairo_truetype_font_check_boundary (font, next);
  591.         if (unlikely (status))
  592.             goto FAIL;
  593.  
  594.         font->glyphs[i].location = next - start_offset;
  595.  
  596.         status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
  597.         if (unlikely (status))
  598.             goto FAIL;
  599.  
  600.         if (size != 0) {
  601.             status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
  602.                                                          TT_TAG_glyf, begin, buffer, &size);
  603.             if (unlikely (status))
  604.                 goto FAIL;
  605.  
  606.             status = cairo_truetype_font_remap_composite_glyph (font, buffer, size);
  607.             if (unlikely (status))
  608.                 goto FAIL;
  609.         }
  610.     }
  611.  
  612.     status = cairo_truetype_font_align_output (font, &next);
  613.     if (unlikely (status))
  614.         goto FAIL;
  615.  
  616.     font->glyphs[i].location = next - start_offset;
  617.  
  618.     status = font->status;
  619. FAIL:
  620.     free (u.bytes);
  621.  
  622.     return _cairo_truetype_font_set_error (font, status);
  623. }
  624.  
  625. static cairo_status_t
  626. cairo_truetype_font_write_head_table (cairo_truetype_font_t *font,
  627.                                       unsigned long          tag)
  628. {
  629.     unsigned char *buffer;
  630.     unsigned long size;
  631.     cairo_status_t status;
  632.  
  633.     if (font->status)
  634.         return font->status;
  635.  
  636.     size = 0;
  637.     status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
  638.                                                  tag, 0, NULL, &size);
  639.     if (unlikely (status))
  640.         return _cairo_truetype_font_set_error (font, status);
  641.  
  642.     font->checksum_index = _cairo_array_num_elements (&font->output) + 8;
  643.     status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
  644.     if (unlikely (status))
  645.         return _cairo_truetype_font_set_error (font, status);
  646.  
  647.     status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
  648.                                                  tag, 0, buffer, &size);
  649.     if (unlikely (status))
  650.         return _cairo_truetype_font_set_error (font, status);
  651.  
  652.     /* set checkSumAdjustment to 0 for table checksum calculation */
  653.     *(uint32_t *)(buffer + 8) = 0;
  654.  
  655.     return CAIRO_STATUS_SUCCESS;
  656. }
  657.  
  658. static cairo_status_t
  659. cairo_truetype_font_write_hhea_table (cairo_truetype_font_t *font, unsigned long tag)
  660. {
  661.     tt_hhea_t *hhea;
  662.     unsigned long size;
  663.     cairo_status_t status;
  664.  
  665.     if (font->status)
  666.         return font->status;
  667.  
  668.     size = sizeof (tt_hhea_t);
  669.     status = cairo_truetype_font_allocate_write_buffer (font, size, (unsigned char **) &hhea);
  670.     if (unlikely (status))
  671.         return _cairo_truetype_font_set_error (font, status);
  672.  
  673.     status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
  674.                                                  tag, 0, (unsigned char *) hhea, &size);
  675.     if (unlikely (status))
  676.         return _cairo_truetype_font_set_error (font, status);
  677.  
  678.     hhea->num_hmetrics = cpu_to_be16 ((uint16_t)(font->base.num_glyphs));
  679.  
  680.     return CAIRO_STATUS_SUCCESS;
  681. }
  682.  
  683. static cairo_status_t
  684. cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font,
  685.                                       unsigned long          tag)
  686. {
  687.     unsigned long size;
  688.     unsigned long long_entry_size;
  689.     unsigned long short_entry_size;
  690.     short *p;
  691.     unsigned int i;
  692.     tt_hhea_t hhea;
  693.     int num_hmetrics;
  694.     cairo_status_t status;
  695.  
  696.     if (font->status)
  697.         return font->status;
  698.  
  699.     size = sizeof (tt_hhea_t);
  700.     status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
  701.                                                  TT_TAG_hhea, 0,
  702.                                                  (unsigned char*) &hhea, &size);
  703.     if (unlikely (status))
  704.         return _cairo_truetype_font_set_error (font, status);
  705.  
  706.     num_hmetrics = be16_to_cpu(hhea.num_hmetrics);
  707.  
  708.     for (i = 0; i < font->base.num_glyphs; i++) {
  709.         long_entry_size = 2 * sizeof (int16_t);
  710.         short_entry_size = sizeof (int16_t);
  711.         status = cairo_truetype_font_allocate_write_buffer (font,
  712.                                                             long_entry_size,
  713.                                                             (unsigned char **) &p);
  714.         if (unlikely (status))
  715.             return _cairo_truetype_font_set_error (font, status);
  716.  
  717.         if (font->glyphs[i].parent_index < num_hmetrics) {
  718.             status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
  719.                                                          TT_TAG_hmtx,
  720.                                                          font->glyphs[i].parent_index * long_entry_size,
  721.                                                          (unsigned char *) p, &long_entry_size);
  722.             if (unlikely (status))
  723.                 return _cairo_truetype_font_set_error (font, status);
  724.         }
  725.         else
  726.         {
  727.             status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
  728.                                                          TT_TAG_hmtx,
  729.                                                          (num_hmetrics - 1) * long_entry_size,
  730.                                                          (unsigned char *) p, &short_entry_size);
  731.             if (unlikely (status))
  732.                 return _cairo_truetype_font_set_error (font, status);
  733.  
  734.             status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
  735.                                                          TT_TAG_hmtx,
  736.                                                          num_hmetrics * long_entry_size +
  737.                                                          (font->glyphs[i].parent_index - num_hmetrics) * short_entry_size,
  738.                                                          (unsigned char *) (p + 1), &short_entry_size);
  739.             if (unlikely (status))
  740.                 return _cairo_truetype_font_set_error (font, status);
  741.         }
  742.         font->base.widths[i] = be16_to_cpu (p[0]);
  743.     }
  744.  
  745.     return CAIRO_STATUS_SUCCESS;
  746. }
  747.  
  748. static cairo_status_t
  749. cairo_truetype_font_write_loca_table (cairo_truetype_font_t *font,
  750.                                       unsigned long          tag)
  751. {
  752.     unsigned int i;
  753.     tt_head_t header;
  754.     unsigned long size;
  755.     cairo_status_t status;
  756.  
  757.     if (font->status)
  758.         return font->status;
  759.  
  760.     size = sizeof(tt_head_t);
  761.     status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
  762.                                                  TT_TAG_head, 0,
  763.                                                  (unsigned char*) &header, &size);
  764.     if (unlikely (status))
  765.         return _cairo_truetype_font_set_error (font, status);
  766.  
  767.     if (be16_to_cpu (header.index_to_loc_format) == 0)
  768.     {
  769.         for (i = 0; i < font->base.num_glyphs + 1; i++)
  770.             cairo_truetype_font_write_be16 (font, font->glyphs[i].location / 2);
  771.     } else {
  772.         for (i = 0; i < font->base.num_glyphs + 1; i++)
  773.             cairo_truetype_font_write_be32 (font, font->glyphs[i].location);
  774.     }
  775.  
  776.     return font->status;
  777. }
  778.  
  779. static cairo_status_t
  780. cairo_truetype_font_write_maxp_table (cairo_truetype_font_t *font,
  781.                                       unsigned long          tag)
  782. {
  783.     tt_maxp_t *maxp;
  784.     unsigned long size;
  785.     cairo_status_t status;
  786.  
  787.     if (font->status)
  788.         return font->status;
  789.  
  790.     size = sizeof (tt_maxp_t);
  791.     status = cairo_truetype_font_allocate_write_buffer (font, size, (unsigned char **) &maxp);
  792.     if (unlikely (status))
  793.         return _cairo_truetype_font_set_error (font, status);
  794.  
  795.     status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
  796.                                                  tag, 0, (unsigned char *) maxp, &size);
  797.     if (unlikely (status))
  798.         return _cairo_truetype_font_set_error (font, status);
  799.  
  800.     maxp->num_glyphs = cpu_to_be16 (font->base.num_glyphs);
  801.  
  802.     return CAIRO_STATUS_SUCCESS;
  803. }
  804.  
  805. static cairo_status_t
  806. cairo_truetype_font_write_offset_table (cairo_truetype_font_t *font)
  807. {
  808.     cairo_status_t status;
  809.     unsigned char *table_buffer;
  810.     size_t table_buffer_length;
  811.     unsigned short search_range, entry_selector, range_shift;
  812.  
  813.     if (font->status)
  814.         return font->status;
  815.  
  816.     search_range = 1;
  817.     entry_selector = 0;
  818.     while (search_range * 2 <= font->num_tables) {
  819.         search_range *= 2;
  820.         entry_selector++;
  821.     }
  822.     search_range *= 16;
  823.     range_shift = font->num_tables * 16 - search_range;
  824.  
  825.     cairo_truetype_font_write_be32 (font, SFNT_VERSION);
  826.     cairo_truetype_font_write_be16 (font, font->num_tables);
  827.     cairo_truetype_font_write_be16 (font, search_range);
  828.     cairo_truetype_font_write_be16 (font, entry_selector);
  829.     cairo_truetype_font_write_be16 (font, range_shift);
  830.  
  831.     /* Allocate space for the table directory. Each directory entry
  832.      * will be filled in by cairo_truetype_font_update_entry() after
  833.      * the table is written. */
  834.     table_buffer_length = font->num_tables * 16;
  835.     status = cairo_truetype_font_allocate_write_buffer (font, table_buffer_length,
  836.                                                       &table_buffer);
  837.     if (unlikely (status))
  838.         return _cairo_truetype_font_set_error (font, status);
  839.  
  840.     return CAIRO_STATUS_SUCCESS;
  841. }
  842.  
  843. static uint32_t
  844. cairo_truetype_font_calculate_checksum (cairo_truetype_font_t *font,
  845.                                         unsigned long          start,
  846.                                         unsigned long          end)
  847. {
  848.     uint32_t *padded_end;
  849.     uint32_t *p;
  850.     uint32_t checksum;
  851.     char *data;
  852.  
  853.     checksum = 0;
  854.     data = _cairo_array_index (&font->output, 0);
  855.     p = (uint32_t *) (data + start);
  856.     padded_end = (uint32_t *) (data + ((end + 3) & ~3));
  857.     while (p < padded_end)
  858.         checksum += be32_to_cpu(*p++);
  859.  
  860.     return checksum;
  861. }
  862.  
  863. static void
  864. cairo_truetype_font_update_entry (cairo_truetype_font_t *font,
  865.                                   int                    index,
  866.                                   unsigned long          tag,
  867.                                   unsigned long          start,
  868.                                   unsigned long          end)
  869. {
  870.     uint32_t *entry;
  871.  
  872.     entry = _cairo_array_index (&font->output, 12 + 16 * index);
  873.     entry[0] = cpu_to_be32 ((uint32_t)tag);
  874.     entry[1] = cpu_to_be32 (cairo_truetype_font_calculate_checksum (font, start, end));
  875.     entry[2] = cpu_to_be32 ((uint32_t)start);
  876.     entry[3] = cpu_to_be32 ((uint32_t)(end - start));
  877. }
  878.  
  879. static cairo_status_t
  880. cairo_truetype_font_generate (cairo_truetype_font_t  *font,
  881.                               const char            **data,
  882.                               unsigned long          *length,
  883.                               const unsigned long   **string_offsets,
  884.                               unsigned long          *num_strings)
  885. {
  886.     cairo_status_t status;
  887.     unsigned long start, end, next;
  888.     uint32_t checksum, *checksum_location;
  889.     int i;
  890.  
  891.     if (font->status)
  892.         return font->status;
  893.  
  894.     status = cairo_truetype_font_write_offset_table (font);
  895.     if (unlikely (status))
  896.         goto FAIL;
  897.  
  898.     status = cairo_truetype_font_align_output (font, &start);
  899.     if (unlikely (status))
  900.         goto FAIL;
  901.  
  902.     end = 0;
  903.     for (i = 0; i < font->num_tables; i++) {
  904.         status = font->truetype_tables[i].write (font, font->truetype_tables[i].tag);
  905.         if (unlikely (status))
  906.             goto FAIL;
  907.  
  908.         end = _cairo_array_num_elements (&font->output);
  909.         status = cairo_truetype_font_align_output (font, &next);
  910.         if (unlikely (status))
  911.             goto FAIL;
  912.  
  913.         cairo_truetype_font_update_entry (font, font->truetype_tables[i].pos,
  914.                                           font->truetype_tables[i].tag, start, end);
  915.         status = cairo_truetype_font_check_boundary (font, next);
  916.         if (unlikely (status))
  917.             goto FAIL;
  918.  
  919.         start = next;
  920.     }
  921.  
  922.     checksum =
  923.         0xb1b0afba - cairo_truetype_font_calculate_checksum (font, 0, end);
  924.     checksum_location = _cairo_array_index (&font->output, font->checksum_index);
  925.     *checksum_location = cpu_to_be32 (checksum);
  926.  
  927.     *data = _cairo_array_index (&font->output, 0);
  928.     *length = _cairo_array_num_elements (&font->output);
  929.     *num_strings = _cairo_array_num_elements (&font->string_offsets);
  930.     if (*num_strings != 0)
  931.         *string_offsets = _cairo_array_index (&font->string_offsets, 0);
  932.     else
  933.         *string_offsets = NULL;
  934.  
  935.  FAIL:
  936.     return _cairo_truetype_font_set_error (font, status);
  937. }
  938.  
  939. static cairo_status_t
  940. cairo_truetype_font_use_glyph (cairo_truetype_font_t        *font,
  941.                                unsigned short                glyph,
  942.                                unsigned short               *out)
  943. {
  944.     if (glyph >= font->num_glyphs_in_face)
  945.         return CAIRO_INT_STATUS_UNSUPPORTED;
  946.  
  947.     if (font->parent_to_subset[glyph] == 0) {
  948.         font->parent_to_subset[glyph] = font->base.num_glyphs;
  949.         font->glyphs[font->base.num_glyphs].parent_index = glyph;
  950.         font->base.num_glyphs++;
  951.     }
  952.  
  953.     *out = font->parent_to_subset[glyph];
  954.     return CAIRO_STATUS_SUCCESS;
  955. }
  956.  
  957. static void
  958. cairo_truetype_font_add_truetype_table (cairo_truetype_font_t *font,
  959.            unsigned long tag,
  960.            cairo_status_t (*write) (cairo_truetype_font_t *font, unsigned long tag),
  961.            int pos)
  962. {
  963.     font->truetype_tables[font->num_tables].tag = tag;
  964.     font->truetype_tables[font->num_tables].write = write;
  965.     font->truetype_tables[font->num_tables].pos = pos;
  966.     font->num_tables++;
  967. }
  968.  
  969. /* cairo_truetype_font_create_truetype_table_list() builds the list of
  970.  * truetype tables to be embedded in the subsetted font. Each call to
  971.  * cairo_truetype_font_add_truetype_table() adds a table, the callback
  972.  * for generating the table, and the position in the table directory
  973.  * to the truetype_tables array.
  974.  *
  975.  * As we write out the glyf table we remap composite glyphs.
  976.  * Remapping composite glyphs will reference the sub glyphs the
  977.  * composite glyph is made up of. The "glyf" table callback needs to
  978.  * be called first so we have all the glyphs in the subset before
  979.  * going further.
  980.  *
  981.  * The order in which tables are added to the truetype_table array
  982.  * using cairo_truetype_font_add_truetype_table() specifies the order
  983.  * in which the callback functions will be called.
  984.  *
  985.  * The tables in the table directory must be listed in alphabetical
  986.  * order.  The "cvt", "fpgm", and "prep" are optional tables. They
  987.  * will only be embedded in the subset if they exist in the source
  988.  * font. The pos parameter of cairo_truetype_font_add_truetype_table()
  989.  * specifies the position of the table in the table directory.
  990.  */
  991. static void
  992. cairo_truetype_font_create_truetype_table_list (cairo_truetype_font_t *font)
  993. {
  994.     cairo_bool_t has_cvt = FALSE;
  995.     cairo_bool_t has_fpgm = FALSE;
  996.     cairo_bool_t has_prep = FALSE;
  997.     unsigned long size;
  998.     int pos;
  999.  
  1000.     size = 0;
  1001.     if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
  1002.                                       TT_TAG_cvt, 0, NULL,
  1003.                                       &size) == CAIRO_STATUS_SUCCESS)
  1004.         has_cvt = TRUE;
  1005.  
  1006.     size = 0;
  1007.     if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
  1008.                                       TT_TAG_fpgm, 0, NULL,
  1009.                                       &size) == CAIRO_STATUS_SUCCESS)
  1010.         has_fpgm = TRUE;
  1011.  
  1012.     size = 0;
  1013.     if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
  1014.                                       TT_TAG_prep, 0, NULL,
  1015.                                       &size) == CAIRO_STATUS_SUCCESS)
  1016.         has_prep = TRUE;
  1017.  
  1018.     font->num_tables = 0;
  1019.     pos = 1;
  1020.     if (has_cvt)
  1021.         pos++;
  1022.     if (has_fpgm)
  1023.         pos++;
  1024.     cairo_truetype_font_add_truetype_table (font, TT_TAG_glyf, cairo_truetype_font_write_glyf_table, pos);
  1025.  
  1026.     pos = 0;
  1027.     cairo_truetype_font_add_truetype_table (font, TT_TAG_cmap, cairo_truetype_font_write_cmap_table, pos++);
  1028.     if (has_cvt)
  1029.         cairo_truetype_font_add_truetype_table (font, TT_TAG_cvt, cairo_truetype_font_write_generic_table, pos++);
  1030.     if (has_fpgm)
  1031.         cairo_truetype_font_add_truetype_table (font, TT_TAG_fpgm, cairo_truetype_font_write_generic_table, pos++);
  1032.     pos++;
  1033.     cairo_truetype_font_add_truetype_table (font, TT_TAG_head, cairo_truetype_font_write_head_table, pos++);
  1034.     cairo_truetype_font_add_truetype_table (font, TT_TAG_hhea, cairo_truetype_font_write_hhea_table, pos++);
  1035.     cairo_truetype_font_add_truetype_table (font, TT_TAG_hmtx, cairo_truetype_font_write_hmtx_table, pos++);
  1036.     cairo_truetype_font_add_truetype_table (font, TT_TAG_loca, cairo_truetype_font_write_loca_table, pos++);
  1037.     cairo_truetype_font_add_truetype_table (font, TT_TAG_maxp, cairo_truetype_font_write_maxp_table, pos++);
  1038.     if (has_prep)
  1039.         cairo_truetype_font_add_truetype_table (font, TT_TAG_prep, cairo_truetype_font_write_generic_table, pos);
  1040. }
  1041.  
  1042. cairo_status_t
  1043. _cairo_truetype_subset_init (cairo_truetype_subset_t    *truetype_subset,
  1044.                              cairo_scaled_font_subset_t *font_subset)
  1045. {
  1046.     cairo_truetype_font_t *font = NULL;
  1047.     cairo_status_t status;
  1048.     const char *data = NULL; /* squelch bogus compiler warning */
  1049.     unsigned long length = 0; /* squelch bogus compiler warning */
  1050.     unsigned long offsets_length;
  1051.     unsigned int i;
  1052.     const unsigned long *string_offsets = NULL;
  1053.     unsigned long num_strings = 0;
  1054.  
  1055.     status = _cairo_truetype_font_create (font_subset, &font);
  1056.     if (unlikely (status))
  1057.         return status;
  1058.  
  1059.     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
  1060.         unsigned short parent_glyph = font->scaled_font_subset->glyphs[i];
  1061.         status = cairo_truetype_font_use_glyph (font, parent_glyph, &parent_glyph);
  1062.         if (unlikely (status))
  1063.             goto fail1;
  1064.     }
  1065.  
  1066.     cairo_truetype_font_create_truetype_table_list (font);
  1067.     status = cairo_truetype_font_generate (font, &data, &length,
  1068.                                            &string_offsets, &num_strings);
  1069.     if (unlikely (status))
  1070.         goto fail1;
  1071.  
  1072.     truetype_subset->ps_name = strdup (font->base.ps_name);
  1073.     if (unlikely (truetype_subset->ps_name == NULL)) {
  1074.         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  1075.         goto fail1;
  1076.     }
  1077.  
  1078.     if (font->base.font_name != NULL) {
  1079.         truetype_subset->font_name = strdup (font->base.font_name);
  1080.         if (unlikely (truetype_subset->font_name == NULL)) {
  1081.             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  1082.             goto fail2;
  1083.         }
  1084.     } else {
  1085.         truetype_subset->font_name = NULL;
  1086.     }
  1087.  
  1088.     /* The widths array returned must contain only widths for the
  1089.      * glyphs in font_subset. Any subglyphs appended after
  1090.      * font_subset->num_glyphs are omitted. */
  1091.     truetype_subset->widths = calloc (sizeof (double),
  1092.                                       font->scaled_font_subset->num_glyphs);
  1093.     if (unlikely (truetype_subset->widths == NULL)) {
  1094.         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  1095.         goto fail3;
  1096.     }
  1097.     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
  1098.         truetype_subset->widths[i] = (double)font->base.widths[i]/font->base.units_per_em;
  1099.  
  1100.     truetype_subset->x_min = (double)font->base.x_min/font->base.units_per_em;
  1101.     truetype_subset->y_min = (double)font->base.y_min/font->base.units_per_em;
  1102.     truetype_subset->x_max = (double)font->base.x_max/font->base.units_per_em;
  1103.     truetype_subset->y_max = (double)font->base.y_max/font->base.units_per_em;
  1104.     truetype_subset->ascent = (double)font->base.ascent/font->base.units_per_em;
  1105.     truetype_subset->descent = (double)font->base.descent/font->base.units_per_em;
  1106.  
  1107.     if (length) {
  1108.         truetype_subset->data = malloc (length);
  1109.         if (unlikely (truetype_subset->data == NULL)) {
  1110.             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  1111.             goto fail4;
  1112.         }
  1113.  
  1114.         memcpy (truetype_subset->data, data, length);
  1115.     } else
  1116.         truetype_subset->data = NULL;
  1117.     truetype_subset->data_length = length;
  1118.  
  1119.     if (num_strings) {
  1120.         offsets_length = num_strings * sizeof (unsigned long);
  1121.         truetype_subset->string_offsets = malloc (offsets_length);
  1122.         if (unlikely (truetype_subset->string_offsets == NULL)) {
  1123.             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  1124.             goto fail5;
  1125.         }
  1126.  
  1127.         memcpy (truetype_subset->string_offsets, string_offsets, offsets_length);
  1128.         truetype_subset->num_string_offsets = num_strings;
  1129.     } else {
  1130.         truetype_subset->string_offsets = NULL;
  1131.         truetype_subset->num_string_offsets = 0;
  1132.     }
  1133.  
  1134.     cairo_truetype_font_destroy (font);
  1135.  
  1136.     return CAIRO_STATUS_SUCCESS;
  1137.  
  1138.  fail5:
  1139.     free (truetype_subset->data);
  1140.  fail4:
  1141.     free (truetype_subset->widths);
  1142.  fail3:
  1143.     if (truetype_subset->font_name)
  1144.         free (truetype_subset->font_name);
  1145.  fail2:
  1146.     free (truetype_subset->ps_name);
  1147.  fail1:
  1148.     cairo_truetype_font_destroy (font);
  1149.  
  1150.     return status;
  1151. }
  1152.  
  1153. void
  1154. _cairo_truetype_subset_fini (cairo_truetype_subset_t *subset)
  1155. {
  1156.     free (subset->ps_name);
  1157.     if (subset->font_name)
  1158.         free (subset->font_name);
  1159.     free (subset->widths);
  1160.     free (subset->data);
  1161.     free (subset->string_offsets);
  1162. }
  1163.  
  1164. static cairo_int_status_t
  1165. _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font,
  1166.                               unsigned long        table_offset,
  1167.                               unsigned long        index,
  1168.                               uint32_t            *ucs4)
  1169. {
  1170.     cairo_status_t status;
  1171.     const cairo_scaled_font_backend_t *backend;
  1172.     tt_segment_map_t *map;
  1173.     char buf[4];
  1174.     unsigned int num_segments, i;
  1175.     unsigned long size;
  1176.     uint16_t *start_code;
  1177.     uint16_t *end_code;
  1178.     uint16_t *delta;
  1179.     uint16_t *range_offset;
  1180.     uint16_t *glyph_array;
  1181.     uint16_t  c;
  1182.  
  1183.     backend = scaled_font->backend;
  1184.     size = 4;
  1185.     status = backend->load_truetype_table (scaled_font,
  1186.                                            TT_TAG_cmap, table_offset,
  1187.                                            (unsigned char *) &buf,
  1188.                                            &size);
  1189.     if (unlikely (status))
  1190.         return status;
  1191.  
  1192.     /* All table formats have the same first two words */
  1193.     map = (tt_segment_map_t *) buf;
  1194.     if (be16_to_cpu (map->format) != 4)
  1195.         return CAIRO_INT_STATUS_UNSUPPORTED;
  1196.  
  1197.     size = be16_to_cpu (map->length);
  1198.     map = malloc (size);
  1199.     if (unlikely (map == NULL))
  1200.         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  1201.  
  1202.     status = backend->load_truetype_table (scaled_font,
  1203.                                            TT_TAG_cmap, table_offset,
  1204.                                            (unsigned char *) map,
  1205.                                            &size);
  1206.     if (unlikely (status))
  1207.         goto fail;
  1208.  
  1209.     num_segments = be16_to_cpu (map->segCountX2)/2;
  1210.  
  1211.     /* A Format 4 cmap contains 8 uint16_t numbers and 4 arrays of
  1212.      * uint16_t each num_segments long. */
  1213.     if (size < (8 + 4*num_segments)*sizeof(uint16_t))
  1214.         return CAIRO_INT_STATUS_UNSUPPORTED;
  1215.  
  1216.     end_code = map->endCount;
  1217.     start_code = &(end_code[num_segments + 1]);
  1218.     delta = &(start_code[num_segments]);
  1219.     range_offset = &(delta[num_segments]);
  1220.     glyph_array = &(range_offset[num_segments]);
  1221.  
  1222.     /* search for glyph in segments with rangeOffset=0 */
  1223.     for (i = 0; i < num_segments; i++) {
  1224.         c = index - be16_to_cpu (delta[i]);
  1225.         if (range_offset[i] == 0 &&
  1226.             c >= be16_to_cpu (start_code[i]) &&
  1227.             c <= be16_to_cpu (end_code[i]))
  1228.         {
  1229.             *ucs4 = c;
  1230.             goto found;
  1231.         }
  1232.     }
  1233.  
  1234.     /* search for glyph in segments with rangeOffset=1 */
  1235.     for (i = 0; i < num_segments; i++) {
  1236.         if (range_offset[i] != 0) {
  1237.             uint16_t *glyph_ids = &range_offset[i] + be16_to_cpu (range_offset[i])/2;
  1238.             int range_size = be16_to_cpu (end_code[i]) - be16_to_cpu (start_code[i]) + 1;
  1239.             uint16_t g_id_be = cpu_to_be16 (index);
  1240.             int j;
  1241.  
  1242.             if (range_size > 0) {
  1243.                 if ((char*)glyph_ids + 2*range_size > (char*)map + size)
  1244.                     return CAIRO_INT_STATUS_UNSUPPORTED;
  1245.  
  1246.                 for (j = 0; j < range_size; j++) {
  1247.                     if (glyph_ids[j] == g_id_be) {
  1248.                         *ucs4 = be16_to_cpu (start_code[i]) + j;
  1249.                         goto found;
  1250.                     }
  1251.                 }
  1252.             }
  1253.         }
  1254.     }
  1255.  
  1256.     /* glyph not found */
  1257.     *ucs4 = -1;
  1258.  
  1259. found:
  1260.     status = CAIRO_STATUS_SUCCESS;
  1261.  
  1262. fail:
  1263.     free (map);
  1264.  
  1265.     return status;
  1266. }
  1267.  
  1268. cairo_int_status_t
  1269. _cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font,
  1270.                                unsigned long        index,
  1271.                                uint32_t            *ucs4)
  1272. {
  1273.     cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
  1274.     const cairo_scaled_font_backend_t *backend;
  1275.     tt_cmap_t *cmap;
  1276.     char buf[4];
  1277.     int num_tables, i;
  1278.     unsigned long size;
  1279.  
  1280.     backend = scaled_font->backend;
  1281.     if (!backend->load_truetype_table)
  1282.         return CAIRO_INT_STATUS_UNSUPPORTED;
  1283.  
  1284.     size = 4;
  1285.     status = backend->load_truetype_table (scaled_font,
  1286.                                            TT_TAG_cmap, 0,
  1287.                                            (unsigned char *) &buf,
  1288.                                            &size);
  1289.     if (unlikely (status))
  1290.         return status;
  1291.  
  1292.     cmap = (tt_cmap_t *) buf;
  1293.     num_tables = be16_to_cpu (cmap->num_tables);
  1294.     size = 4 + num_tables*sizeof(tt_cmap_index_t);
  1295.     cmap = _cairo_malloc_ab_plus_c (num_tables, sizeof (tt_cmap_index_t), 4);
  1296.     if (unlikely (cmap == NULL))
  1297.         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  1298.  
  1299.     status = backend->load_truetype_table (scaled_font,
  1300.                                            TT_TAG_cmap, 0,
  1301.                                            (unsigned char *) cmap,
  1302.                                            &size);
  1303.     if (unlikely (status))
  1304.         goto cleanup;
  1305.  
  1306.     /* Find a table with Unicode mapping */
  1307.     for (i = 0; i < num_tables; i++) {
  1308.         if (be16_to_cpu (cmap->index[i].platform) == 3 &&
  1309.             be16_to_cpu (cmap->index[i].encoding) == 1) {
  1310.             status = _cairo_truetype_reverse_cmap (scaled_font,
  1311.                                                    be32_to_cpu (cmap->index[i].offset),
  1312.                                                    index,
  1313.                                                    ucs4);
  1314.             if (status != CAIRO_INT_STATUS_UNSUPPORTED)
  1315.                 break;
  1316.         }
  1317.     }
  1318.  
  1319. cleanup:
  1320.     free (cmap);
  1321.  
  1322.     return status;
  1323. }
  1324.  
  1325. cairo_int_status_t
  1326. _cairo_truetype_read_font_name (cairo_scaled_font_t      *scaled_font,
  1327.                                 char                    **ps_name_out,
  1328.                                 char                    **font_name_out)
  1329. {
  1330.     cairo_status_t status;
  1331.     const cairo_scaled_font_backend_t *backend;
  1332.     tt_name_t *name;
  1333.     tt_name_record_t *record;
  1334.     unsigned long size;
  1335.     int i, j;
  1336.     char *ps_name = NULL;
  1337.     char *font_name = NULL;
  1338.  
  1339.     backend = scaled_font->backend;
  1340.     if (!backend->load_truetype_table)
  1341.         return CAIRO_INT_STATUS_UNSUPPORTED;
  1342.  
  1343.     size = 0;
  1344.     status = backend->load_truetype_table (scaled_font,
  1345.                                            TT_TAG_name, 0,
  1346.                                            NULL,
  1347.                                            &size);
  1348.     if (status)
  1349.         return status;
  1350.  
  1351.     name = malloc (size);
  1352.     if (name == NULL)
  1353.         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  1354.  
  1355.    status = backend->load_truetype_table (scaled_font,
  1356.                                            TT_TAG_name, 0,
  1357.                                            (unsigned char *) name,
  1358.                                            &size);
  1359.     if (status)
  1360.         goto fail;
  1361.  
  1362.     /* Extract the font name and PS name from the name table. At
  1363.      * present this just looks for the Mac platform/Roman encoded font
  1364.      * name. It should be extended to use any suitable font name in
  1365.      * the name table.
  1366.      */
  1367.     for (i = 0; i < be16_to_cpu(name->num_records); i++) {
  1368.         record = &(name->records[i]);
  1369.         if ((be16_to_cpu (record->platform) == 1) &&
  1370.             (be16_to_cpu (record->encoding) == 0)) {
  1371.  
  1372.             if (be16_to_cpu (record->name) == 4) {
  1373.                 font_name = malloc (be16_to_cpu(record->length) + 1);
  1374.                 if (font_name == NULL) {
  1375.                     status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  1376.                     goto fail;
  1377.                 }
  1378.                 strncpy(font_name,
  1379.                         ((char*)name) + be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset),
  1380.                         be16_to_cpu (record->length));
  1381.                 font_name[be16_to_cpu (record->length)] = 0;
  1382.             }
  1383.  
  1384.             if (be16_to_cpu (record->name) == 6) {
  1385.                 ps_name = malloc (be16_to_cpu(record->length) + 1);
  1386.                 if (ps_name == NULL) {
  1387.                     status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  1388.                     goto fail;
  1389.                 }
  1390.                 strncpy(ps_name,
  1391.                         ((char*)name) + be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset),
  1392.                         be16_to_cpu (record->length));
  1393.                 ps_name[be16_to_cpu (record->length)] = 0;
  1394.             }
  1395.  
  1396.             if (font_name && ps_name)
  1397.                 break;
  1398.         }
  1399.     }
  1400.  
  1401.     free (name);
  1402.  
  1403.     /* Ensure PS name does not contain any spaces */
  1404.     if (ps_name) {
  1405.         for (i = 0, j = 0; ps_name[j]; j++) {
  1406.             if (ps_name[j] == ' ')
  1407.                 continue;
  1408.             ps_name[i++] = ps_name[j];
  1409.         }
  1410.         ps_name[i] = '\0';
  1411.     }
  1412.  
  1413.     *ps_name_out = ps_name;
  1414.     *font_name_out = font_name;
  1415.  
  1416.     return CAIRO_STATUS_SUCCESS;
  1417.  
  1418. fail:
  1419.     free (name);
  1420.  
  1421.     if (ps_name != NULL)
  1422.         free (ps_name);
  1423.  
  1424.     if (font_name != NULL)
  1425.         free (font_name);
  1426.  
  1427.     *ps_name_out = NULL;
  1428.     *font_name_out = NULL;
  1429.  
  1430.     return status;
  1431. }
  1432.  
  1433. #endif /* CAIRO_HAS_FONT_SUBSET */
  1434.