Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(161)

Side by Side Diff: src/device/xps/SkXPSDevice.cpp

Issue 1471043002: Change XPS to use find and place glyph. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix warning Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkTypes.h" 8 #include "SkTypes.h"
9 #if defined(SK_BUILD_FOR_WIN32) 9 #if defined(SK_BUILD_FOR_WIN32)
10 10
11 #ifndef UNICODE 11 #ifndef UNICODE
12 #define UNICODE 12 #define UNICODE
13 #endif 13 #endif
14 #ifndef _UNICODE 14 #ifndef _UNICODE
15 #define _UNICODE 15 #define _UNICODE
16 #endif 16 #endif
17 #include <ObjBase.h> 17 #include <ObjBase.h>
18 #include <XpsObjectModel.h> 18 #include <XpsObjectModel.h>
19 #include <T2EmbApi.h> 19 #include <T2EmbApi.h>
20 #include <FontSub.h> 20 #include <FontSub.h>
21 21
22 #include "SkColor.h" 22 #include "SkColor.h"
23 #include "SkConstexprMath.h" 23 #include "SkConstexprMath.h"
24 #include "SkData.h" 24 #include "SkData.h"
25 #include "SkDraw.h" 25 #include "SkDraw.h"
26 #include "SkDrawProcs.h" 26 #include "SkDrawProcs.h"
27 #include "SkEndian.h" 27 #include "SkEndian.h"
28 #include "SkFindAndPlaceGlyph.h"
28 #include "SkGeometry.h" 29 #include "SkGeometry.h"
29 #include "SkGlyphCache.h" 30 #include "SkGlyphCache.h"
30 #include "SkHRESULT.h" 31 #include "SkHRESULT.h"
31 #include "SkImageEncoder.h" 32 #include "SkImageEncoder.h"
32 #include "SkIStream.h" 33 #include "SkIStream.h"
33 #include "SkMaskFilter.h" 34 #include "SkMaskFilter.h"
34 #include "SkPaint.h" 35 #include "SkPaint.h"
35 #include "SkPathOps.h" 36 #include "SkPathOps.h"
36 #include "SkPoint.h" 37 #include "SkPoint.h"
37 #include "SkRasterizer.h" 38 #include "SkRasterizer.h"
(...skipping 1999 matching lines...) Expand 10 before | Expand all | Expand 10 after
2037 "Could not add glyphs to page."); 2038 "Could not add glyphs to page.");
2038 HR(this->clip(glyphCanvas.get(), d)); 2039 HR(this->clip(glyphCanvas.get(), d));
2039 2040
2040 HRM(visuals->Append(glyphCanvas.get()), 2041 HRM(visuals->Append(glyphCanvas.get()),
2041 "Could not add glyph canvas to page."); 2042 "Could not add glyph canvas to page.");
2042 } 2043 }
2043 2044
2044 return S_OK; 2045 return S_OK;
2045 } 2046 }
2046 2047
2047 struct SkXPSDrawProcs : public SkDrawProcs { 2048 static int num_glyph_guess(SkPaint::TextEncoding encoding, const void* text, siz e_t byteLength) {
2048 public: 2049 switch (encoding) {
2049 /** [in] Advance width and offsets for glyphs measured in 2050 case SkPaint::kUTF8_TextEncoding:
2050 hundredths of the font em size (XPS Spec 5.1.3). */ 2051 return SkUTF8_CountUnichars(static_cast<const char *>(text), byteLength) ;
2051 FLOAT centemPerUnit; 2052 case SkPaint::kUTF16_TextEncoding:
2052 /** [in,out] The accumulated glyphs used in the current typeface. */ 2053 return SkUTF16_CountUnichars(static_cast<const uint16_t *>(text), SkToIn t(byteLength));
2053 SkBitSet* glyphUse; 2054 case SkPaint::kGlyphID_TextEncoding:
2054 /** [out] The glyphs to draw. */ 2055 return SkToInt(byteLength / 2);
2055 SkTDArray<XPS_GLYPH_INDEX> xpsGlyphs; 2056 default:
2056 }; 2057 SK_ALWAYSBREAK(true);
2057
2058 static void xps_draw_1_glyph(const SkDraw1Glyph& state,
2059 Sk48Dot16 fx, Sk48Dot16 fy,
2060 const SkGlyph& skGlyph) {
2061 SkASSERT(skGlyph.fWidth > 0 && skGlyph.fHeight > 0);
2062
2063 SkXPSDrawProcs* procs = static_cast<SkXPSDrawProcs*>(state.fDraw->fProcs);
2064
2065 //Draw pre-adds half the sampling frequency for floor rounding.
2066 SkScalar x = Sk48Dot16ToScalar(fx) - state.fHalfSampleX;
2067 SkScalar y = Sk48Dot16ToScalar(fy) - state.fHalfSampleY;
2068
2069 XPS_GLYPH_INDEX* xpsGlyph = procs->xpsGlyphs.append();
2070 uint16_t glyphID = skGlyph.getGlyphID();
2071 procs->glyphUse->setBit(glyphID, true);
2072 xpsGlyph->index = glyphID;
2073 if (1 == procs->xpsGlyphs.count()) {
2074 xpsGlyph->advanceWidth = 0.0f;
2075 xpsGlyph->horizontalOffset = SkScalarToFloat(x) * procs->centemPerUnit;
2076 xpsGlyph->verticalOffset = SkScalarToFloat(y) * -procs->centemPerUnit;
2077 } else {
2078 const XPS_GLYPH_INDEX& first = procs->xpsGlyphs[0];
2079 xpsGlyph->advanceWidth = 0.0f;
2080 xpsGlyph->horizontalOffset = (SkScalarToFloat(x) * procs->centemPerUnit)
2081 - first.horizontalOffset;
2082 xpsGlyph->verticalOffset = (SkScalarToFloat(y) * -procs->centemPerUnit)
2083 - first.verticalOffset;
2084 } 2058 }
2085 } 2059 return 0;
2086
2087 static void text_draw_init(const SkPaint& paint,
2088 const void* text, size_t byteLength,
2089 SkBitSet& glyphsUsed,
2090 SkDraw& myDraw, SkXPSDrawProcs& procs) {
2091 procs.fD1GProc = xps_draw_1_glyph;
2092 int numGlyphGuess;
2093 switch (paint.getTextEncoding()) {
2094 case SkPaint::kUTF8_TextEncoding:
2095 numGlyphGuess = SkUTF8_CountUnichars(
2096 static_cast<const char *>(text),
2097 byteLength);
2098 break;
2099 case SkPaint::kUTF16_TextEncoding:
2100 numGlyphGuess = SkUTF16_CountUnichars(
2101 static_cast<const uint16_t *>(text),
2102 SkToInt(byteLength));
2103 break;
2104 case SkPaint::kGlyphID_TextEncoding:
2105 numGlyphGuess = SkToInt(byteLength / 2);
2106 break;
2107 default:
2108 SK_ALWAYSBREAK(true);
2109 }
2110 procs.xpsGlyphs.setReserve(numGlyphGuess);
2111 procs.glyphUse = &glyphsUsed;
2112 procs.centemPerUnit = 100.0f / SkScalarToFLOAT(paint.getTextSize());
2113
2114 myDraw.fProcs = &procs;
2115 } 2060 }
2116 2061
2117 static bool text_must_be_pathed(const SkPaint& paint, const SkMatrix& matrix) { 2062 static bool text_must_be_pathed(const SkPaint& paint, const SkMatrix& matrix) {
2118 const SkPaint::Style style = paint.getStyle(); 2063 const SkPaint::Style style = paint.getStyle();
2119 return matrix.hasPerspective() 2064 return matrix.hasPerspective()
2120 || SkPaint::kStroke_Style == style 2065 || SkPaint::kStroke_Style == style
2121 || SkPaint::kStrokeAndFill_Style == style 2066 || SkPaint::kStrokeAndFill_Style == style
2122 || paint.getMaskFilter() 2067 || paint.getMaskFilter()
2123 || paint.getRasterizer() 2068 || paint.getRasterizer()
2124 ; 2069 ;
2125 } 2070 }
2126 2071
2072 typedef SkTDArray<XPS_GLYPH_INDEX> GlyphRun;
2073
2074 class ProcessOneGlyph {
2075 public:
2076 ProcessOneGlyph(FLOAT centemPerUnit, SkBitSet* glyphUse, GlyphRun* xpsGlyphs )
2077 : fCentemPerUnit(centemPerUnit)
2078 , fGlyphUse(glyphUse)
2079 , fXpsGlyphs(xpsGlyphs) { }
2080
2081 void operator()(const SkGlyph& glyph, SkPoint position, SkPoint) {
2082 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
2083
2084 SkScalar x = position.fX;
2085 SkScalar y = position.fY;
2086
2087 XPS_GLYPH_INDEX* xpsGlyph = fXpsGlyphs->append();
2088 uint16_t glyphID = glyph.getGlyphID();
2089 fGlyphUse->setBit(glyphID, true);
2090 xpsGlyph->index = glyphID;
2091 if (1 == fXpsGlyphs->count()) {
2092 xpsGlyph->advanceWidth = 0.0f;
2093 xpsGlyph->horizontalOffset = SkScalarToFloat(x) * fCentemPerUnit;
2094 xpsGlyph->verticalOffset = SkScalarToFloat(y) * -fCentemPerUnit;
2095 }
2096 else {
2097 const XPS_GLYPH_INDEX& first = (*fXpsGlyphs)[0];
2098 xpsGlyph->advanceWidth = 0.0f;
2099 xpsGlyph->horizontalOffset = (SkScalarToFloat(x) * fCentemPerUnit)
2100 - first.horizontalOffset;
2101 xpsGlyph->verticalOffset = (SkScalarToFloat(y) * -fCentemPerUnit)
2102 - first.verticalOffset;
2103 }
2104 }
2105
2106 private:
2107 /** [in] Advance width and offsets for glyphs measured in
2108 hundredths of the font em size (XPS Spec 5.1.3). */
2109 const FLOAT fCentemPerUnit;
2110 /** [in,out] The accumulated glyphs used in the current typeface. */
2111 SkBitSet* const fGlyphUse;
2112 /** [out] The glyphs to draw. */
2113 GlyphRun* const fXpsGlyphs;
2114 };
2115
2127 void SkXPSDevice::drawText(const SkDraw& d, 2116 void SkXPSDevice::drawText(const SkDraw& d,
2128 const void* text, size_t byteLen, 2117 const void* text, size_t byteLen,
2129 SkScalar x, SkScalar y, 2118 SkScalar x, SkScalar y,
2130 const SkPaint& paint) { 2119 const SkPaint& paint) {
2131 if (byteLen < 1) return; 2120 if (byteLen < 1) return;
2132 2121
2133 if (text_must_be_pathed(paint, *d.fMatrix)) { 2122 if (text_must_be_pathed(paint, *d.fMatrix)) {
2134 SkPath path; 2123 SkPath path;
2135 paint.getTextPath(text, byteLen, x, y, &path); 2124 paint.getTextPath(text, byteLen, x, y, &path);
2136 this->drawPath(d, path, paint, nullptr, true); 2125 this->drawPath(d, path, paint, nullptr, true);
2137 //TODO: add automation "text" 2126 //TODO: add automation "text"
2138 return; 2127 return;
2139 } 2128 }
2140 2129
2141 TypefaceUse* typeface; 2130 TypefaceUse* typeface;
2142 HRV(CreateTypefaceUse(paint, &typeface)); 2131 HRV(CreateTypefaceUse(paint, &typeface));
2143 2132
2144 SkDraw myDraw(d); 2133 const SkMatrix& matrix = SkMatrix::I();
2145 myDraw.fMatrix = &SkMatrix::I();
2146 SkXPSDrawProcs procs;
2147 text_draw_init(paint, text, byteLen, *typeface->glyphsUsed, myDraw, procs);
2148 2134
2149 myDraw.drawText(static_cast<const char*>(text), byteLen, x, y, paint); 2135 SkAutoGlyphCache autoCache(paint, &this->surfaceProps(), &matrix);
2136 SkGlyphCache* cache = autoCache.getCache();
2150 2137
2151 // SkDraw may have clipped out the glyphs, so we need to check 2138 // Advance width and offsets for glyphs measured in hundredths of the font e m size
2152 if (procs.xpsGlyphs.count() == 0) { 2139 // (XPS Spec 5.1.3).
2140 FLOAT centemPerUnit = 100.0f / SkScalarToFLOAT(paint.getTextSize());
2141 GlyphRun xpsGlyphs;
2142 xpsGlyphs.setReserve(num_glyph_guess(paint.getTextEncoding(),
2143 static_cast<const char*>(text), byteLen));
2144
2145 ProcessOneGlyph processOneGlyph(centemPerUnit, typeface->glyphsUsed, &xpsGly phs);
2146
2147 SkFindAndPlaceGlyph::ProcessText(
2148 paint.getTextEncoding(), static_cast<const char*>(text), byteLen,
2149 SkPoint{ x, y }, matrix, paint.getTextAlign(), cache, processOneGlyph);
2150
2151 if (xpsGlyphs.count() == 0) {
2153 return; 2152 return;
2154 } 2153 }
2155 2154
2156 XPS_POINT origin = { 2155 XPS_POINT origin = {
2157 procs.xpsGlyphs[0].horizontalOffset / procs.centemPerUnit, 2156 xpsGlyphs[0].horizontalOffset / centemPerUnit,
2158 procs.xpsGlyphs[0].verticalOffset / -procs.centemPerUnit, 2157 xpsGlyphs[0].verticalOffset / -centemPerUnit,
2159 }; 2158 };
2160 procs.xpsGlyphs[0].horizontalOffset = 0.0f; 2159 xpsGlyphs[0].horizontalOffset = 0.0f;
2161 procs.xpsGlyphs[0].verticalOffset = 0.0f; 2160 xpsGlyphs[0].verticalOffset = 0.0f;
2162 2161
2163 HRV(AddGlyphs(d, 2162 HRV(AddGlyphs(d,
2164 this->fXpsFactory.get(), 2163 this->fXpsFactory.get(),
2165 this->fCurrentXpsCanvas.get(), 2164 this->fCurrentXpsCanvas.get(),
2166 typeface, 2165 typeface,
2167 nullptr, 2166 nullptr,
2168 procs.xpsGlyphs.begin(), procs.xpsGlyphs.count(), 2167 xpsGlyphs.begin(), xpsGlyphs.count(),
2169 &origin, 2168 &origin,
2170 SkScalarToFLOAT(paint.getTextSize()), 2169 SkScalarToFLOAT(paint.getTextSize()),
2171 XPS_STYLE_SIMULATION_NONE, 2170 XPS_STYLE_SIMULATION_NONE,
2172 *d.fMatrix, 2171 *d.fMatrix,
2173 paint)); 2172 paint));
2174 } 2173 }
2175 2174
2176 void SkXPSDevice::drawPosText(const SkDraw& d, 2175 void SkXPSDevice::drawPosText(const SkDraw& d,
2177 const void* text, size_t byteLen, 2176 const void* text, size_t byteLen,
2178 const SkScalar pos[], int scalarsPerPos, 2177 const SkScalar pos[], int scalarsPerPos,
2179 const SkPoint& offset, const SkPaint& paint) { 2178 const SkPoint& offset, const SkPaint& paint) {
2180 if (byteLen < 1) return; 2179 if (byteLen < 1) return;
2181 2180
2182 if (text_must_be_pathed(paint, *d.fMatrix)) { 2181 if (text_must_be_pathed(paint, *d.fMatrix)) {
2183 SkPath path; 2182 SkPath path;
2184 //TODO: make this work, Draw currently does not handle as well. 2183 //TODO: make this work, Draw currently does not handle as well.
2185 //paint.getTextPath(text, byteLength, x, y, &path); 2184 //paint.getTextPath(text, byteLength, x, y, &path);
2186 //this->drawPath(d, path, paint, nullptr, true); 2185 //this->drawPath(d, path, paint, nullptr, true);
2187 //TODO: add automation "text" 2186 //TODO: add automation "text"
2188 return; 2187 return;
2189 } 2188 }
2190 2189
2191 TypefaceUse* typeface; 2190 TypefaceUse* typeface;
2192 HRV(CreateTypefaceUse(paint, &typeface)); 2191 HRV(CreateTypefaceUse(paint, &typeface));
2193 2192
2194 SkDraw myDraw(d); 2193 const SkMatrix& matrix = SkMatrix::I();
2195 myDraw.fMatrix = &SkMatrix::I();
2196 SkXPSDrawProcs procs;
2197 text_draw_init(paint, text, byteLen, *typeface->glyphsUsed, myDraw, procs);
2198 2194
2199 myDraw.drawPosText(static_cast<const char*>(text), byteLen, pos, scalarsPerP os, offset, paint); 2195 SkAutoGlyphCache autoCache(paint, &this->surfaceProps(), &matrix);
2196 SkGlyphCache* cache = autoCache.getCache();
2200 2197
2201 // SkDraw may have clipped out the glyphs, so we need to check 2198 // Advance width and offsets for glyphs measured in hundredths of the font e m size
2202 if (procs.xpsGlyphs.count() == 0) { 2199 // (XPS Spec 5.1.3).
2200 FLOAT centemPerUnit = 100.0f / SkScalarToFLOAT(paint.getTextSize());
2201 GlyphRun xpsGlyphs;
2202 xpsGlyphs.setReserve(num_glyph_guess(paint.getTextEncoding(),
2203 static_cast<const char*>(text), byteLen));
2204
2205 ProcessOneGlyph processOneGlyph(centemPerUnit, typeface->glyphsUsed, &xpsGly phs);
2206
2207 SkFindAndPlaceGlyph::ProcessPosText(
2208 paint.getTextEncoding(), static_cast<const char*>(text), byteLen,
2209 offset, matrix, pos, scalarsPerPos, paint.getTextAlign(), cache, process OneGlyph);
2210
2211 if (xpsGlyphs.count() == 0) {
2203 return; 2212 return;
2204 } 2213 }
2205 2214
2206 XPS_POINT origin = { 2215 XPS_POINT origin = {
2207 procs.xpsGlyphs[0].horizontalOffset / procs.centemPerUnit, 2216 xpsGlyphs[0].horizontalOffset / centemPerUnit,
2208 procs.xpsGlyphs[0].verticalOffset / -procs.centemPerUnit, 2217 xpsGlyphs[0].verticalOffset / -centemPerUnit,
2209 }; 2218 };
2210 procs.xpsGlyphs[0].horizontalOffset = 0.0f; 2219 xpsGlyphs[0].horizontalOffset = 0.0f;
2211 procs.xpsGlyphs[0].verticalOffset = 0.0f; 2220 xpsGlyphs[0].verticalOffset = 0.0f;
2212 2221
2213 HRV(AddGlyphs(d, 2222 HRV(AddGlyphs(d,
2214 this->fXpsFactory.get(), 2223 this->fXpsFactory.get(),
2215 this->fCurrentXpsCanvas.get(), 2224 this->fCurrentXpsCanvas.get(),
2216 typeface, 2225 typeface,
2217 nullptr, 2226 nullptr,
2218 procs.xpsGlyphs.begin(), procs.xpsGlyphs.count(), 2227 xpsGlyphs.begin(), xpsGlyphs.count(),
2219 &origin, 2228 &origin,
2220 SkScalarToFLOAT(paint.getTextSize()), 2229 SkScalarToFLOAT(paint.getTextSize()),
2221 XPS_STYLE_SIMULATION_NONE, 2230 XPS_STYLE_SIMULATION_NONE,
2222 *d.fMatrix, 2231 *d.fMatrix,
2223 paint)); 2232 paint));
2224 } 2233 }
2225 2234
2226 void SkXPSDevice::drawDevice(const SkDraw& d, SkBaseDevice* dev, 2235 void SkXPSDevice::drawDevice(const SkDraw& d, SkBaseDevice* dev,
2227 int x, int y, 2236 int x, int y,
2228 const SkPaint&) { 2237 const SkPaint&) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2260 //SkXPSDevice* dev = new SkXPSDevice(this); 2269 //SkXPSDevice* dev = new SkXPSDevice(this);
2261 //SkSize s = SkSize::Make(width, height); 2270 //SkSize s = SkSize::Make(width, height);
2262 //dev->BeginCanvas(s, s, SkMatrix::I()); 2271 //dev->BeginCanvas(s, s, SkMatrix::I());
2263 //return dev; 2272 //return dev;
2264 } 2273 }
2265 #endif 2274 #endif
2266 return new SkXPSDevice(this->fXpsFactory.get()); 2275 return new SkXPSDevice(this->fXpsFactory.get());
2267 } 2276 }
2268 2277
2269 #endif//defined(SK_BUILD_FOR_WIN32) 2278 #endif//defined(SK_BUILD_FOR_WIN32)
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698