/// <summary> /// Initializes this reader to decode the naming table of the supplied font. /// </summary> /// <param name="openType">The font to decode.</param> public void Setup(OpenType openType) { this.openType = openType; name = openType.GetName(); index = -1; count = openType.ReadUInt16(name, 2); stringOffset = name.offset + openType.ReadUInt16(name, 4); }
private void Reset() { if (subrStackIndex > 0) { charString = subrStack[0]; } cursor = 0; stackIndex = 0; subrStackIndex = 0; inHeader = true; maskBits = 0; x = 0; y = 0; i = 0; instruction = 0; sx = 0; sy = 0; }
internal override bool Setup(OpenType openType, double pixelSize, uint glyphIndex) { Reset(); if (openType.GetGlyphOutlineKind() != GlyphOutlineKind.Cff) { throw new ArgumentException(nameof(openType)); } this.openType = openType; globalSubrs = openType.GetGlobalSubrs(); subrs = openType.GetGlyphSubrs(glyphIndex); charString = openType.GetCharString(glyphIndex); Scale = pixelSize / openType.GetUnitsPerEm(); bool first = true; XMin = 0; XMax = 0; YMin = 0; YMax = 0; while (Move()) { if (first) { first = false; XMin = X; YMin = Y; XMax = X; YMax = Y; } else { if (X < XMin) { XMin = X; } else if (X > XMax) { XMax = X; } if (Y < YMin) { YMin = Y; } else if (Y > YMax) { YMax = Y; } } switch (PathCommand) { case PathCommand.MoveTo: break; case PathCommand.LineTo: break; case PathCommand.CubicBezierTo: if (Cx1 < XMin) { XMin = Cx1; } else if (Cx1 > XMax) { XMax = Cx1; } if (Cy1 < YMin) { YMin = Cy1; } else if (Cy1 > YMax) { YMax = Cy1; } goto case PathCommand.QuadraticBezierTo; case PathCommand.QuadraticBezierTo: if (Cx < XMin) { XMin = Cx; } else if (Cx > XMax) { XMax = Cx; } if (Cy < YMin) { YMin = Cy; } else if (Cy > YMax) { YMax = Cy; } break; } } Reset(); return(XMin != 0 || XMax != 0); }
internal override bool Move() { for (;;) { switch (instruction) { case 0x0E: // endchar return(false); case 0x04: // vmoveto sx = x; sy = y += stack[stackIndex - 1]; SetPath(PathCommand.MoveTo, x, y, 0, 0, 0, 0); instruction = 0; stackIndex = 0; return(true); case 0x15: // rmoveto sx = x += stack[stackIndex - 2]; sy = y += stack[stackIndex - 1]; SetPath(PathCommand.MoveTo, x, y, 0, 0, 0, 0); instruction = 0; stackIndex = 0; return(true); case 0x16: // hmoveto sx = x += stack[stackIndex - 1]; sy = y; SetPath(PathCommand.MoveTo, x, y, 0, 0, 0, 0); instruction = 0; stackIndex = 0; return(true); case 0x05: // rlineto x += stack[i]; y += stack[i + 1]; i += 2; SetPath(PathCommand.LineTo, x, y, 0, 0, 0, 0); if (i + 1 < stackIndex) { instruction = 0x05; } else { instruction = 0; stackIndex = 0; } return(true); case 0x06: // hlineto x += stack[i++]; SetPath(PathCommand.LineTo, x, y, 0, 0, 0, 0); if (i < stackIndex) { instruction = 0x07; } else { instruction = 0; stackIndex = 0; } return(true); case 0x07: // vlineto y += stack[i++]; SetPath(PathCommand.LineTo, x, y, 0, 0, 0, 0); if (i < stackIndex) { instruction = 0x06; } else { instruction = 0; stackIndex = 0; } return(true); case 0x1E: // vhcurveto SetCurveTo(0, stack[i], stack[i + 1], stack[i + 2], stack[i + 3], (stackIndex - i == 5) ? stack[i + 4] : 0d); i += 4; if (i + 3 < stackIndex) { instruction = 0x1F; } else { instruction = 0; stackIndex = 0; } return(true); case 0x1F: // hvcurveto SetCurveTo(stack[i], 0, stack[i + 1], stack[i + 2], (stackIndex - i == 5) ? stack[i + 4] : 0d, stack[i + 3]); i += 4; if (i + 3 < stackIndex) { instruction = 0x1E; } else { instruction = 0; stackIndex = 0; } return(true); case 0x08: // rrcurveto SetCurveTo(stack[i], stack[i + 1], stack[i + 2], stack[i + 3], stack[i + 4], stack[i + 5]); i += 6; if (i + 5 < stackIndex) { instruction = 0x08; } else { instruction = 0; stackIndex = 0; } return(true); case 0x18: // rcurveline if (i + 5 < stackIndex - 2) { SetCurveTo(stack[i], stack[i + 1], stack[i + 2], stack[i + 3], stack[i + 4], stack[i + 5]); i += 6; return(true); } else { x += stack[i]; y += stack[i + 1]; SetPath(PathCommand.LineTo, x, y, 0, 0, 0, 0); instruction = 0; stackIndex = 0; return(true); } case 0x19: // rlinecurve if (i + 1 < stackIndex - 6) { x += stack[i]; y += stack[i + 1]; i += 2; SetPath(PathCommand.LineTo, x, y, 0, 0, 0, 0); return(true); } else { SetCurveTo(stack[i], stack[i + 1], stack[i + 2], stack[i + 3], stack[i + 4], stack[i + 5]); instruction = 0; stackIndex = 0; return(true); } case 0x1A: // vvcurveto SetCurveTo(0d, stack[i], stack[i + 1], stack[i + 2], 0d, stack[i + 3]); i += 4; if (i + 3 < stackIndex) { instruction = 0x1A; } else { instruction = 0; stackIndex = 0; } return(true); case 0x1B: // hhcurveto SetCurveTo(stack[i], 0d, stack[i + 1], stack[i + 2], stack[i + 3], 0d); i += 4; if (i + 3 < stackIndex) { instruction = 0x1B; } else { instruction = 0; stackIndex = 0; } return(true); case 0x22: // hflex SetCurveTo(dx4, 0d, dx5, -dy2, dx6, 0d); instruction = 0; stackIndex = 0; return(true); case 0x23: // flex SetCurveTo(dx4, dy4, dx5, dy5, dx6, dy6); instruction = 0; stackIndex = 0; return(true); case 0x24: // hflex1 SetCurveTo(dx4, 0, dx5, dy5, dx6, -(dy1 + dy2 + dy5)); instruction = 0; stackIndex = 0; return(true); case 0x25: // flex1 SetCurveTo(dx4, dy4, dx5, dy5, dx6, dy6); instruction = 0; stackIndex = 0; return(true); } bool exit = false; while (cursor < charString.length && !exit) { i = 0; clearStack = true; instruction = 0; uint b0 = openType !.ReadByte(charString, cursor++); switch (b0) { case 0x01: // hstem case 0x03: // vstem case 0x12: // hstemhm case 0x17: // vstemhm maskBits += (stackIndex / 2); break; case 0x13: case 0x14: if (inHeader) { maskBits += (stackIndex / 2); inHeader = false; } cursor += (maskBits + 7) / 8; break; case 0x0E: // endchar if (x != sx || y != sy) { SetPath(PathCommand.LineTo, sx, sy, 0, 0, 0, 0); instruction = 0x0E; return(true); } return(false); case 0x04: // vmoveto case 0x15: // rmoveto case 0x16: // hmoveto inHeader = false; instruction = b0; if (x != sx || y != sy) { SetPath(PathCommand.LineTo, sx, sy, 0, 0, 0, 0); return(true); } clearStack = false; exit = true; break; case 0x05: // rlineto x += stack[i]; y += stack[i + 1]; i += 2; SetPath(PathCommand.LineTo, x, y, 0, 0, 0, 0); if (i + 1 < stackIndex) { instruction = 0x05; } else { stackIndex = 0; } return(true); case 0x06: // hlineto x += stack[i++]; SetPath(PathCommand.LineTo, x, y, 0, 0, 0, 0); if (i < stackIndex) { instruction = 0x07; } else { stackIndex = 0; } return(true); case 0x07: // vlineto y += stack[i++]; SetPath(PathCommand.LineTo, x, y, 0, 0, 0, 0); if (i < stackIndex) { instruction = 0x06; } else { stackIndex = 0; } return(true); case 0x1E: // vhcurveto SetCurveTo(0, stack[i], stack[i + 1], stack[i + 2], stack[i + 3], (stackIndex - i == 5) ? stack[i + 4] : 0d); i += 4; if (i + 3 < stackIndex) { instruction = 0x1F; } else { stackIndex = 0; } return(true); case 0x1F: // hvcurveto SetCurveTo(stack[i], 0, stack[i + 1], stack[i + 2], (stackIndex - i == 5) ? stack[i + 4] : 0f, stack[i + 3]); i += 4; if (i + 3 < stackIndex) { instruction = 0x1E; } else { stackIndex = 0; } return(true); case 0x08: // rrcurveto SetCurveTo(stack[i], stack[i + 1], stack[i + 2], stack[i + 3], stack[i + 4], stack[i + 5]); i += 6; if (i + 5 < stackIndex) { instruction = 0x08; } else { stackIndex = 0; } return(true); case 0x18: // rcurveline SetCurveTo(stack[i], stack[i + 1], stack[i + 2], stack[i + 3], stack[i + 4], stack[i + 5]); i += 6; instruction = 0x18; return(true); case 0x19: // rlinecurve x += stack[i]; y += stack[i + 1]; i += 2; SetPath(PathCommand.LineTo, x, y, 0, 0, 0, 0); instruction = 0x19; return(true); case 0x1A: // vvcurveto double f = ((stackIndex & 1) != 0) ? stack[i++] : 0d; SetCurveTo(f, stack[i], stack[i + 1], stack[i + 2], 0d, stack[i + 3]); i += 4; if (i + 3 < stackIndex) { instruction = 0x1A; } else { stackIndex = 0; } return(true); case 0x1B: // hhcurveto f = ((stackIndex & 1) != 0) ? stack[i++] : 0d; SetCurveTo(stack[i], f, stack[i + 1], stack[i + 2], stack[i + 3], 0d); i += 4; if (i + 3 < stackIndex) { instruction = 0x1B; } else { stackIndex = 0; } return(true); case 0x0A: // callsubr { if (subrStackIndex >= 10) { throw new InvalidOperationException(Resources.GetMessage(Resources.Key.SubrStackOverflow)); } uint v = (uint)stack[--stackIndex]; cursorStack[subrStackIndex] = cursor; subrStack[subrStackIndex++] = charString; charString = openType.GetSubr(subrs, v); cursor = 0; clearStack = false; } break; case 0x1D: // callgsubr { if (subrStackIndex >= 10) { throw new InvalidOperationException(Resources.GetMessage(Resources.Key.SubrStackOverflow)); } uint v = (uint)stack[--stackIndex]; cursorStack[subrStackIndex] = cursor; subrStack[subrStackIndex++] = charString; charString = openType.GetSubr(globalSubrs, v); cursor = 0; clearStack = false; } break; case 0x0B: // return charString = subrStack[--subrStackIndex]; cursor = cursorStack[subrStackIndex]; clearStack = false; break; case 0x0C: // two-byte escape { uint b1 = openType.ReadByte(charString, cursor++); switch (b1) { case 0x22: // hflex dx1 = stack[0]; dx2 = stack[1]; dy2 = stack[2]; dx3 = stack[3]; dx4 = stack[4]; dx5 = stack[5]; dx6 = stack[6]; SetCurveTo(dx1, 0, dx2, dy2, dx3, 0); instruction = 0x22; return(true); case 0x23: // flex dx1 = stack[0]; dy1 = stack[1]; dx2 = stack[2]; dy2 = stack[3]; dx3 = stack[4]; dy3 = stack[5]; dx4 = stack[6]; dy4 = stack[7]; dx5 = stack[8]; dy5 = stack[9]; dx6 = stack[10]; dy6 = stack[11]; SetCurveTo(dx1, dy1, dx2, dy2, dx3, dy3); instruction = 0x23; return(true); case 0x24: // hflex1 dx1 = stack[0]; dy1 = stack[1]; dx2 = stack[2]; dy2 = stack[3]; dx3 = stack[4]; dx4 = stack[5]; dx5 = stack[6]; dy5 = stack[7]; dx6 = stack[8]; SetCurveTo(dx1, dy1, dx2, dy2, dx3, 0); instruction = 0x24; return(true); case 0x25: // flex1 dx1 = stack[0]; dy1 = stack[1]; dx2 = stack[2]; dy2 = stack[3]; dx3 = stack[4]; dy3 = stack[5]; dx4 = stack[6]; dy4 = stack[7]; dx5 = stack[8]; dy5 = stack[9]; dx6 = dy6 = stack[10]; double dx = dx1 + dx2 + dx3 + dx4 + dx5; double dy = dy1 + dy2 + dy3 + dy4 + dy5; if (Math.Abs(dx) > Math.Abs(dy)) { dy6 = -dy; } else { dx6 = -dx; } SetCurveTo(dx1, dy1, dx2, dy2, dx3, dy3); instruction = 0x25; return(true); default: throw new InvalidOperationException(Resources.GetMessage(Resources.Key.InvalidFontFormat)); } } default: if (b0 != 255u && b0 != 28 && (b0 < 32 || b0 > 254)) { throw new InvalidOperationException(Resources.GetMessage(Resources.Key.InvalidFontFormat)); } if (stackIndex >= 48) { throw new InvalidOperationException(Resources.GetMessage(Resources.Key.OperandStackOverflow)); } if (b0 == 255u) { stack[stackIndex++] = openType.ReadInt32(charString, cursor) / 0x10000; cursor += 4; } else { uint c = cursor - 1; stack[stackIndex++] = openType.ReadInt32(charString, ref c); cursor = c; } clearStack = false; break; } if (clearStack) { stackIndex = 0; } } if (charString.length == 0) { return(false); } if (!exit) { throw new InvalidOperationException(Resources.GetMessage(Resources.Key.InvalidFontFormat)); } } }