already_AddRefed<gfxOS2Font>
gfxOS2Platform::FindFontForChar(PRUint32 aCh, gfxOS2Font *aFont)
{
#ifdef DEBUG_thebes
    printf("gfxOS2Platform::FindFontForChar(%d, ...)\n", aCh);
#endif

    // is codepoint with no matching font? return null immediately
    if (mCodepointsWithNoFonts.test(aCh)) {
        return nsnull;
    }

    // the following is not very clever but it's a quick fix to search all fonts
    // (one should instead cache the charmaps as done on Mac and Win)

    // just continue to append all fonts known to the system
    nsTArray<nsString> fontList;
    nsCAutoString generic;
    nsresult rv = GetFontList(aFont->GetStyle()->langGroup, generic, fontList);
    if (NS_SUCCEEDED(rv)) {
        // start at 3 to skip over the generic entries
        for (PRUint32 i = 3; i < fontList.Length(); i++) {
#ifdef DEBUG_thebes
            printf("searching in entry i=%d (%s)\n",
                   i, NS_LossyConvertUTF16toASCII(fontList[i]).get());
#endif
            nsRefPtr<gfxOS2Font> font =
                gfxOS2Font::GetOrMakeFont(fontList[i], aFont->GetStyle());
            if (!font)
                continue;
            FT_Face face = cairo_ft_scaled_font_lock_face(font->CairoScaledFont());
            if (!face || !face->charmap) {
                if (face)
                    cairo_ft_scaled_font_unlock_face(font->CairoScaledFont());
                continue;
            }

            FT_UInt gid = FT_Get_Char_Index(face, aCh); // find the glyph id
            if (gid != 0) {
                // this is the font
                cairo_ft_scaled_font_unlock_face(font->CairoScaledFont());
                return font.forget();
            }
        }
    }

    // no match found, so add to the set of non-matching codepoints
    mCodepointsWithNoFonts.set(aCh);
    return nsnull;
}
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const Font* fontData)
{
    cairo_scaled_font_t* scaledFont = fontData->platformData().scaledFont();
    ASSERT(scaledFont);

    FT_Face face = cairo_ft_scaled_font_lock_face(scaledFont);
    if (!face)
        return false;

    bool haveGlyphs = false;
    UTF16UChar32Iterator iterator(buffer, bufferLength);
    for (unsigned i = 0; i < length; i++) {
        UChar32 character = iterator.next();
        if (character == iterator.end())
            break;

        Glyph glyph = FcFreeTypeCharIndex(face, character);
        if (!glyph)
            setGlyphDataForIndex(offset + i, 0, 0);
        else {
            setGlyphDataForIndex(offset + i, glyph, fontData);
            haveGlyphs = true;
        }
    }

    cairo_ft_scaled_font_unlock_face(scaledFont);
    return haveGlyphs;
}
Exemple #3
0
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    // The bufferLength will be greater than the glyph page size if the buffer has Unicode supplementary characters.
    // We won't support this for now.
    if (bufferLength > GlyphPage::size)
        return false;

    cairo_scaled_font_t* scaledFont = fontData->platformData().scaledFont();
    if (!scaledFont)
        return false;

    FT_Face face = cairo_ft_scaled_font_lock_face(scaledFont);
    if (!face)
        return false;

    bool haveGlyphs = false;
    for (unsigned i = 0; i < length; i++) {
        Glyph glyph = FcFreeTypeCharIndex(face, buffer[i]);
        if (!glyph)
            setGlyphDataForIndex(offset + i, 0, 0);
        else {
            setGlyphDataForIndex(offset + i, glyph, fontData);
            haveGlyphs = true;
        }
    }

    cairo_ft_scaled_font_unlock_face(scaledFont);
    return haveGlyphs;
}
Exemple #4
0
bool SimpleFontData::canRenderCombiningCharacterSequence(const UChar* characters, size_t length) const
{
    if (!m_combiningCharacterSequenceSupport)
        m_combiningCharacterSequenceSupport = adoptPtr(new HashMap<String, bool>);

    WTF::HashMap<String, bool>::AddResult addResult = m_combiningCharacterSequenceSupport->add(String(characters, length), false);
    if (!addResult.isNewEntry)
        return addResult.iterator->value;

    UErrorCode error = U_ZERO_ERROR;
    Vector<UChar, 4> normalizedCharacters(length);
    int32_t normalizedLength = unorm_normalize(characters, length, UNORM_NFC, UNORM_UNICODE_3_2, &normalizedCharacters[0], length, &error);
    // Can't render if we have an error or no composition occurred.
    if (U_FAILURE(error) || (static_cast<size_t>(normalizedLength) == length))
        return false;

    FT_Face face = cairo_ft_scaled_font_lock_face(m_platformData.scaledFont());
    if (!face)
        return false;

    if (FcFreeTypeCharIndex(face, normalizedCharacters[0]))
        addResult.iterator->value = true;

    cairo_ft_scaled_font_unlock_face(m_platformData.scaledFont());
    return addResult.iterator->value;
}
PassRefPtr<SharedBuffer> FontPlatformData::openTypeTable(uint32_t table) const
{
    FT_Face freeTypeFace = cairo_ft_scaled_font_lock_face(m_scaledFont);
    if (!freeTypeFace)
        return 0;

    FT_ULong tableSize = 0;
    // Tag bytes need to be reversed because OT_MAKE_TAG uses big-endian order.
    uint32_t tag = FT_MAKE_TAG((table & 0xff), (table & 0xff00) >> 8, (table & 0xff0000) >> 16, table >> 24);
    if (FT_Load_Sfnt_Table(freeTypeFace, tag, 0, 0, &tableSize))
        return 0;

    RefPtr<SharedBuffer> buffer = SharedBuffer::create(tableSize);
    FT_ULong expectedTableSize = tableSize;
    if (buffer->size() != tableSize)
        return 0;

    FT_Error error = FT_Load_Sfnt_Table(freeTypeFace, tag, 0, reinterpret_cast<FT_Byte*>(const_cast<char*>(buffer->data())), &tableSize);
    if (error || tableSize != expectedTableSize)
        return 0;

    cairo_ft_scaled_font_unlock_face(m_scaledFont);

    return buffer.release();
}
bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
{
    FT_Face face = cairo_ft_scaled_font_lock_face(m_platformData.m_scaledFont);

    if (!face)
        return false;

    for (int i = 0; i < length; i++) {
        if (FcFreeTypeCharIndex(face, characters[i]) == 0) {
            cairo_ft_scaled_font_unlock_face(m_platformData.m_scaledFont);
            return false;
        }
    }

    cairo_ft_scaled_font_unlock_face(m_platformData.m_scaledFont);

    return true;
}
static cairo_status_t
glyph_array_add_text(glyph_array_t *glyphs, cairo_t *cr, const char *s, double spacing)
{
    cairo_scaled_font_t *scaled_font;
    cairo_status_t status;
    FT_Face face;
    unsigned long charcode;
    unsigned int index;
    cairo_text_extents_t extents;
    const char *p;
    FT_Vector kerning;
    double kern_x;
    int first = TRUE;

    scaled_font = cairo_get_scaled_font (cr);
    status = cairo_scaled_font_status (scaled_font);
    if (status)
	return status;

    face = cairo_ft_scaled_font_lock_face (scaled_font);
    if (face == NULL)
	return CAIRO_STATUS_FONT_TYPE_MISMATCH;

    p = s;
    while (*p)
    {
        charcode = *p;
        index = FT_Get_Char_Index (face, charcode);
        glyphs->glyph_list[glyphs->num_glyphs].index = index;
        if (first) {
            first = FALSE;
            glyphs->glyph_list[glyphs->num_glyphs].x = glyphs->x;
            glyphs->glyph_list[glyphs->num_glyphs].y = glyphs->y;
        } else {
            cairo_glyph_extents (cr, &glyphs->glyph_list[glyphs->num_glyphs - 1], 1, &extents);
            FT_Get_Kerning (face,
                            glyphs->glyph_list[glyphs->num_glyphs - 1].index,
                            glyphs->glyph_list[glyphs->num_glyphs].index,
                            FT_KERNING_UNSCALED,
                            &kerning);
            kern_x = DOUBLE_FROM_26_6(kerning.x);
            glyphs->glyph_list[glyphs->num_glyphs].x =
		glyphs->glyph_list[glyphs->num_glyphs - 1].x + extents.x_advance + kern_x + spacing;
            glyphs->glyph_list[glyphs->num_glyphs].y =
		glyphs->glyph_list[glyphs->num_glyphs - 1].y + extents.y_advance;
	}

	cairo_glyph_extents (cr, &glyphs->glyph_list[glyphs->num_glyphs], 1, &extents);
	glyphs->x = glyphs->glyph_list[glyphs->num_glyphs].x + extents.x_advance + spacing;
	glyphs->y = glyphs->glyph_list[glyphs->num_glyphs].y + extents.y_advance;
	p++;
        glyphs->num_glyphs++;
    }

    cairo_ft_scaled_font_unlock_face (scaled_font);
    return CAIRO_STATUS_SUCCESS;
}
bool FontPlatformData::hasCompatibleCharmap()
{
    ASSERT(m_scaledFont);
    FT_Face freeTypeFace = cairo_ft_scaled_font_lock_face(m_scaledFont);
    bool hasCompatibleCharmap = !(FT_Select_Charmap(freeTypeFace, ft_encoding_unicode)
                                && FT_Select_Charmap(freeTypeFace, ft_encoding_symbol)
                                && FT_Select_Charmap(freeTypeFace, ft_encoding_apple_roman));
    cairo_ft_scaled_font_unlock_face(m_scaledFont);
    return hasCompatibleCharmap;
}
Exemple #9
0
static void
pango_cairo_fc_font_unlock_face (PangoFcFont *font)
{
  PangoCairoFcFont *cffont = (PangoCairoFcFont *) (font);
  cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (&cffont->cf_priv);

  if (G_UNLIKELY (!scaled_font))
    return;

  cairo_ft_scaled_font_unlock_face (scaled_font);
}
Exemple #10
0
bool SimpleFontData::containsCharacters(const UChar* characters, int bufferLength) const
{
    ASSERT(m_platformData.scaledFont());
    FT_Face face = cairo_ft_scaled_font_lock_face(m_platformData.scaledFont());
    if (!face)
        return false;

    UTF16UChar32Iterator iterator(characters, bufferLength);
    UChar32 character = iterator.next();
    while (character != iterator.end()) {
        if (!FcFreeTypeCharIndex(face, character)) {
            cairo_ft_scaled_font_unlock_face(m_platformData.scaledFont());
            return false;
        }
        character = iterator.next();
    }

    cairo_ft_scaled_font_unlock_face(m_platformData.scaledFont());
    return true;
}
Exemple #11
0
bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
{
    // If this is a no-op font (zero size), then it should always contain the characters,
    // since we never read from or render from this font.
    if (!m_platformData.scaledFont())
        return true;

    FT_Face face = cairo_ft_scaled_font_lock_face(m_platformData.scaledFont());
    if (!face)
        return false;

    for (int i = 0; i < length; i++) {
        if (FcFreeTypeCharIndex(face, characters[i]) == 0) {
            cairo_ft_scaled_font_unlock_face(m_platformData.scaledFont());
            return false;
        }
    }

    cairo_ft_scaled_font_unlock_face(m_platformData.scaledFont());
    return true;
}
Exemple #12
0
// gfxOS2Font::GetMetrics()
// return the metrics of the current font using the gfxFont metrics structure.
// If the metrics are not available yet, compute them using the FreeType
// function on the font. (This is partly based on the respective function from
// gfxPangoFonts)
const gfxFont::Metrics& gfxOS2Font::GetMetrics()
{
#ifdef DEBUG_thebes_1
    printf("gfxOS2Font[%#x]::GetMetrics()\n", (unsigned)this);
#endif
    if (mMetrics) {
        return *mMetrics;
    }

    // whatever happens below, we can always create the metrics
    mMetrics = new gfxFont::Metrics;
    mSpaceGlyph = 0;

    // round size to integer pixels, this is to get full pixels for layout
    // together with internal/external leading (see below)
    mMetrics->emHeight = NS_floor(GetStyle()->size + 0.5);

    FT_Face face = cairo_ft_scaled_font_lock_face(CairoScaledFont());
    if (!face) {
        // Abort here already, otherwise we crash in the following
        // this can happen if the font-size requested is zero.
        FillMetricsDefaults(mMetrics);
        return *mMetrics;
    }
    if (!face->charmap) {
        // Also abort, if the charmap isn't loaded; then the char
        // lookups won't work. This happens for fonts without Unicode
        // charmap.
        cairo_ft_scaled_font_unlock_face(CairoScaledFont());
        FillMetricsDefaults(mMetrics);
        return *mMetrics;
    }

    // compute font scaling factors
    gfxFloat emUnit = 1.0 * face->units_per_EM;
    gfxFloat xScale = face->size->metrics.x_ppem / emUnit;
    gfxFloat yScale = face->size->metrics.y_ppem / emUnit;

    FT_UInt gid; // glyph ID

    // properties of space
    gid = FT_Get_Char_Index(face, ' ');
    if (gid) {
        // Load glyph into glyph slot. Use load_default here to get results in
        // 26.6 fractional pixel format which is what is used for all other
        // characters in gfxOS2FontGroup::CreateGlyphRunsFT.
        FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT);
        // glyph width doesn't work for spaces, use advance instead
        mMetrics->spaceWidth = face->glyph->advance.x >> 6;
        // save the space glyph
        mSpaceGlyph = gid;
    } else {
Exemple #13
0
FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool italic)
    : m_fallbacks(0)
    , m_size(size)
    , m_syntheticBold(bold)
    , m_syntheticOblique(italic)
{
    initializeWithFontFace(fontFace);

    FT_Face fontConfigFace = cairo_ft_scaled_font_lock_face(m_scaledFont.get());
    if (fontConfigFace) {
        m_fixedWidth = fontConfigFace->face_flags & FT_FACE_FLAG_FIXED_WIDTH;
        cairo_ft_scaled_font_unlock_face(m_scaledFont.get());
    }
}
Exemple #14
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    cairo_font_options_t *font_options;
    cairo_scaled_font_t *scaled_font;
    FT_Face face;
    FT_ULong charcode;
    FT_UInt idx;
    int i = 0;
    cairo_glyph_t glyphs[NUM_GLYPHS];

    /* paint white so we don't need separate ref images for
     * RGB24 and ARGB32 */
    cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
    cairo_paint (cr);

    cairo_select_font_face (cr, "Bitstream Vera Sans",
			    CAIRO_FONT_SLANT_NORMAL,
			    CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size (cr, TEXT_SIZE);

    font_options = cairo_font_options_create ();
    cairo_get_font_options (cr, font_options);
    cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF);
    cairo_set_font_options (cr, font_options);
    cairo_font_options_destroy (font_options);

    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);

    scaled_font = cairo_get_scaled_font (cr);
    face = cairo_ft_scaled_font_lock_face (scaled_font);
    {
	charcode = FT_Get_First_Char(face, &idx);
	while (idx && (i < NUM_GLYPHS)) {
	    glyphs[i] = (cairo_glyph_t) {idx, PAD + GRID_SIZE * (i/GRID_ROWS), PAD + TEXT_SIZE + GRID_SIZE * (i%GRID_ROWS)};
	    i++;
	    charcode = FT_Get_Next_Char(face, charcode, &idx);
	}
    }
    cairo_ft_scaled_font_unlock_face (scaled_font);

    cairo_show_glyphs(cr, glyphs, i);

    return CAIRO_TEST_SUCCESS;
}
static cairo_int_status_t
_cairo_qt_surface_show_glyphs (void *abstract_surface,
			       cairo_operator_t op,
			       const cairo_pattern_t *source,
			       cairo_glyph_t *glyphs,
			       int num_glyphs,
			       cairo_scaled_font_t *scaled_font,
			       const cairo_clip_t *clip)
{
#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)) || defined(QT_GLYPHS_API_BACKPORT)
    cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;

    // pick out the colour to use from the cairo source
    cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) source;
    cairo_scaled_glyph_t* glyph;
    // documentation says you have to freeze the cache, but I don't believe it
    _cairo_scaled_font_freeze_cache(scaled_font);

    QColor tempColour(solid->color.red * 255, solid->color.green * 255, solid->color.blue * 255);
    QVarLengthArray<QPointF> positions(num_glyphs);
    QVarLengthArray<unsigned int> glyphss(num_glyphs);
    FT_Face face = cairo_ft_scaled_font_lock_face (scaled_font);
    const FT_Size_Metrics& ftMetrics = face->size->metrics;
    QFont font(face->family_name);
    font.setStyleStrategy(QFont::NoFontMerging);
    font.setBold(face->style_flags & FT_STYLE_FLAG_BOLD);
    font.setItalic(face->style_flags & FT_STYLE_FLAG_ITALIC);
    font.setKerning(face->face_flags & FT_FACE_FLAG_KERNING);
    font.setPixelSize(ftMetrics.y_ppem);
    cairo_ft_scaled_font_unlock_face(scaled_font);
    qs->p->setFont(font);
    qs->p->setPen(tempColour);
    for (int currentGlyph = 0; currentGlyph < num_glyphs; currentGlyph++) {
        positions[currentGlyph].setX(glyphs[currentGlyph].x);
        positions[currentGlyph].setY(glyphs[currentGlyph].y);
        glyphss[currentGlyph] = glyphs[currentGlyph].index;
    }
    qt_draw_glyphs(qs->p, glyphss.data(), positions.data(), num_glyphs);
    _cairo_scaled_font_thaw_cache(scaled_font);
    return CAIRO_INT_STATUS_SUCCESS;
#else
    return CAIRO_INT_STATUS_UNSUPPORTED;
#endif
}
void SimpleFontData::platformInit()
{
    if (!m_platformData.m_size)
        return;

    ASSERT(m_platformData.scaledFont());
    cairo_font_extents_t fontExtents;
    cairo_scaled_font_extents(m_platformData.scaledFont(), &fontExtents);

    float ascent = narrowPrecisionToFloat(fontExtents.ascent);
    float descent = narrowPrecisionToFloat(fontExtents.descent);
    float lineGap = narrowPrecisionToFloat(fontExtents.height - fontExtents.ascent - fontExtents.descent);

    m_fontMetrics.setAscent(ascent);
    m_fontMetrics.setDescent(descent);

#if PLATFORM(EFL)
    m_fontMetrics.setLineSpacing(ascent + descent + lineGap);
#else
    // Match CoreGraphics metrics.
    m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));
#endif
    m_fontMetrics.setLineGap(lineGap);

    cairo_text_extents_t textExtents;
    cairo_scaled_font_text_extents(m_platformData.scaledFont(), "x", &textExtents);
    m_fontMetrics.setXHeight(narrowPrecisionToFloat((platformData().orientation() == Horizontal) ? textExtents.height : textExtents.width));

    cairo_scaled_font_text_extents(m_platformData.scaledFont(), " ", &textExtents);
    m_spaceWidth = narrowPrecisionToFloat((platformData().orientation() == Horizontal) ? textExtents.x_advance : -textExtents.y_advance);

    if ((platformData().orientation() == Vertical) && !isTextOrientationFallback()) {
        FT_Face freeTypeFace = cairo_ft_scaled_font_lock_face(m_platformData.scaledFont());
        m_fontMetrics.setUnitsPerEm(freeTypeFace->units_per_EM);
        cairo_ft_scaled_font_unlock_face(m_platformData.scaledFont());
    }

    m_syntheticBoldOffset = m_platformData.syntheticBold() ? 1.0f : 0.f;
}
 ~CairoLockedFTFace()
 {
     cairo_ft_scaled_font_unlock_face(fScaledFont);
 }
Exemple #18
0
static void
text_to_glyphs (cairo_t *cr,
                const gchar *text,
                cairo_glyph_t **glyphs,
                int *num_glyphs)
{
  PangoAttribute *fallback_attr;
  PangoAttrList *attr_list;
  PangoContext *context;
  PangoDirection base_dir;
  GList *items;
  GList *visual_items;
  FT_Face ft_face;
  hb_font_t *hb_font;
  gdouble x = 0, y = 0;
  gint i;
  gdouble x_scale, y_scale;

  *num_glyphs = 0;
  *glyphs = NULL;

  base_dir = pango_find_base_dir (text, -1);

  cairo_scaled_font_t *cr_font = cairo_get_scaled_font (cr);
  ft_face = cairo_ft_scaled_font_lock_face (cr_font);
  hb_font = hb_ft_font_create (ft_face, NULL);

  cairo_surface_t *target = cairo_get_target (cr);
  cairo_surface_get_device_scale (target, &x_scale, &y_scale);

  /* We abuse pango itemazation to split text into script and direction
   * runs, since we use our fonts directly no through pango, we don't
   * bother changing the default font, but we disable font fallback as
   * pango will split runs at font change */
  context = pango_cairo_create_context (cr);
  attr_list = pango_attr_list_new ();
  fallback_attr = pango_attr_fallback_new (FALSE);
  pango_attr_list_insert (attr_list, fallback_attr);
  items = pango_itemize_with_base_dir (context, base_dir,
                                       text, 0, strlen (text),
                                       attr_list, NULL);
  g_object_unref (context);
  pango_attr_list_unref (attr_list);

  /* reorder the items in the visual order */
  visual_items = pango_reorder_items (items);

  while (visual_items) {
    PangoItem *item;
    PangoAnalysis analysis;
    hb_buffer_t *hb_buffer;
    hb_glyph_info_t *hb_glyphs;
    hb_glyph_position_t *hb_positions;
    gint n;

    item = visual_items->data;
    analysis = item->analysis;

    hb_buffer = hb_buffer_create ();
    hb_buffer_add_utf8 (hb_buffer, text, -1, item->offset, item->length);
    hb_buffer_set_script (hb_buffer, hb_glib_script_to_script (analysis.script));
    hb_buffer_set_language (hb_buffer, hb_language_from_string (pango_language_to_string (analysis.language), -1));
    hb_buffer_set_direction (hb_buffer, analysis.level % 2 ? HB_DIRECTION_RTL : HB_DIRECTION_LTR);

    hb_shape (hb_font, hb_buffer, NULL, 0);

    n = hb_buffer_get_length (hb_buffer);
    hb_glyphs = hb_buffer_get_glyph_infos (hb_buffer, NULL);
    hb_positions = hb_buffer_get_glyph_positions (hb_buffer, NULL);

    *glyphs = g_renew (cairo_glyph_t, *glyphs, *num_glyphs + n);

    for (i = 0; i < n; i++) {
      (*glyphs)[*num_glyphs + i].index = hb_glyphs[i].codepoint;
      (*glyphs)[*num_glyphs + i].x = x + (hb_positions[i].x_offset / (64. * x_scale));
      (*glyphs)[*num_glyphs + i].y = y - (hb_positions[i].y_offset / (64. * y_scale));
      x += (hb_positions[i].x_advance / (64. * x_scale));
      y -= (hb_positions[i].y_advance / (64. * y_scale));
    }

    *num_glyphs += n;

    hb_buffer_destroy (hb_buffer);

    visual_items = visual_items->next;
  }

  g_list_free_full (visual_items, (GDestroyNotify) pango_item_free);
  g_list_free_full (items, (GDestroyNotify) pango_item_free);

  hb_font_destroy (hb_font);
  cairo_ft_scaled_font_unlock_face (cr_font);
}