Index

C/C++ Functions

dtFontAddAsMMInstance

DT_ID_SWORD dtFontAddAsMMInstance(DT_DTENGINE engine, DT_ID_SWORD font_index, const DT_SWORD contribs[])

Short Description: Add new font as a Multiple-Master font instance and return its font index

dtFontAddAsMMInstancePlus

DT_ID_SWORD dtFontAddAsMMInstancePlus(DT_DTENGINE engine, DT_ID_SWORD font_index, DT_ID_SWORD contribs_flag, DT_SWORD contribs_len, const DT_SLONG contribs[])

Short Description: Add new font as a Multiple-Master font instance and return its font index

These two functions add an interpolated multiple-master font instance to the Font Catalog of the specified Standard Engine instance.

Similar to dtFontAddViaStream, these functions return a font index for the newly added font instance. This index uniquely identifies the font (or font instance) in the Font Catalog.

dtFontAddAsMMInstance is deprecated; this function has the same effect as calling dtFontAddAsMMInstancePlus with contribs_flag set to DV_MMCONTRIB_TYPE_DIM_NORM1024 and contribs_len set to dim, where dim can be obtained by calling the dtFontGetDim or dtFontGetMMAxisInfo function.

Parameters

ParameterDescription

engine

Handle of the previously created Standard Engine instance.

font_index

Font index of an existing multiple-master font or multiple-master font instance in the Font Catalog. The new interpolated multiple-master font instance will be created from the font or font instance specified by that font index.

contribs_flag

Identifies how the dtFontAddAsMMInstancePlus function should interpret the values stored in the contribs array. Can be one of the following:

  • 0 (DV_MMCONTRIB_TYPE_NONE) — This option will be described in the future.

  • 1 (DV_MMCONTRIB_TYPE_DIM_NORM1024) — Each element in the contribs array represents a contribution of the corresponding base design in the final interpolated font instance. The value of each element must be in the 0 - 1024 range, where zero means "no contribution" (or 0% contribution) and 1024 means "full contribution" (or 100% contribution). The sum of all the elements in the array must equal 1024 (or 100%), otherwise unexpected results might occur.

  • 2 (DV_MMCONTRIB_TYPE_DIM_NORM16384) — Each element in the contribs array represents a contribution of the corresponding base design in the final interpolated font instance. The value of each element must be in the 0 - 16384 range, where zero means "no contribution" (or 0% contribution) and 16384 means "full contribution" (or 100% contribution). The sum of all the elements in the array must equal 16384 (or 100%), otherwise unexpected results might occur.

  • 3 (DV_MMCONTRIB_TYPE_AXIS_NORM1024) — Each element in the contribs array represents a contribution of the corresponding design axis in the final interpolated font instance. The value of each element must be in the 0 - 1024 range, where zero means "no contribution" (or 0% contribution) and 1024 means "full contribution" (or 100% contribution).

  • 4 (DV_MMCONTRIB_TYPE_AXIS_NORM16384) — Each element in the contribs array represents a contribution of the corresponding design axis in the final interpolated font instance. The value of each element must be in the 0 - 16384 range, where zero means "no contribution" (or 0% contribution) and 16384 means "full contribution" (or 100% contribution).

  • 5 (DV_MMCONTRIB_TYPE_AXIS_USER1024) — Each element in the contribs array represents a contribution of the corresponding design axis in the final interpolated font instance, expressed as a percentage of the axis' end-user scale that starts at the minimum axis value and ends at the maximum axis value. The minimum and maximum axis values can be obtained by calling the dtFontGetNumericValue function. The value of each element must be in the 0 - 1024 range, where zero means "minimum axis value" (or 0%) and 1024 means "maximum axis value" (or 100%). See Example 4 below for details.

  • 6 (DV_MMCONTRIB_TYPE_AXIS_USER16384) — Each element in the contribs array represents a contribution of the corresponding design axis in the final interpolated font instance, expressed as a percentage of the axis' end-user scale that starts at the minimum axis value and ends at the maximum axis value. The minimum and maximum axis values can be obtained by calling the dtFontGetNumericValue function. The value of each element must be in the 0 - 16384 range, where zero means "minimum axis value" (or 0%) and 16384 means "maximum axis value" (or 100%). See Example 4 below for details.

contribs_len

Number of elements in the contribs array when dtFontAddAsMMInstancePlus is used.

contribs

A Contribution Array.

If dtFontAddAsMMInstancePlus is used, the number of elements in this array is explicitly specified by the contribs_len parameter and their values should be interpreted according to the contribs_flag value described above.

If dtFontAddAsMMInstance is used, the number of elements in this array must be the same as the number of base designs in the multiple-master font referenced by font_index. This number can be obtained by calling the dtFontGetMMAxisInfo or dtFontGetDim function. In this case, each element in the contribs array represents a contribution of the corresponding base design in the final interpolated font instance. The value of each element must be in the 0 - 1024 range, where zero means "no contribution" (or 0% contribution) and 1024 means "full contribution" (or 100% contribution). Finally, the sum of all the elements in the array must equal 1024 (or 100%), otherwise unexpected results might occur.

Return Value

If successful, the return value is the index of the created font instance in the Font Catalog. This value uniquely identifies the font or font instance in the catalog and is referred to as font index. If not successful, the function returns -1.

Comments

The created font instance should be treated as any regular font. This means that an application can even use the dtGlyphGetOutline or dtCharGetOutline function to get the interpolated outline curve for an interpolated outline glyph or character.

Note 1

DV_MMCONTRIB_TYPE_DIM_NORM1024 and DV_MMCONTRIB_TYPE_DIM_NORM16384 are now obsolete and should not be used in modern programs. These flags were used long time ago in the age of Adobe's Multiple Master fonts which predate variable OpenType fonts.

Example 1

The following example illustrates a multiple-master font with 2 design axes (width and weight), 4 base designs and 12 interpolated (intermediate) designs (16 font instances in total). The value of the ContributionArray elements is shown below for each design (indicated as C[0], C[1], C[2] and C[3]). Please note that the sum of all contributions in each array is exactly 1024 (or 100%).

MM contributions

Example 2

The following program illustrates how to create intermediate font instances from a single multiple-master font file.

#include <stdio.h>
#include "dtype.h"

#define INTERPOLATIONS_X 3
#define INTERPOLATIONS_Y 5
#define INTERPOLATIONS_X_AND_Y (1 + (INTERPOLATIONS_X + 1) * (INTERPOLATIONS_Y + 1))

DT_SWORD MMFont[INTERPOLATIONS_X_AND_Y];

DT_SWORD InitMMInstances(DT_DTENGINE engine)
{
    /* Add a multiple-master font to catalog */ 
    DT_STREAM_FILE(sd, "system/fonts/pfb/HSansMM.pfb");
    MMFont[0] = dtFontAddViaStream(engine, DV_FONT_TYPE1_ADOBE, DV_NULL, 0, 0, 0, 1, &sd);

    if (MMFont[0] < 0)
    {
        /* Error opening font */ 
        printf("multiple-master font file \"HSansMM.pfb\" not found
        in D-Type's system/fonts/pfb sub-directory");
        return 0;
    }

    DT_SWORD font_axis_count = dtFontGetMMAxisInfo(engine, MMFont[0], DV_NULL, DV_NULL);

    if (font_axis_count < 0)
    {
        printf("Something is wrong with this font!\n");
        return 0;
    }
    else if (font_axis_count > 16)
    {
        printf("This is a complex multiple-master font with more than 16 axes! This font cannot be used with this program.\n");
        return 0;
    }
    else if (font_axis_count == 0)
    {
        printf("This is not a multiple-master, but a regular font! This font cannot be used with this program.\n");
        return 0;
    }
    else if (font_axis_count < 2)
    {
        printf("Although this is a multiple-master font, it cannot be used for this demo because it has less than 2 axes!\n");
        return 0;
    }

    DT_SWORD mm_contribs[2];
    DT_SLONG mm_contribs[2];
    DT_SLONG i = 1, i_x, i_y;
    DT_SWORD result = 1;

    // Create interpolated font instances

    for (i_y = 0; i_y <= DV_MM_INTERPOLATIONS_Y; i_y++)
    for (i_x = 0; i_x <= DV_MM_INTERPOLATIONS_X; i_x++)
    {
        mm_contribs[0] = 1024 * i_x / DV_MM_INTERPOLATIONS_X;
        mm_contribs[1] = 1024 * i_y / DV_MM_INTERPOLATIONS_Y;

        // Now we can make an MM instance
        MMFont[i] = dtFontAddAsMMInstancePlus(engine, MMFont[0], DV_MMCONTRIB_TYPE_AXIS_NORM1024, 2, mm_contribs);
        if (MMFont[i] < 0) result = 0; /* Error creating font instance */

        i++;
    }

    return result;
}

void DrawMMInstances(DT_DTENGINE engine)
{
    DT_SLONG i = 1, i_x, i_y;
    DT_STYLE_ATTRIBS style = {{0, 0}, {20, 115, 0, 0}, 0, DV_NULL};
    DT_TYPE_EFFECTS type = {0, 0, 0, {{50, 50, 0, 0, 0}}, {0, 0, 0, 0, 0, DV_SCALE_100}};

    dtOutputSetStyleAttribs(engine, &style, 0);

    /* Draw a sample of all the previously created font instances */ 

    for (i_y = 0; i_y <= INTERPOLATIONS_Y; i_y++)
    for (i_x = 0; i_x <= INTERPOLATIONS_X; i_x++)
    {
        type.font = MMFont[i];
        dtTypesetterSetTypeEffects(engine, &type, 0);

        dtxTextDoOutput_ANSI(engine, 20 + 340 * wgh, 20 + 80 * wdt,
        80, DV_TEXTMODE_KERN_FRAC, DV_NULL, "D-Type");
        i++;
    }
}

void main(void)
{
    DT_DTENGINE engine
    DT_MDC dc_mem;
    DT_SWORD wcl = 640, hcl = 400;

    /* Initialize Standard Engine */ 
    DT_STREAM_FILE(sd, "dtype.inf");
    if (dtEngineIniViaStream(&engine, &sd, DV_NULL) <= 0) return;

    /* Generate MM instances */ 
    InitMMInstances(engine);

    /* Create a 640x480-pixel memory surface */ 
    dc_mem.w = wcl;
    dc_mem.h = hcl,
    dc_mem.l = (DT_SLONG)3 * wcl * hcl;
    if ((dc_mem.m = (DT_UBYTE*)malloc(dc_mem.l)) == DV_NULL) return;
    memset(dc_mem.m, 255, dc_mem.l);

    /* Redirect all D-Type output to that surface */ 
    dtOutputSetAsMDC(engine, DV_FORMAT_24, 0, &dc_mem, 0, 0, wcl, hcl);

    /* Draw a sample of MM instances */ 
    DrawMMInstances(engine);

    /* Copy surface to screen or save as image */ 

    ...

    /* Release the surface */ 
    free(dc_mem.m);

    /* And destroy Standard Engine instance */ 
    dtEngineExt(engine);
}

Output:

MM instances

Example 3

The following program illustrates another way to create intermediate font instances from a single multiple-master font file.

#include <stdio.h>
#include "dtype.h"

#define INTERPOLATIONS_X 3
#define INTERPOLATIONS_Y 5
#define MAXBASEDESIGNS 16

DT_SWORD MMFont[1 + (INTERPOLATIONS_X + 1) * (INTERPOLATIONS_Y + 1)];

DT_SWORD InitMMInstances(DT_DTENGINE engine)
{
    DT_SWORD result = 1;
    DT_SWORD font_dim;
    DT_SLONG i, wdt, wgh;
    DT_SWORD mm_contribs[MAXBASEDESIGNS];
    DT_FLOAT k_wgh, k_wdt;

    /* Add a multiple-master font to catalog */ 
    DT_STREAM_FILE(sd, "system/fonts/pfb/HSansMM.pfb");
    MMFont[0] = dtFontAddViaStream(engine, DV_FONT_TYPE1_ADOBE, DV_NULL, 0, 0, 0, 1, &sd);

    if (MMFont[0] < 0)
    {
        /* Error opening font */ 
        printf("multiple-master font file \"HSansMM.pfb\" not found
        in D-Type's system/fonts/pfb sub-directory");
        return 0;
    }

    font_dim = dtFontGetDim(engine, MMFont[0]);

    if (font_dim == 1)
    {
        printf("This is not a multiple-master, but a regular font! This
        font cannot be used in demonstration of multiple-master features.");
        return 0;
    }
    else if (font_dim < 4)
    {
        printf("Although this is a multiple-master font, it cannot be
        used with this program because it has less than 4 base designs!");
        return 0;
    }
    else if (font_dim > MAXBASEDESIGNS)
    {
        printf("This is an incredibly complex multiple-master font!");
        return 0;
    }

    /* Set all base contributions to 0 */ 
    for (i = 0; i < font_dim; i++) mm_contribs[i] = 0;

    /* Create Interpolated Font Instances */ 
    for (wdt = 0, i = 1; wdt <= INTERPOLATIONS_Y; wdt++)
    {
        /* k_wdt is a "Width" factor, and is always between 0 and 1 */ 
        k_wdt = (wdt / (DT_FLOAT)INTERPOLATIONS_Y);

        for (wgh = 0; wgh <= INTERPOLATIONS_X; wgh++)
        {
            /* k_wgh is a "Weight" factor, and is always between 0 and 1 */ 
            k_wgh = (wgh / (DT_FLOAT)INTERPOLATIONS_X);

            /* Calculate contribution of each base design */ 

            /* If the font has more than 4 base designs, we calculate only the */ 
            /* first four contributions, and ignore all remaining contributions */ 

            /* Contribution of base design 0 (Weight-0, Width-0) */ 
            mm_contribs[0] = (DT_SWORD)((1 - k_wdt) * (1 - k_wgh) * 1024);
            /* Contribution of base design 1 (Weight-1, Width-0) */ 
            mm_contribs[1] = (DT_SWORD)((1 - k_wdt) * k_wgh * 1024);
            /* Contribution of base design 2 (Weight-0, Width-1) */ 
            mm_contribs[2] = (DT_SWORD)(k_wdt * (1 - k_wgh) * 1024);
            /* Contribution of base design 3 (Weight-1, Width-1) */ 
            mm_contribs[3] = (DT_SWORD)(k_wgh * k_wdt * 1024);

            /* NOTE: The sum of all the contributions MUST ALWAYS EQUAL 1024 */ 

            /* Now we can make a MM instance */ 
            MMFont[i] = dtFontAddAsMMInstance(engine, MMFont[0], mm_contribs);

            if (MMFont[i] < 0) result = 0; /* Error creating font instance */ 

            i++;
        }
    }

    return result;
}

void DrawMMInstances(DT_DTENGINE engine)
{
    DT_SLONG i, wdt, wgh;
    DT_STYLE_ATTRIBS style = {{0, 0}, {20, 115, 0, 0}, 0, DV_NULL};
    DT_TYPE_ATTRIBS type = {0, 0, 0, 0, 0, {{50, 50, 0, 0, 0}}};

    dtOutputSetStyleAttribs(engine, &style, 0);

    /* Draw a sample of all the previously created font instances */ 

    for (wdt = 0, i = 1; wdt <= INTERPOLATIONS_Y; wdt++)
    {
        for (wgh = 0; wgh <= INTERPOLATIONS_X; wgh++)
        {
            type.font = MMFont[i];
            dtTypesetterSetTypeAttribs(engine, &type, 0);

            dtxTextDoOutput_ANSI(engine, 20 + 340 * wgh, 20 + 80 * wdt,
            80, DV_TEXTMODE_KERN_FRAC, DV_NULL, "D-Type");
            i++;
        }
    }
}

void main(void)
{
    DT_DTENGINE engine
    DT_MDC dc_mem;
    DT_SWORD wcl = 640, hcl = 400;

    /* Initialize Standard Engine */ 
    DT_STREAM_FILE(sd, "dtype.inf");
    if (dtEngineIniViaStream(&engine, &sd, DV_NULL) <= 0) return;

    /* Generate MM instances */ 
    InitMMInstances(engine);

    /* Create a 640x480-pixel memory surface */ 
    dc_mem.w = wcl;
    dc_mem.h = hcl,
    dc_mem.l = (DT_SLONG)3 * wcl * hcl;
    if ((dc_mem.m = (DT_UBYTE*)malloc(dc_mem.l)) == DV_NULL) return;
    memset(dc_mem.m, 255, dc_mem.l);

    /* Redirect all D-Type output to that surface */ 
    dtOutputSetAsMDC(engine, DV_FORMAT_24, 0, &dc_mem, 0, 0, wcl, hcl);

    /* Draw a sample of MM instances */ 
    DrawMMInstances(engine);

    /* Copy surface to screen or save as image */ 

    ...

    /* Release the surface */ 
    free(dc_mem.m);

    /* And destroy Standard Engine instance */ 
    dtEngineExt(engine);
}

Output:

MM instances

Example 4

Assume we have a variable OpenType font called Bahnschrift.ttf. This font has two design axes, Weight and Width. The Weight scale is in the 300 – 700 range, while the Width scale is in the 75 – 100 range. We want to calculate the elements of the contribs array corresponding to the final interpolated font instance "SemiBold SemiCondensed" in which Weight = 600 and Width = 87.5. We want to use either contribs_flag = DV_MMCONTRIB_TYPE_AXIS_USER1024 or contribs_flag = DV_MMCONTRIB_TYPE_AXIS_USER16384 when calling dtFontAddAsMMInstance.

Weight
  End-user scale (based on the font data): min_value = 300 and max_value = 700
  scale_range = max_value - min_value = 700 - 300 = 400
  desired_weight = 600
  Percentage of the axis' end-user scale = (desired_weight - min_value) / scale_range = (600 - 300) / 400 = 0.75 or 75%

Width
  End-user scale (based on the font data): min_value = 75 and max_value = 100
  scale_range = max_value - min_value = 100 - 75 = 25
  desired_width = 87.5
  Percentage of the axis' end-user scale = (desired_width - min_value) / scale_range = (87.5 - 75) / 25 = 0.5 or 50%

Thus, when contribs_flag = DV_MMCONTRIB_TYPE_AXIS_USER1024, the elements of the contribs array should be set up as follows:

contribs[0] = 768 (which is 75% since 0.75 * 1024 = 768)
contribs[1] = 512 (which is 50% since 0.50 * 1024 = 512)

Similarly, when contribs_flag = DV_MMCONTRIB_TYPE_AXIS_USER16384, the elements of the contribs array should be set up as follows:

contribs[0] = 12288 (which is 75% since 0.75 * 16384 = 12288)
contribs[1] = 8192 (which is 50% since 0.50 * 16384 = 8192)

 

Index