+++ /dev/null
-
-/*
- * Copyright 2009 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include "SkHarfBuzzFont.h"
-#include "SkFontHost.h"
-#include "SkPaint.h"
-#include "SkPath.h"
-
-// HB_Fixed is a 26.6 fixed point format.
-static inline HB_Fixed SkScalarToHarfbuzzFixed(SkScalar value) {
- return static_cast<HB_Fixed>(value * 64);
-}
-
-static HB_Bool stringToGlyphs(HB_Font hbFont, const HB_UChar16* characters,
- hb_uint32 length, HB_Glyph* glyphs,
- hb_uint32* glyphsSize, HB_Bool isRTL) {
- SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData);
- SkPaint paint;
-
- paint.setTypeface(font->getTypeface());
- paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
- int numGlyphs = paint.textToGlyphs(characters, length * sizeof(uint16_t),
- reinterpret_cast<uint16_t*>(glyphs));
-
- // HB_Glyph is 32-bit, but Skia outputs only 16-bit numbers. So our
- // |glyphs| array needs to be converted.
- for (int i = numGlyphs - 1; i >= 0; --i) {
- uint16_t value;
- // We use a memcpy to avoid breaking strict aliasing rules.
- memcpy(&value, reinterpret_cast<char*>(glyphs) + sizeof(uint16_t) * i, sizeof(uint16_t));
- glyphs[i] = value;
- }
-
- *glyphsSize = numGlyphs;
- return 1;
-}
-
-static void glyphsToAdvances(HB_Font hbFont, const HB_Glyph* glyphs,
- hb_uint32 numGlyphs, HB_Fixed* advances, int flags) {
- SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData);
- SkPaint paint;
-
- font->setupPaint(&paint);
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
-
- SkAutoMalloc storage(numGlyphs * (sizeof(SkScalar) + sizeof(uint16_t)));
- SkScalar* scalarWidths = reinterpret_cast<SkScalar*>(storage.get());
- uint16_t* glyphs16 = reinterpret_cast<uint16_t*>(scalarWidths + numGlyphs);
-
- // convert HB 32bit glyphs to skia's 16bit
- for (hb_uint32 i = 0; i < numGlyphs; ++i) {
- glyphs16[i] = SkToU16(glyphs[i]);
- }
- paint.getTextWidths(glyphs16, numGlyphs * sizeof(uint16_t), scalarWidths);
-
- for (hb_uint32 i = 0; i < numGlyphs; ++i) {
- advances[i] = SkScalarToHarfbuzzFixed(scalarWidths[i]);
- }
-}
-
-static HB_Bool canRender(HB_Font hbFont, const HB_UChar16* characters,
- hb_uint32 length) {
- SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData);
- SkPaint paint;
-
- paint.setTypeface(font->getTypeface());
- paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
- return paint.containsText(characters, length * sizeof(uint16_t));
-}
-
-static HB_Error getOutlinePoint(HB_Font hbFont, HB_Glyph glyph, int flags,
- hb_uint32 index, HB_Fixed* xPos, HB_Fixed* yPos,
- hb_uint32* resultingNumPoints) {
- SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData);
- SkPaint paint;
-
- font->setupPaint(&paint);
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- if (flags & HB_ShaperFlag_UseDesignMetrics) {
- paint.setHinting(SkPaint::kNo_Hinting);
- }
-
- SkPath path;
- uint16_t glyph16 = SkToU16(glyph);
- paint.getTextPath(&glyph16, sizeof(glyph16), 0, 0, &path);
- int numPoints = path.countPoints();
- if (index >= numPoints) {
- return HB_Err_Invalid_SubTable;
- }
-
- SkPoint pt = path.getPoint(index);
- *xPos = SkScalarToHarfbuzzFixed(pt.fX);
- *yPos = SkScalarToHarfbuzzFixed(pt.fY);
- *resultingNumPoints = numPoints;
-
- return HB_Err_Ok;
-}
-
-static void getGlyphMetrics(HB_Font hbFont, HB_Glyph glyph,
- HB_GlyphMetrics* metrics) {
- SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData);
- SkPaint paint;
-
- font->setupPaint(&paint);
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
-
- SkScalar width;
- SkRect bounds;
- uint16_t glyph16 = SkToU16(glyph);
- paint.getTextWidths(&glyph16, sizeof(glyph16), &width, &bounds);
-
- metrics->x = SkScalarToHarfbuzzFixed(bounds.fLeft);
- metrics->y = SkScalarToHarfbuzzFixed(bounds.fTop);
- metrics->width = SkScalarToHarfbuzzFixed(bounds.width());
- metrics->height = SkScalarToHarfbuzzFixed(bounds.height());
-
- metrics->xOffset = SkScalarToHarfbuzzFixed(width);
- // We can't actually get the |y| correct because Skia doesn't export
- // the vertical advance. However, nor we do ever render vertical text at
- // the moment so it's unimportant.
- metrics->yOffset = 0;
-}
-
-static HB_Fixed getFontMetric(HB_Font hbFont, HB_FontMetric metric)
-{
- SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData);
- SkPaint paint;
- SkPaint::FontMetrics skiaMetrics;
-
- font->setupPaint(&paint);
- paint.getFontMetrics(&skiaMetrics);
-
- switch (metric) {
- case HB_FontAscent:
- return SkScalarToHarfbuzzFixed(-skiaMetrics.fAscent);
- default:
- SkDebugf("--- unknown harfbuzz metric enum %d\n", metric);
- return 0;
- }
-}
-
-static HB_FontClass gSkHarfBuzzFontClass = {
- stringToGlyphs,
- glyphsToAdvances,
- canRender,
- getOutlinePoint,
- getGlyphMetrics,
- getFontMetric,
-};
-
-const HB_FontClass& SkHarfBuzzFont::GetFontClass() {
- return gSkHarfBuzzFontClass;
-}
-
-HB_Error SkHarfBuzzFont::GetFontTableFunc(void* voidface, const HB_Tag tag,
- HB_Byte* buffer, HB_UInt* len) {
- SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(voidface);
- SkTypeface* typeface = font->getTypeface();
-
- const size_t tableSize = typeface->getTableSize(tag);
- if (!tableSize) {
- return HB_Err_Invalid_Argument;
- }
- // If Harfbuzz specified a NULL buffer then it's asking for the size.
- if (!buffer) {
- *len = tableSize;
- return HB_Err_Ok;
- }
-
- if (*len < tableSize) {
- // is this right, or should we just copy less than the full table?
- return HB_Err_Invalid_Argument;
- }
- typeface->getTableData(tag, 0, tableSize, buffer);
- return HB_Err_Ok;
-}
+++ /dev/null
-
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include "SkXMLParser.h"
-#include "SkString.h"
-#include "SkStream.h"
-
-#include "expat.h"
-
-#ifdef SK_BUILD_FOR_PPI
-#define CHAR_16_TO_9
-#endif
-
-#if defined CHAR_16_TO_9
-inline size_t sk_wcslen(const short* char16) {
- const short* start = char16;
- while (*char16)
- char16++;
- return char16 - start;
-}
-
-inline const char* ConvertUnicodeToChar(const short* ch16, size_t len, SkAutoMalloc& ch8Malloc) {
- char* ch8 = (char*) ch8Malloc.get();
- int index;
- for (index = 0; index < len; index++)
- ch8[index] = (char) ch16[index];
- ch8[index] = '\0';
- return ch8;
-}
-#endif
-
-static void XMLCALL start_proc(void *data, const char *el, const char **attr)
-{
-#if defined CHAR_16_TO_9
- size_t len = sk_wcslen((const short*) el);
- SkAutoMalloc el8(len + 1);
- el = ConvertUnicodeToChar((const short*) el, len, el8);
-#endif
- if (((SkXMLParser*)data)->startElement(el)) {
- XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false);
- return;
- }
- while (*attr)
- {
- const char* attr0 = attr[0];
- const char* attr1 = attr[1];
-#if defined CHAR_16_TO_9
- size_t len0 = sk_wcslen((const short*) attr0);
- SkAutoMalloc attr0_8(len0 + 1);
- attr0 = ConvertUnicodeToChar((const short*) attr0, len0, attr0_8);
- size_t len1 = sk_wcslen((const short*) attr1);
- SkAutoMalloc attr1_8(len1 + 1);
- attr1 = ConvertUnicodeToChar((const short*) attr1, len1, attr1_8);
-#endif
- if (((SkXMLParser*)data)->addAttribute(attr0, attr1)) {
- XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false);
- return;
- }
- attr += 2;
- }
-}
-
-static void XMLCALL end_proc(void *data, const char *el)
-{
-#if defined CHAR_16_TO_9
- size_t len = sk_wcslen((const short*) el);
- SkAutoMalloc el8(len + 1);
- el = ConvertUnicodeToChar((const short*) el, len, el8);
-#endif
- if (((SkXMLParser*)data)->endElement(el))
- XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false);
-}
-
-static void XMLCALL text_proc(void* data, const char* text, int len)
-{
-#if defined CHAR_16_TO_9
- SkAutoMalloc text8(len + 1);
- text = ConvertUnicodeToChar((const short*) text, len, text8);
-#endif
- if (((SkXMLParser*)data)->text(text, len))
- XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false);
-}
-
-bool SkXMLParser::parse(const char doc[], size_t len)
-{
- if (len == 0) {
- fError->fCode = SkXMLParserError::kEmptyFile;
- reportError(NULL);
- return false;
- }
- XML_Parser p = XML_ParserCreate(NULL);
- SkASSERT(p);
- fParser = p;
- XML_SetElementHandler(p, start_proc, end_proc);
- XML_SetCharacterDataHandler(p, text_proc);
- XML_SetUserData(p, this);
-
- bool success = true;
- int error = XML_Parse(p, doc, len, true);
- if (error == XML_STATUS_ERROR) {
- reportError(p);
- success = false;
- }
- XML_ParserFree(p);
- return success;
-}
-
-bool SkXMLParser::parse(SkStream& input)
-{
- size_t len = input.getLength();
- SkAutoMalloc am(len);
- char* doc = (char*)am.get();
-
- input.rewind();
- size_t len2 = input.read(doc, len);
- SkASSERT(len2 == len);
-
- return this->parse(doc, len2);
-}
-
-void SkXMLParser::reportError(void* p)
-{
- XML_Parser parser = (XML_Parser) p;
- if (fError && parser) {
- fError->fNativeCode = XML_GetErrorCode(parser);
- fError->fLineNumber = XML_GetCurrentLineNumber(parser);
- }
-}
-
-void SkXMLParser::GetNativeErrorString(int error, SkString* str)
-{
- if (str)
- str->set(XML_ErrorString((XML_Error) error));
-}
+++ /dev/null
-
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include "SkXMLParser.h"
-#include "SkStream.h"
-#include "SkTemplates.h"
-#include "tinyxml.h"
-
-static void walk_elem(SkXMLParser* parser, const TiXmlElement* elem)
-{
- //printf("walk_elem(%s) ", elem->Value());
-
- parser->startElement(elem->Value());
-
- const TiXmlAttribute* attr = elem->FirstAttribute();
- while (attr)
- {
- //printf("walk_elem_attr(%s=\"%s\") ", attr->Name(), attr->Value());
-
- parser->addAttribute(attr->Name(), attr->Value());
- attr = attr->Next();
- }
- //printf("\n");
-
- const TiXmlNode* node = elem->FirstChild();
- while (node)
- {
- if (node->ToElement())
- walk_elem(parser, node->ToElement());
- else if (node->ToText())
- parser->text(node->Value(), strlen(node->Value()));
- node = node->NextSibling();
- }
-
- parser->endElement(elem->Value());
-}
-
-static bool load_buf(SkXMLParser* parser, const char buf[])
-{
- TiXmlDocument doc;
-
- (void)doc.Parse(buf);
- if (doc.Error())
- {
- printf("tinyxml error: <%s> row[%d] col[%d]\n", doc.ErrorDesc(), doc.ErrorRow(), doc.ErrorCol());
- return false;
- }
-
- walk_elem(parser, doc.RootElement());
- return true;
-}
-
-bool SkXMLParser::parse(SkStream& stream)
-{
- size_t size = stream.getLength();
-
- SkAutoMalloc buffer(size + 1);
- char* buf = (char*)buffer.get();
-
- stream.read(buf, size);
- buf[size] = 0;
-
- return load_buf(this, buf);
-}
-
-bool SkXMLParser::parse(const char doc[], size_t len)
-{
- SkAutoMalloc buffer(len + 1);
- char* buf = (char*)buffer.get();
-
- memcpy(buf, doc, len);
- buf[len] = 0;
-
- return load_buf(this, buf);
-}
-
-void SkXMLParser::GetNativeErrorString(int error, SkString* str)
-{
- if (str)
- str->set("GetNativeErrorString not implemented for TinyXml");
-}
+++ /dev/null
-
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include "SkXMLParser.h"
-#include "SkChunkAlloc.h"
-#include "SkString.h"
-#include "SkStream.h"
-
-#include "expat.h"
-
-static inline char* dupstr(SkChunkAlloc& chunk, const char src[], size_t len)
-{
- SkASSERT(src);
- char* dst = (char*)chunk.alloc(len + 1, SkChunkAlloc::kThrow_AllocFailType);
-
- memcpy(dst, src, len);
- dst[len] = 0;
- return dst;
-}
-
-static inline int count_pairs(const char** p)
-{
- const char** start = p;
- while (*p)
- {
- SkASSERT(p[1] != NULL);
- p += 2;
- }
- return (p - start) >> 1;
-}
-
-struct Data {
- Data() : fAlloc(2048), fState(NORMAL) {}
-
- XML_Parser fParser;
- SkXMLPullParser::Curr* fCurr;
- SkChunkAlloc fAlloc;
-
- enum State {
- NORMAL,
- MISSED_START_TAG,
- RETURN_END_TAG
- };
- State fState;
- const char* fEndTag; // if state is RETURN_END_TAG
-};
-
-static void XMLCALL start_proc(void *data, const char *el, const char **attr)
-{
- Data* p = (Data*)data;
- SkXMLPullParser::Curr* c = p->fCurr;
- SkChunkAlloc& alloc = p->fAlloc;
-
- c->fName = dupstr(alloc, el, strlen(el));
-
- int n = count_pairs(attr);
- SkXMLPullParser::AttrInfo* info = (SkXMLPullParser::AttrInfo*)alloc.alloc(n * sizeof(SkXMLPullParser::AttrInfo),
- SkChunkAlloc::kThrow_AllocFailType);
- c->fAttrInfoCount = n;
- c->fAttrInfos = info;
-
- for (int i = 0; i < n; i++)
- {
- info[i].fName = dupstr(alloc, attr[0], strlen(attr[0]));
- info[i].fValue = dupstr(alloc, attr[1], strlen(attr[1]));
- attr += 2;
- }
-
- c->fEventType = SkXMLPullParser::START_TAG;
- XML_StopParser(p->fParser, true);
-}
-
-static void XMLCALL end_proc(void *data, const char *el)
-{
- Data* p = (Data*)data;
- SkXMLPullParser::Curr* c = p->fCurr;
-
- if (c->fEventType == SkXMLPullParser::START_TAG)
- {
- /* if we get here, we were called with a start_tag immediately
- followed by this end_tag. The caller will only see the end_tag,
- so we set a flag to notify them of the missed start_tag
- */
- p->fState = Data::MISSED_START_TAG;
-
- SkASSERT(c->fName != NULL);
- SkASSERT(strcmp(c->fName, el) == 0);
- }
- else
- c->fName = dupstr(p->fAlloc, el, strlen(el));
-
- c->fEventType = SkXMLPullParser::END_TAG;
- XML_StopParser(p->fParser, true);
-}
-
-#include <ctype.h>
-
-static bool isws(const char s[])
-{
- for (; *s; s++)
- if (!isspace(*s))
- return false;
- return true;
-}
-
-static void XMLCALL text_proc(void* data, const char* text, int len)
-{
- Data* p = (Data*)data;
- SkXMLPullParser::Curr* c = p->fCurr;
-
- c->fName = dupstr(p->fAlloc, text, len);
- c->fIsWhitespace = isws(c->fName);
-
- c->fEventType = SkXMLPullParser::TEXT;
- XML_StopParser(p->fParser, true);
-}
-
-//////////////////////////////////////////////////////////////////////////
-
-struct SkXMLPullParser::Impl {
- Data fData;
- void* fBuffer;
- size_t fBufferLen;
-};
-
-static void reportError(XML_Parser parser)
-{
- XML_Error code = XML_GetErrorCode(parser);
- int lineNumber = XML_GetCurrentLineNumber(parser);
- const char* msg = XML_ErrorString(code);
-
- printf("-------- XML error [%d] on line %d, %s\n", code, lineNumber, msg);
-}
-
-bool SkXMLPullParser::onInit()
-{
- fImpl = new Impl;
-
- XML_Parser p = XML_ParserCreate(NULL);
- SkASSERT(p);
-
- fImpl->fData.fParser = p;
- fImpl->fData.fCurr = &fCurr;
-
- XML_SetElementHandler(p, start_proc, end_proc);
- XML_SetCharacterDataHandler(p, text_proc);
- XML_SetUserData(p, &fImpl->fData);
-
- size_t len = fStream->getLength();
- fImpl->fBufferLen = len;
- fImpl->fBuffer = sk_malloc_throw(len);
- fStream->rewind();
- size_t len2 = fStream->read(fImpl->fBuffer, len);
- return len2 == len;
-}
-
-void SkXMLPullParser::onExit()
-{
- sk_free(fImpl->fBuffer);
- XML_ParserFree(fImpl->fData.fParser);
- delete fImpl;
- fImpl = NULL;
-}
-
-SkXMLPullParser::EventType SkXMLPullParser::onNextToken()
-{
- if (Data::RETURN_END_TAG == fImpl->fData.fState)
- {
- fImpl->fData.fState = Data::NORMAL;
- fCurr.fName = fImpl->fData.fEndTag; // restore name from (below) save
- return SkXMLPullParser::END_TAG;
- }
-
- fImpl->fData.fAlloc.reset();
-
- XML_Parser p = fImpl->fData.fParser;
- XML_Status status;
-
- status = XML_ResumeParser(p);
-
-CHECK_STATUS:
- switch (status) {
- case XML_STATUS_OK:
- return SkXMLPullParser::END_DOCUMENT;
-
- case XML_STATUS_ERROR:
- if (XML_GetErrorCode(p) != XML_ERROR_NOT_SUSPENDED)
- {
- reportError(p);
- return SkXMLPullParser::ERROR;
- }
- status = XML_Parse(p, (const char*)fImpl->fBuffer, fImpl->fBufferLen, true);
- goto CHECK_STATUS;
-
- case XML_STATUS_SUSPENDED:
- if (Data::MISSED_START_TAG == fImpl->fData.fState)
- {
- // return a start_tag, and clear the flag so we return end_tag next
- SkASSERT(SkXMLPullParser::END_TAG == fCurr.fEventType);
- fImpl->fData.fState = Data::RETURN_END_TAG;
- fImpl->fData.fEndTag = fCurr.fName; // save this pointer
- return SkXMLPullParser::START_TAG;
- }
- break;
- }
- return fCurr.fEventType;
-}