OLD | NEW |
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 Loading... |
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 Loading... |
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) |
OLD | NEW |