void Font::platformInit()
{
    if (!m_platformData.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 capHeight = narrowPrecisionToFloat(fontExtents.height);
    float lineGap = narrowPrecisionToFloat(fontExtents.height - fontExtents.ascent - fontExtents.descent);

    {
        CairoFtFaceLocker cairoFtFaceLocker(m_platformData.scaledFont());

        // If the USE_TYPO_METRICS flag is set in the OS/2 table then we use typo metrics instead.
        FT_Face freeTypeFace = cairoFtFaceLocker.ftFace();
        TT_OS2* OS2Table = freeTypeFace ? static_cast<TT_OS2*>(FT_Get_Sfnt_Table(freeTypeFace, ft_sfnt_os2)) : nullptr;
        if (OS2Table) {
            const FT_Short kUseTypoMetricsMask = 1 << 7;
            if (OS2Table->fsSelection & kUseTypoMetricsMask) {
                // FT_Size_Metrics::y_scale is in 16.16 fixed point format.
                // Its (fractional) value is a factor that converts vertical metrics from design units to units of 1/64 pixels.
                double yscale = (freeTypeFace->size->metrics.y_scale / 65536.0) / 64.0;
                ascent = narrowPrecisionToFloat(yscale * OS2Table->sTypoAscender);
                descent = -narrowPrecisionToFloat(yscale * OS2Table->sTypoDescender);
                lineGap = narrowPrecisionToFloat(yscale * OS2Table->sTypoLineGap);
            }
        }
    }

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

#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()) {
        CairoFtFaceLocker cairoFtFaceLocker(m_platformData.scaledFont());
        FT_Face freeTypeFace = cairoFtFaceLocker.ftFace();
        m_fontMetrics.setUnitsPerEm(freeTypeFace->units_per_EM);
    }

    m_syntheticBoldOffset = m_platformData.syntheticBold() ? 1.0f : 0.f;
}
CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typesettingFeatures, FontOrientation orientation) const
{
    unsigned key = typesettingFeatures + 1;
    HashMap<unsigned, RetainPtr<CFDictionaryRef>>::AddResult addResult = m_CFStringAttributes.add(key, RetainPtr<CFDictionaryRef>());
    RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.iterator->value;
    if (!addResult.isNewEntry)
        return attributesDictionary.get();

    attributesDictionary = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 4, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
    CFMutableDictionaryRef mutableAttributes = (CFMutableDictionaryRef)attributesDictionary.get();

    CFDictionarySetValue(mutableAttributes, kCTFontAttributeName, platformData().ctFont());

    if (!(typesettingFeatures & Kerning)) {
        const float zero = 0;
        static CFNumberRef zeroKerningValue = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &zero);
        CFDictionarySetValue(mutableAttributes, kCTKernAttributeName, zeroKerningValue);
    }

    bool allowLigatures = (orientation == Horizontal && platformData().allowsLigatures()) || (typesettingFeatures & Ligatures);
    if (!allowLigatures) {
        const int zero = 0;
        static CFNumberRef essentialLigaturesValue = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &zero);
        CFDictionarySetValue(mutableAttributes, kCTLigatureAttributeName, essentialLigaturesValue);
    }

    if (orientation == Vertical)
        CFDictionarySetValue(mutableAttributes, kCTVerticalFormsAttributeName, kCFBooleanTrue);

    return attributesDictionary.get();
}
Пример #3
0
js::detail::MutexImpl::~MutexImpl()
{
  if (!platformData_)
    return;

  TRY_CALL_PTHREADS(pthread_mutex_destroy(&platformData()->ptMutex),
                    "js::detail::MutexImpl::~MutexImpl: pthread_mutex_destroy failed");

  js_delete(platformData());
}
Пример #4
0
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
    if (!glyph || !platformData().size())
        return 0;

    QVector<quint32> glyphIndexes;
    glyphIndexes.append(glyph);
    QVector<QPointF> advances = platformData().rawFont().advancesForGlyphIndexes(glyphIndexes);
    ASSERT(!advances.isEmpty());
    return advances.at(0).x();
}
Пример #5
0
bool SimpleFontData::fillGlyphPage(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength) const
{
    if (U16_IS_LEAD(buffer[bufferLength-1])) {
        DLOG(ERROR) << "Last UTF-16 code unit is high-surrogate.";
        return false;
    }

    SkTypeface* typeface = platformData().typeface();
    if (!typeface) {
        DLOG(ERROR) << "fillGlyphPage called on an empty Skia typeface.";
        return false;
    }

    SkAutoSTMalloc<GlyphPage::size, uint16_t> glyphStorage(length);
    uint16_t* glyphs = glyphStorage.get();
    typeface->charsToGlyphs(buffer, SkTypeface::kUTF16_Encoding, glyphs, length);

    bool haveGlyphs = false;
    for (unsigned i = 0; i < length; i++) {
        if (glyphs[i]) {
            pageToFill->setGlyphDataForIndex(offset + i, glyphs[i], this);
            haveGlyphs = true;
        }
    }

    return haveGlyphs;
}
Пример #6
0
SimpleFontData* SimpleFontData::scaledFontData(const FontDescription& fontDescription, float scaleFactor) const
{
    FontDescription desc = FontDescription(fontDescription);
    desc.setSpecifiedSize(scaleFactor * fontDescription.computedSize());
    FontPlatformData platformData(desc, desc.family().family());
    return new SimpleFontData(platformData, isCustomFont(), false);
}
Пример #7
0
bool SimpleFontData::fillGlyphPage(GlyphPage* pageToFill,
                                   unsigned offset,
                                   unsigned length,
                                   UChar* buffer,
                                   unsigned bufferLength) const {
  if (U16_IS_LEAD(buffer[bufferLength - 1])) {
    SkDebugf("%s last char is high-surrogate", __FUNCTION__);
    return false;
  }

  SkAutoSTMalloc<GlyphPage::size, uint16_t> glyphStorage(length);

  uint16_t* glyphs = glyphStorage.get();
  SkTypeface* typeface = platformData().typeface();
  typeface->charsToGlyphs(buffer, SkTypeface::kUTF16_Encoding, glyphs, length);

  bool haveGlyphs = false;
  for (unsigned i = 0; i < length; i++) {
    if (glyphs[i]) {
      pageToFill->setGlyphDataForIndex(offset + i, glyphs[i], this);
      haveGlyphs = true;
    }
  }

  return haveGlyphs;
}
Пример #8
0
Glyph SimpleFontData::glyphForCharacter(UChar32 codepoint) const {
  uint16_t glyph;
  SkTypeface* typeface = platformData().typeface();
  RELEASE_ASSERT(typeface);
  typeface->charsToGlyphs(&codepoint, SkTypeface::kUTF32_Encoding, &glyph, 1);
  return glyph;
}
Пример #9
0
js::detail::MutexImpl::MutexImpl()
{
  AutoEnterOOMUnsafeRegion oom;
  platformData_ = js_new<PlatformData>();
  if (!platformData_)
    oom.crash("js::detail::MutexImpl::MutexImpl");

  pthread_mutexattr_t* attrp = nullptr;

#ifdef DEBUG
  pthread_mutexattr_t attr;

  TRY_CALL_PTHREADS(pthread_mutexattr_init(&attr),
                    "js::detail::MutexImpl::MutexImpl: pthread_mutexattr_init failed");

  TRY_CALL_PTHREADS(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK),
                    "js::detail::MutexImpl::MutexImpl: pthread_mutexattr_settype failed");

  attrp = &attr;
#endif

  TRY_CALL_PTHREADS(pthread_mutex_init(&platformData()->ptMutex, attrp),
                    "js::detail::MutexImpl::MutexImpl: pthread_mutex_init failed");

#ifdef DEBUG
  TRY_CALL_PTHREADS(pthread_mutexattr_destroy(&attr),
                    "js::detail::MutexImpl::MutexImpl: pthread_mutexattr_destroy failed");
#endif
}
Пример #10
0
bool RendererGlLinux::initialize( void *window, RendererRef sharedRenderer )
{
	mContext = reinterpret_cast<GLFWwindow*>( window );

	::glfwMakeContextCurrent( mContext );

#if defined( CINDER_GL_ES )
	gl::Environment::setEs();
#else
	gl::Environment::setCore();
#endif
	gl::env()->initializeFunctionPointers();

	std::shared_ptr<gl::PlatformDataLinux> platformData( new gl::PlatformDataLinux( mContext ) );
	platformData->mDebug = mRenderer->getOptions().getDebug();
	platformData->mDebugLogSeverity = mRenderer->getOptions().getDebugLogSeverity();
	platformData->mDebugBreakSeverity = mRenderer->getOptions().getDebugBreakSeverity();
	platformData->mObjectTracking = mRenderer->getOptions().getObjectTracking();

	mCinderContext = gl::Context::createFromExisting( platformData );
	mCinderContext->makeCurrent();

	::glfwSwapInterval( 1 );

	return true;
}
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
    Olympia::Platform::Text::Font* font = platformData().font();
    ASSERT(font);

    const Olympia::Platform::Text::Utf16Char characters[] = { glyph };
    Olympia::Platform::Text::TextMetrics metrics;

#if PLATFORM(EGL) // FIXME: remove after Text API fixes shared context handling
    if (eglGetCurrentContext() == EGL_NO_CONTEXT)
        EGLDisplayOpenVG::current()->sharedPlatformSurface()->makeCurrent();
#endif
    FontPlatformData::engine()->drawText(0 /* no drawing, only measuring */,
        *font, characters, 1 /* number of characters */, 0 /*x*/, 0 /*y*/,
        0 /* no wrap */, 0 /* draw params */, &metrics);

    return metrics.m_linearAdvance * platformData().scaleFactor();
}
Пример #12
0
bool
js::Thread::Id::operator==(const Id& aOther) const
{
  const PlatformData& self = *platformData();
  const PlatformData& other = *aOther.platformData();
  return (!self.hasThread && !other.hasThread) ||
         (self.hasThread == other.hasThread &&
          pthread_equal(self.ptThread, other.ptThread));
}
Пример #13
0
String Font::description() const
{
    if (isSVGFont())
        return "[SVG font]";
    if (isCustomFont())
        return "[custom font]";

    return platformData().description();
}
Пример #14
0
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
    if (!glyph || !platformData().size())
        return 0;

    float escapements[1];
    CString encoded = UTF8Encoding().encode((UChar *)&glyph, 1, URLEncodedEntitiesForUnencodables);
    m_platformData.font()->GetEscapements(encoded.data(), 1, escapements);
    return escapements[0] * m_platformData.font()->Size();
}
Пример #15
0
SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
{
    if (!m_smallCapsFontData) {
        FontDescription desc = FontDescription(fontDescription);
        desc.setSpecifiedSize(0.70f * fontDescription.computedSize());
        FontPlatformData platformData(desc, desc.family().family());
        m_smallCapsFontData = new SimpleFontData(platformData);
    }
    return m_smallCapsFontData;
}
Пример #16
0
const char* SharedBuffer::data() const
{
    if (hasPlatformData())
        return platformData();
    
    if (m_purgeableBuffer)
        return m_purgeableBuffer->data();
    
    return buffer().data();
}
SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& desc) const
{
    if (m_smallCapsFontData)
        return m_smallCapsFontData;

    FontDescription smallCapsDesc = desc;
    smallCapsDesc.setSmallCaps(true);

    FontPlatformData smallCapsPlatformFont(smallCapsDesc, platformData().fontFamily());
    m_smallCapsFontData = new SimpleFontData(smallCapsPlatformFont);
    return m_smallCapsFontData;
}
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;
}
Пример #19
0
const char* SharedBuffer::data() const
{

    if (hasPlatformData())
        return platformData();

#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
    if (const char* buffer = singleDataArrayBuffer())
        return buffer;
#endif

    return this->buffer().data();
}
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
    if (!m_platformData.size())
        return 0;

    if (cairo_scaled_font_status(m_platformData.scaledFont()) != CAIRO_STATUS_SUCCESS)
        return m_spaceWidth;

    cairo_glyph_t cairoGlyph = { glyph, 0, 0 };
    cairo_text_extents_t extents;
    cairo_scaled_font_glyph_extents(m_platformData.scaledFont(), &cairoGlyph, 1, &extents);
    float width = platformData().orientation() == Horizontal ? extents.x_advance : -extents.y_advance;
    return width ? width : m_spaceWidth;
}
FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const
{
    Olympia::Platform::Text::Font* font = platformData().font();
    ASSERT(font);

    const Olympia::Platform::Text::Utf16Char characters[] = { glyph };
    Olympia::Platform::Text::TextMetrics metrics;

#if PLATFORM(EGL) // FIXME: remove after Text API fixes shared context handling
    if (eglGetCurrentContext() == EGL_NO_CONTEXT)
        EGLDisplayOpenVG::current()->sharedPlatformSurface()->makeCurrent();
#endif
    FontPlatformData::engine()->drawText(0 /* no drawing, only measuring */,
        *font, characters, 1 /* number of characters */, 0 /*x*/, 0 /*y*/,
        0 /* no wrap */, 0 /* draw params */, &metrics);

    const float scaleFactor = platformData().scaleFactor();
    float boundLeft = metrics.m_boundsLeft * scaleFactor;
    float boundTop = metrics.m_boundsTop * scaleFactor;
    float boundRight = metrics.m_boundsRight * scaleFactor;
    float boundBottom = metrics.m_boundsBottom * scaleFactor;
    return FloatRect(boundLeft, boundTop, boundRight - boundLeft, boundBottom - boundTop);
}
CFDictionaryRef Font::getCFStringAttributes(bool enableKerning, FontOrientation orientation) const
{
    auto& attributesDictionary = enableKerning ? m_kernedCFStringAttributes : m_nonKernedCFStringAttributes;
    if (attributesDictionary)
        return attributesDictionary.get();

    attributesDictionary = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 4, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
    CFMutableDictionaryRef mutableAttributes = (CFMutableDictionaryRef)attributesDictionary.get();

    CFDictionarySetValue(mutableAttributes, kCTFontAttributeName, platformData().ctFont());

    if (!enableKerning) {
        const float zero = 0;
        static CFNumberRef zeroKerningValue = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &zero);
        CFDictionarySetValue(mutableAttributes, kCTKernAttributeName, zeroKerningValue);
    }

    if (orientation == Vertical)
        CFDictionarySetValue(mutableAttributes, kCTVerticalFormsAttributeName, kCFBooleanTrue);

    return attributesDictionary.get();
}
Пример #23
0
const char* SharedBuffer::data() const
{
#if ENABLE(DISK_IMAGE_CACHE)
    if (isMemoryMapped())
        return static_cast<const char*>(diskImageCache().dataForItem(m_diskImageCacheId));
#endif

    if (hasPlatformData())
        return platformData();

#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
    if (const char* buffer = singleDataArrayBuffer())
        return buffer;
#endif

    createPurgeableBuffer();

    if (m_purgeableBuffer)
        return m_purgeableBuffer->data();
    
    return this->buffer().data();
}
Пример #24
0
void SimpleFontData::platformGlyphInit() {
  SkTypeface* typeface = platformData().typeface();
  if (!typeface->countGlyphs()) {
    m_spaceGlyph = 0;
    m_spaceWidth = 0;
    m_zeroGlyph = 0;
    m_missingGlyphData.fontData = this;
    m_missingGlyphData.glyph = 0;
    return;
  }

  // Nasty hack to determine if we should round or ceil space widths.
  // If the font is monospace or fake monospace we ceil to ensure that
  // every character and the space are the same width.  Otherwise we round.
  m_spaceGlyph = glyphForCharacter(' ');
  float width = widthForGlyph(m_spaceGlyph);
  m_spaceWidth = width;
  m_zeroGlyph = glyphForCharacter('0');
  m_fontMetrics.setZeroWidth(widthForGlyph(m_zeroGlyph));

  m_missingGlyphData.fontData = this;
  m_missingGlyphData.glyph = 0;
}
void SimpleFontData::platformInit()
{
    if (platformData().isValid()) {
        Olympia::Platform::Text::Font* font = platformData().font();
        const float scaleFactor = platformData().scaleFactor();
        ASSERT(font);

        Olympia::Platform::Text::FontMetrics fontMetrics;
        font->getFontMetrics(fontMetrics);

        m_ascent = fontMetrics.m_ascent * scaleFactor + 0.9;
        m_descent = fontMetrics.m_descent * scaleFactor + 0.9;
        m_lineGap = (fontMetrics.m_leadingAbove + fontMetrics.m_leadingBelow) * scaleFactor + 0.9;
        m_lineSpacing = m_ascent + m_descent + m_lineGap;
        m_maxCharWidth = fontMetrics.m_maxCharWidth * scaleFactor;
        m_unitsPerEm = fontMetrics.m_height * scaleFactor;

        static const Olympia::Platform::Text::Utf16Char characters[] = { 'x' };
        Olympia::Platform::Text::TextMetrics metrics;

#if PLATFORM(EGL) // FIXME: remove after Text API fixes shared context handling
        if (eglGetCurrentContext() == EGL_NO_CONTEXT)
            EGLDisplayOpenVG::current()->sharedPlatformSurface()->makeCurrent();
#endif
        FontPlatformData::engine()->drawText(0 /* no drawing, only measuring */,
            *font, characters, 1 /* number of characters */, 0 /*x*/, 0 /*y*/,
            0 /* no wrap */, 0 /* draw params */, &metrics);

        if (platformData().hasLineSpacingOverride()) {
            m_ascent = platformData().ascentOverride();
            m_descent = platformData().descentOverride();
            m_lineSpacing = platformData().lineSpacingOverride();
            m_lineGap = 0;
        }

        m_xHeight = (metrics.m_boundsBottom - metrics.m_boundsTop) * scaleFactor;
        m_avgCharWidth = metrics.m_linearAdvance * scaleFactor;
    }
}
Пример #26
0
CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typesettingFeatures) const
{
    unsigned key = typesettingFeatures + 1;
    pair<HashMap<unsigned, RetainPtr<CFDictionaryRef> >::iterator, bool> addResult = m_CFStringAttributes.add(key, RetainPtr<CFDictionaryRef>());
    RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.first->second;
    if (!addResult.second)
        return attributesDictionary.get();

    bool allowLigatures = platformData().allowsLigatures() || (typesettingFeatures & Ligatures);

    static const int ligaturesNotAllowedValue = 0;
    static CFNumberRef ligaturesNotAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesNotAllowedValue);

    static const int ligaturesAllowedValue = 1;
    static CFNumberRef ligaturesAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesAllowedValue);

    if (!(typesettingFeatures & Kerning)) {
        static const float kerningAdjustmentValue = 0;
        static CFNumberRef kerningAdjustment = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &kerningAdjustmentValue);
        static const void* keysWithKerningDisabled[] = { kCTFontAttributeName, kCTKernAttributeName, kCTLigatureAttributeName };
        const void* valuesWithKerningDisabled[] = { getCTFont(), kerningAdjustment, allowLigatures
            ? ligaturesAllowed : ligaturesNotAllowed };
        attributesDictionary.adoptCF(CFDictionaryCreate(0, keysWithKerningDisabled, valuesWithKerningDisabled,
            sizeof(keysWithKerningDisabled) / sizeof(*keysWithKerningDisabled),
            &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
    } else {
        // By omitting the kCTKernAttributeName attribute, we get Core Text's standard kerning.
        static const void* keysWithKerningEnabled[] = { kCTFontAttributeName, kCTLigatureAttributeName };
        const void* valuesWithKerningEnabled[] = { getCTFont(), allowLigatures ? ligaturesAllowed : ligaturesNotAllowed };
        attributesDictionary.adoptCF(CFDictionaryCreate(0, keysWithKerningEnabled, valuesWithKerningEnabled,
            sizeof(keysWithKerningEnabled) / sizeof(*keysWithKerningEnabled),
            &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
    }

    return attributesDictionary.get();
}
Пример #27
0
GlyphData FontCascadeFonts::glyphDataForSystemFallback(UChar32 c, const FontCascadeDescription& description, FontVariant variant)
{
    // System fallback is character-dependent.
    auto& primaryRanges = realizeFallbackRangesAt(description, 0);
    auto* originalFont = primaryRanges.fontForCharacter(c);
    if (!originalFont)
        originalFont = &primaryRanges.fontForFirstRange();

    auto systemFallbackFont = originalFont->systemFallbackFontForCharacter(c, description, m_isForPlatformFont);
    if (!systemFallbackFont)
        return GlyphData();

    if (systemFallbackFont->platformData().orientation() == Vertical && !systemFallbackFont->hasVerticalGlyphs() && FontCascade::isCJKIdeographOrSymbol(c))
        variant = BrokenIdeographVariant;

    GlyphData fallbackGlyphData;
    if (variant == NormalVariant)
        fallbackGlyphData = systemFallbackFont->glyphDataForCharacter(c);
    else
        fallbackGlyphData = systemFallbackFont->variantFont(description, variant)->glyphDataForCharacter(c);

    if (fallbackGlyphData.font && fallbackGlyphData.font->platformData().orientation() == Vertical && !fallbackGlyphData.font->isTextOrientationFallback()) {
        if (variant == NormalVariant && !FontCascade::isCJKIdeographOrSymbol(c))
            fallbackGlyphData = glyphDataForNonCJKCharacterWithGlyphOrientation(c, description.nonCJKGlyphOrientation(), fallbackGlyphData);
#if PLATFORM(COCOA) || USE(CAIRO)
        if (fallbackGlyphData.font->platformData().syntheticOblique() && FontCascade::isCJKIdeographOrSymbol(c))
            fallbackGlyphData = glyphDataForCJKCharacterWithoutSyntheticItalic(c, fallbackGlyphData);
#endif
    }

    // Keep the system fallback fonts we use alive.
    if (fallbackGlyphData.glyph)
        m_systemFallbackFontSet.add(WTFMove(systemFallbackFont));

    return fallbackGlyphData;
}
Пример #28
0
void SimpleFontData::platformInit(bool subpixelAscentDescent) {
  if (!m_platformData.size()) {
    m_fontMetrics.reset();
    m_avgCharWidth = 0;
    m_maxCharWidth = 0;
    return;
  }

  SkPaint::FontMetrics metrics;

  m_platformData.setupPaint(&m_paint);
  m_paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
  m_paint.getFontMetrics(&metrics);
  SkTypeface* face = m_paint.getTypeface();
  ASSERT(face);

  int vdmxAscent = 0, vdmxDescent = 0;
  bool isVDMXValid = false;

#if OS(LINUX) || OS(ANDROID)
  // Manually digging up VDMX metrics is only applicable when bytecode hinting
  // using FreeType.  With DirectWrite or CoreText, no bytecode hinting is ever
  // done.  This code should be pushed into FreeType (hinted font metrics).
  static const uint32_t vdmxTag = SkSetFourByteTag('V', 'D', 'M', 'X');
  int pixelSize = m_platformData.size() + 0.5;
  if (!m_paint.isAutohinted() &&
      (m_paint.getHinting() == SkPaint::kFull_Hinting ||
       m_paint.getHinting() == SkPaint::kNormal_Hinting)) {
    size_t vdmxSize = face->getTableSize(vdmxTag);
    if (vdmxSize && vdmxSize < maxVDMXTableSize) {
      uint8_t* vdmxTable = (uint8_t*)WTF::Partitions::fastMalloc(
          vdmxSize, WTF_HEAP_PROFILER_TYPE_NAME(SimpleFontData));
      if (vdmxTable &&
          face->getTableData(vdmxTag, 0, vdmxSize, vdmxTable) == vdmxSize &&
          parseVDMX(&vdmxAscent, &vdmxDescent, vdmxTable, vdmxSize, pixelSize))
        isVDMXValid = true;
      WTF::Partitions::fastFree(vdmxTable);
    }
  }
#endif

  float ascent;
  float descent;

  // Beware those who step here: This code is designed to match Win32 font
  // metrics *exactly* except:
  // - the adjustment of ascent/descent on Linux/Android
  // - metrics.fAscent and .fDesscent are not rounded to int for tiny fonts
  if (isVDMXValid) {
    ascent = vdmxAscent;
    descent = -vdmxDescent;
  } else {
    // For tiny fonts, the rounding of fAscent and fDescent results in equal
    // baseline for different types of text baselines (crbug.com/338908).
    // Please see CanvasRenderingContext2D::getFontBaseline for the heuristic.
    if (subpixelAscentDescent &&
        (-metrics.fAscent < 3 || -metrics.fAscent + metrics.fDescent < 2)) {
      ascent = -metrics.fAscent;
      descent = metrics.fDescent;
    } else {
      ascent = SkScalarRoundToScalar(-metrics.fAscent);
      descent = SkScalarRoundToScalar(metrics.fDescent);
    }
#if OS(LINUX) || OS(ANDROID)
    // When subpixel positioning is enabled, if the descent is rounded down, the
    // descent part of the glyph may be truncated when displayed in a 'overflow:
    // hidden' container.  To avoid that, borrow 1 unit from the ascent when
    // possible.
    // FIXME: This can be removed if sub-pixel ascent/descent is supported.
    if (platformData().getFontRenderStyle().useSubpixelPositioning &&
        descent < SkScalarToFloat(metrics.fDescent) && ascent >= 1) {
      ++descent;
      --ascent;
    }
#endif
  }

#if OS(MACOSX)
  // We are preserving this ascent hack to match Safari's ascent adjustment
  // in their SimpleFontDataMac.mm, for details see crbug.com/445830.
  // We need to adjust Times, Helvetica, and Courier to closely match the
  // vertical metrics of their Microsoft counterparts that are the de facto
  // web standard. The AppKit adjustment of 20% is too big and is
  // incorrectly added to line spacing, so we use a 15% adjustment instead
  // and add it to the ascent.
  DEFINE_STATIC_LOCAL(AtomicString, timesName, ("Times"));
  DEFINE_STATIC_LOCAL(AtomicString, helveticaName, ("Helvetica"));
  DEFINE_STATIC_LOCAL(AtomicString, courierName, ("Courier"));
  String familyName = m_platformData.fontFamilyName();
  if (familyName == timesName || familyName == helveticaName ||
      familyName == courierName)
    ascent += floorf(((ascent + descent) * 0.15f) + 0.5f);
#endif

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

  float xHeight;
  if (metrics.fXHeight) {
    xHeight = metrics.fXHeight;
#if OS(MACOSX)
    // Mac OS CTFontGetXHeight reports the bounding box height of x,
    // including parts extending below the baseline and apparently no x-height
    // value from the OS/2 table. However, the CSS ex unit
    // expects only parts above the baseline, hence measuring the glyph:
    // http://www.w3.org/TR/css3-values/#ex-unit
    const Glyph xGlyph = glyphForCharacter('x');
    if (xGlyph) {
      FloatRect glyphBounds(boundsForGlyph(xGlyph));
      // SkGlyph bounds, y down, based on rendering at (0,0).
      xHeight = -glyphBounds.y();
    }
#endif
    m_fontMetrics.setXHeight(xHeight);
  } else {
    xHeight = ascent * 0.56;  // Best guess from Windows font metrics.
    m_fontMetrics.setXHeight(xHeight);
    m_fontMetrics.setHasXHeight(false);
  }

  float lineGap = SkScalarToFloat(metrics.fLeading);
  m_fontMetrics.setLineGap(lineGap);
  m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) +
                               lroundf(lineGap));

  if (platformData().isVerticalAnyUpright() && !isTextOrientationFallback()) {
    static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a');
    static const uint32_t vorgTag = SkSetFourByteTag('V', 'O', 'R', 'G');
    size_t vheaSize = face->getTableSize(vheaTag);
    size_t vorgSize = face->getTableSize(vorgTag);
    if ((vheaSize > 0) || (vorgSize > 0))
      m_hasVerticalGlyphs = true;
  }

// In WebKit/WebCore/platform/graphics/SimpleFontData.cpp, m_spaceWidth is
// calculated for us, but we need to calculate m_maxCharWidth and
// m_avgCharWidth in order for text entry widgets to be sized correctly.
#if OS(WIN)
  m_maxCharWidth = SkScalarRoundToInt(metrics.fMaxCharWidth);

  // Older version of the DirectWrite API doesn't implement support for max
  // char width. Fall back on a multiple of the ascent. This is entirely
  // arbitrary but comes pretty close to the expected value in most cases.
  if (m_maxCharWidth < 1)
    m_maxCharWidth = ascent * 2;
#elif OS(MACOSX)
  // FIXME: The current avg/max character width calculation is not ideal,
  // it should check either the OS2 table or, better yet, query FontMetrics.
  // Sadly FontMetrics provides incorrect data on Mac at the moment.
  // https://crbug.com/420901
  m_maxCharWidth = std::max(m_avgCharWidth, m_fontMetrics.floatAscent());
#else
  // Better would be to rely on either fMaxCharWidth or fAveCharWidth.
  // skbug.com/3087
  m_maxCharWidth = SkScalarRoundToInt(metrics.fXMax - metrics.fXMin);

#endif

#if !OS(MACOSX)
  if (metrics.fAvgCharWidth) {
    m_avgCharWidth = SkScalarRoundToInt(metrics.fAvgCharWidth);
  } else {
#endif
    m_avgCharWidth = xHeight;
    const Glyph xGlyph = glyphForCharacter('x');
    if (xGlyph) {
      m_avgCharWidth = widthForGlyph(xGlyph);
    }
#if !OS(MACOSX)
  }
#endif

  if (int unitsPerEm = face->getUnitsPerEm())
    m_fontMetrics.setUnitsPerEm(unitsPerEm);
}
void SimpleFontData::platformInit()
{
    if (!m_platformData.size()) {
        m_fontMetrics.reset();
        m_avgCharWidth = 0;
        m_maxCharWidth = 0;
        return;
    }

    SkPaint paint;
    SkPaint::FontMetrics metrics;

    m_platformData.setupPaint(&paint);
    paint.getFontMetrics(&metrics);
    const SkFontID fontID = m_platformData.uniqueID();

    static const uint32_t vdmxTag = SkSetFourByteTag('V', 'D', 'M', 'X');
    int pixelSize = m_platformData.size() + 0.5;
    int vdmxAscent, vdmxDescent;
    bool isVDMXValid = false;

    size_t vdmxSize = SkFontHost::GetTableSize(fontID, vdmxTag);
    if (vdmxSize && vdmxSize < maxVDMXTableSize) {
        uint8_t* vdmxTable = (uint8_t*) fastMalloc(vdmxSize);
        if (vdmxTable
            && SkFontHost::GetTableData(fontID, vdmxTag, 0, vdmxSize, vdmxTable) == vdmxSize
            && parseVDMX(&vdmxAscent, &vdmxDescent, vdmxTable, vdmxSize, pixelSize))
            isVDMXValid = true;
        fastFree(vdmxTable);
    }

    float ascent;
    float descent;

    // Beware those who step here: This code is designed to match Win32 font
    // metrics *exactly*.
    if (isVDMXValid) {
        ascent = vdmxAscent;
        descent = -vdmxDescent;
    } else {
        SkScalar height = -metrics.fAscent + metrics.fDescent + metrics.fLeading;
        ascent = SkScalarRound(-metrics.fAscent);
        descent = SkScalarRound(height) - ascent;
    }

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

    float xHeight;
    if (metrics.fXHeight)
        xHeight = metrics.fXHeight;
    else {
        // hack taken from the Windows port
        xHeight = ascent * 0.56f;
    }

    float lineGap = SkScalarToFloat(metrics.fLeading);
    m_fontMetrics.setLineGap(lineGap);
    m_fontMetrics.setXHeight(xHeight);
    m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));

    if (platformData().orientation() == Vertical && !isTextOrientationFallback()) {
        static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a');
        static const uint32_t vorgTag = SkSetFourByteTag('V', 'O', 'R', 'G');
        size_t vheaSize = SkFontHost::GetTableSize(fontID, vheaTag);
        size_t vorgSize = SkFontHost::GetTableSize(fontID, vorgTag);
        if ((vheaSize > 0) || (vorgSize > 0))
            m_hasVerticalGlyphs = true;
    }

    // In WebKit/WebCore/platform/graphics/SimpleFontData.cpp, m_spaceWidth is
    // calculated for us, but we need to calculate m_maxCharWidth and
    // m_avgCharWidth in order for text entry widgets to be sized correctly.

    SkScalar xRange = metrics.fXMax - metrics.fXMin;
    m_maxCharWidth = SkScalarRound(xRange * SkScalarRound(m_platformData.size()));

    if (metrics.fAvgCharWidth)
        m_avgCharWidth = SkScalarRound(metrics.fAvgCharWidth);
    else {
        m_avgCharWidth = xHeight;

        GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();

        if (glyphPageZero) {
            static const UChar32 x_char = 'x';
            const Glyph xGlyph = glyphPageZero->glyphDataForCharacter(x_char).glyph;

            if (xGlyph)
                m_avgCharWidth = widthForGlyph(xGlyph);
        }
    }
}
void SimpleFontData::determinePitch()
{
    m_treatAsFixedPitch = platformData().isFixedPitch();
}