Example #1
0
static OSStatus atsuPostLayoutCallback(ATSULayoutOperationSelector selector, ATSULineRef lineRef, URefCon refCon,
                                 void *operationExtraParameter, ATSULayoutOperationCallbackStatus *callbackStatus)
{
    Q_UNUSED(selector);
    Q_UNUSED(operationExtraParameter);

    QGlyphLayoutInfo *nfo = reinterpret_cast<QGlyphLayoutInfo *>(refCon);
    nfo->callbackCalled = true;

    ATSLayoutRecord *layoutData = 0;
    ItemCount itemCount = 0;

    OSStatus e = noErr;
    e = ATSUDirectGetLayoutDataArrayPtrFromLineRef(lineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
                                                   /*iCreate =*/ false,
                                                   (void **) &layoutData,
                                                   &itemCount);
    if (e != noErr)
        return e;

    *nfo->numGlyphs = itemCount - 1;

    Fixed *baselineDeltas = 0;

    e = ATSUDirectGetLayoutDataArrayPtrFromLineRef(lineRef, kATSUDirectDataBaselineDeltaFixedArray,
                                                   /*iCreate =*/ true,
                                                   (void **) &baselineDeltas,
                                                   &itemCount);
    if (e != noErr)
        return e;

    int nextCharStop = -1;
    int currentClusterGlyph = -1; // first glyph in log cluster
    QShaperItem *item = 0;
    if (nfo->shaperItem) {
        item = nfo->shaperItem;
#if !defined(QT_NO_DEBUG)
        int surrogates = 0;
        const QString &str = *item->string;
        for (int i = item->from; i < item->from + item->length - 1; ++i) {
            surrogates += (str[i].unicode() >= 0xd800 && str[i].unicode() < 0xdc00
                           && str[i+1].unicode() >= 0xdc00 && str[i+1].unicode() < 0xe000);
        }
        Q_ASSERT(*nfo->numGlyphs == item->length - surrogates);
#endif
        for (nextCharStop = item->from; nextCharStop < item->from + item->length; ++nextCharStop)
            if (item->charAttributes[nextCharStop].charStop)
                break;
        nextCharStop -= item->from;
    }

    nfo->glyphs[0].attributes.clusterStart = true;
    int glyphIdx = 0;
    int glyphIncrement = 1;
    if (nfo->flags & QTextEngine::RightToLeft) {
        glyphIdx  = itemCount - 2;
        glyphIncrement = -1;
    }
    for (int i = 0; i < *nfo->numGlyphs; ++i, glyphIdx += glyphIncrement) {

        int charOffset = layoutData[glyphIdx].originalOffset / sizeof(UniChar);
        const int fontIdx = nfo->mappedFonts[charOffset];

        ATSGlyphRef glyphId = layoutData[glyphIdx].glyphID;

        QFixed yAdvance = FixedToQFixed(baselineDeltas[glyphIdx]);
        QFixed xAdvance = FixedToQFixed(layoutData[glyphIdx + 1].realPos - layoutData[glyphIdx].realPos);

        if (glyphId != 0xffff || i == 0) {
            nfo->glyphs[i].glyph = (glyphId & 0x00ffffff) | (fontIdx << 24);

            nfo->glyphs[i].advance.y = yAdvance;
            nfo->glyphs[i].advance.x = xAdvance;
        } else {
            // ATSUI gives us 0xffff as glyph id at the index in the glyph array for
            // a character position that maps to a ligtature. Such a glyph id does not
            // result in any visual glyph, but it may have an advance, which is why we
            // sum up the glyph advances.
            --i;
            nfo->glyphs[i].advance.y += yAdvance;
            nfo->glyphs[i].advance.x += xAdvance;
            *nfo->numGlyphs -= 1;
        }

        if (item) {
            if (charOffset >= nextCharStop) {
                nfo->glyphs[i].attributes.clusterStart = true;
                currentClusterGlyph = i;

                ++nextCharStop;
                for (; nextCharStop < item->length; ++nextCharStop)
                    if (item->charAttributes[item->from + nextCharStop].charStop)
                        break;
            } else {
                if (currentClusterGlyph == -1)
                    currentClusterGlyph = i;
            }
            item->log_clusters[charOffset] = currentClusterGlyph;

            // surrogate handling
            if (charOffset < item->length - 1) {
                QChar current = item->string->at(item->from + charOffset);
                QChar next = item->string->at(item->from + charOffset + 1);
                if (current.unicode() >= 0xd800 && current.unicode() < 0xdc00
                    && next.unicode() >= 0xdc00 && next.unicode() < 0xe000) {
                    item->log_clusters[charOffset + 1] = currentClusterGlyph;
                }
            }
        }
    }

    /*
    if (item) {
        qDebug() << "resulting logclusters:";
        for (int i = 0; i < item->length; ++i)
            qDebug() << "logClusters[" << i << "] =" << item->log_clusters[i];
        qDebug() << "clusterstarts:";
        for (int i = 0; i < *nfo->numGlyphs; ++i)
            qDebug() << "clusterStart[" << i << "] =" << nfo->glyphs[i].attributes.clusterStart;
    }
    */

    ATSUDirectReleaseLayoutDataArrayPtr(lineRef, kATSUDirectDataBaselineDeltaFixedArray,
                                        (void **) &baselineDeltas);

    ATSUDirectReleaseLayoutDataArrayPtr(lineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
                                        (void **) &layoutData);

    *callbackStatus = kATSULayoutOperationCallbackStatusHandled;
    return noErr;
}
Example #2
0
static cairo_status_t
_cairo_atsui_font_text_to_glyphs(void		*abstract_font,
                                 const char     *utf8,
                                 cairo_glyph_t **glyphs,
				 int		*num_glyphs)
{
    cairo_atsui_font_t *font = abstract_font;
    size_t i;
    OSStatus err;
    ATSUTextLayout textLayout;
    ATSLayoutRecord *layoutRecords;
    ItemCount glyphCount;
    int charCount;
    UniChar *theText;
    cairo_status_t status;

    // liberal estimate of size
    charCount = strlen(utf8);

    if (charCount == 0) {
       *glyphs = NULL;
       *num_glyphs = 0;
       return CAIRO_STATUS_SUCCESS;
    }

    status = _cairo_utf8_to_utf16 (utf8, -1, &theText, &charCount);
    if (status)
	return status;

    err = ATSUCreateTextLayout(&textLayout);

    err = ATSUSetTextPointerLocation(textLayout,
                                     theText, 0, charCount, charCount);


    // Set the style for all of the text
    err = ATSUSetRunStyle(textLayout,
                          font->unscaled_style, kATSUFromTextBeginning, kATSUToTextEnd);

    // Get the glyphs from the text layout object
    err = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(textLayout,
                                                        0,
                                                        kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
                                                        (void *)
                                                        &layoutRecords,
                                                        &glyphCount);

    *num_glyphs = glyphCount - 1;


    *glyphs =
        (cairo_glyph_t *) malloc(*num_glyphs * (sizeof(cairo_glyph_t)));
    if (*glyphs == NULL) {
        return CAIRO_STATUS_NO_MEMORY;
    }

    for (i = 0; i < *num_glyphs; i++) {
        (*glyphs)[i].index = layoutRecords[i].glyphID;
        (*glyphs)[i].x = FixedToFloat(layoutRecords[i].realPos);
        (*glyphs)[i].y = 0;
    }


    free(theText);

    ATSUDirectReleaseLayoutDataArrayPtr(NULL,
                                        kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
                                        (void *) &layoutRecords);

    ATSUDisposeTextLayout(textLayout);

    return CAIRO_STATUS_SUCCESS;
}
Example #3
0
void
DoAtsuiLayout(void* p, int justify)
{
	memoryword*	node = (memoryword*)p;

	unsigned	f = native_font(node);
	if (fontarea[f] != AAT_FONT_FLAG) {
		fprintf(stderr, "internal error: do_atsui_layout called for non-ATSUI font\n");
		exit(1);
	}

	if (sTextLayout == 0)
		InitializeLayout();

	OSStatus	status = noErr;
	
	long		txtLen = native_length(node);
	const UniChar*	txtPtr = (UniChar*)(node + native_node_size);

	status = ATSUSetTextPointerLocation(sTextLayout, txtPtr, 0, txtLen, txtLen);
	
	// we're using this font in AAT mode, so fontlayoutengine[f] is actually an ATSUStyle
	ATSUStyle	style = (ATSUStyle)(fontlayoutengine[native_font(node)]);
	status = ATSUSetRunStyle(sTextLayout, style, 0, txtLen);

	ATSUAttributeTag		tags[] = { kATSULineWidthTag, kATSULineJustificationFactorTag };
	ItemCount				numTags = sizeof(tags) / sizeof(ATSUAttributeTag);
	if (justify) {
		ByteCount				valSizes[] = { sizeof(Fixed), sizeof(Fract) };
		Fixed					wid = FixedTeXtoPSPoints(node_width(node));
		Fract					just = fract1;
		ATSUAttributeValuePtr	valPtrs[] = { &wid, &just };
		status = ATSUSetLayoutControls(sTextLayout, numTags, tags, valSizes, valPtrs);
	}
	
	ItemCount	count;
	ATSLayoutRecord*	layoutRec = NULL;
	status = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(sTextLayout, 0,
		kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void*)&layoutRec, &count);

	int i;
	int	realGlyphCount = 0;
	int lastRealGlyph = 0;
	for (i = 0; i < count; ++i)
		if (layoutRec[i].glyphID < 0xfffe) {
			lastRealGlyph = i;
			++realGlyphCount;
		}

	void*		glyph_info = xmalloc(realGlyphCount * native_glyph_info_size);
	FixedPoint*	locations = (FixedPoint*)glyph_info;
	UInt16*		glyphIDs = (UInt16*)(locations + realGlyphCount);

	Fixed		lsUnit = justify ? 0 : fontletterspace[f];
	Fixed		lsDelta = 0;

	realGlyphCount = 0;
	for (i = 0; i < count; ++i) {
		if (layoutRec[i].glyphID < 0xfffe) {
			if ((layoutRec[i].flags & kATSGlyphInfoIsAttachment) && (lsDelta != 0))
				lsDelta -= lsUnit;
			glyphIDs[realGlyphCount] = layoutRec[i].glyphID;
			locations[realGlyphCount].y = 0;	/* FIXME: won't handle baseline offsets */
			locations[realGlyphCount].x = FixedPStoTeXPoints(layoutRec[i].realPos) + lsDelta;
			lsDelta += lsUnit;
			++realGlyphCount;
		}
	}
	if (lsDelta != 0)
		lsDelta -= lsUnit;

	native_glyph_count(node) = realGlyphCount;
	native_glyph_info_ptr(node) = glyph_info;
	
	if (!justify)
		node_width(node) = FixedPStoTeXPoints(layoutRec[count-1].realPos) + lsDelta;

	ATSUDirectReleaseLayoutDataArrayPtr(NULL, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void*)&layoutRec);

	if (justify)
		ATSUClearLayoutControls(sTextLayout, numTags, tags);
}