| 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 |