Index: src/gpu/gl/GrGLPathRendering.cpp |
diff --git a/src/gpu/gl/GrGLPathRendering.cpp b/src/gpu/gl/GrGLPathRendering.cpp |
index 81d47c4722591e96a5e9253785639c63a66761c5..2fe9758c8a469a8a5e03fc0f509a9cbe60989de1 100644 |
--- a/src/gpu/gl/GrGLPathRendering.cpp |
+++ b/src/gpu/gl/GrGLPathRendering.cpp |
@@ -14,6 +14,9 @@ |
#include "GrGLPathRange.h" |
#include "GrGLPathRendering.h" |
+#include "SkStream.h" |
+#include "SkTypeface.h" |
+ |
#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X) |
#define GL_CALL_RET(RET, X) GR_GL_CALL_RET(fGpu->glInterface(), RET, X) |
@@ -93,8 +96,59 @@ GrPath* GrGLPathRendering::createPath(const SkPath& inPath, const SkStrokeRec& s |
return SkNEW_ARGS(GrGLPath, (fGpu, inPath, stroke)); |
} |
-GrPathRange* GrGLPathRendering::createPathRange(size_t size, const SkStrokeRec& stroke) { |
- return SkNEW_ARGS(GrGLPathRange, (fGpu, size, stroke)); |
+GrPathRange* GrGLPathRendering::createPathRange(GrPathRange::PathGenerator* pathGenerator, |
+ const SkStrokeRec& stroke) { |
+ return SkNEW_ARGS(GrGLPathRange, (fGpu, pathGenerator, stroke)); |
+} |
+ |
+GrPathRange* GrGLPathRendering::createGlyphs(const SkTypeface* typeface, |
+ const SkDescriptor* desc, |
+ const SkStrokeRec& stroke) { |
+ if (NULL != desc || !caps().glyphLoadingSupport) { |
+ return GrPathRendering::createGlyphs(typeface, desc, stroke); |
+ } |
+ |
+ if (NULL == typeface) { |
+ typeface = SkTypeface::GetDefaultTypeface(); |
+ SkASSERT(NULL != typeface); |
+ } |
+ |
+ int faceIndex; |
+ SkAutoTUnref<SkStream> fontStream(typeface->openStream(&faceIndex)); |
+ |
+ const size_t fontDataLength = fontStream->getLength(); |
+ if (0 == fontDataLength) { |
+ return GrPathRendering::createGlyphs(typeface, NULL, stroke); |
+ } |
+ |
+ SkTArray<uint8_t> fontTempBuffer; |
+ const void* fontData = fontStream->getMemoryBase(); |
+ if (NULL == fontData) { |
+ // TODO: Find a more efficient way to pass the font data (e.g. open file descriptor). |
+ fontTempBuffer.reset(fontDataLength); |
+ fontStream->read(&fontTempBuffer.front(), fontDataLength); |
+ fontData = &fontTempBuffer.front(); |
+ } |
+ |
+ const size_t numPaths = typeface->countGlyphs(); |
+ const GrGLuint basePathID = this->genPaths(numPaths); |
+ |
+ GrGLenum status; |
+ GL_CALL_RET(status, PathMemoryGlyphIndexArray(basePathID, GR_GL_STANDARD_FONT_FORMAT, |
+ fontDataLength, fontData, faceIndex, 0, numPaths, |
+ GrGLPath(fGpu, SkPath(), stroke).pathID(), |
+ SkPaint::kCanonicalTextSizeForPaths)); |
+ |
+ if (GR_GL_FONT_GLYPHS_AVAILABLE != status) { |
+ this->deletePaths(basePathID, numPaths); |
+ return GrPathRendering::createGlyphs(typeface, NULL, stroke); |
+ } |
+ |
+ // This is a crude approximation. We may want to consider giving this class |
+ // a pseudo PathGenerator whose sole purpose is to track the approximate gpu |
+ // memory size. |
+ const size_t gpuMemorySize = fontDataLength / 4; |
+ return SkNEW_ARGS(GrGLPathRange, (fGpu, basePathID, numPaths, gpuMemorySize, stroke)); |
} |
void GrGLPathRendering::stencilPath(const GrPath* path, SkPath::FillType fill) { |